@cqsjjb/jjb-react-admin-component 3.3.1-beta.6 → 3.3.1-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/BMap/index.js ADDED
@@ -0,0 +1,167 @@
1
+ import React, { useEffect, useRef, useState, useCallback } from 'react';
2
+ import { Button, Col, message, Modal, Result, Row } from 'antd';
3
+ import './index.less';
4
+ const _B_MAP_SEARCH_ = '_B_MAP_SEARCH_';
5
+ const _B_MAP_DEFAULT_POINT_ = {
6
+ lng: 116.404,
7
+ lat: 39.915
8
+ };
9
+ const BMap = ({
10
+ lng: propLng,
11
+ lat: propLat,
12
+ title = '百度地图',
13
+ width = 700,
14
+ onOk,
15
+ onCancel
16
+ }) => {
17
+ const [lng, setLng] = useState(_B_MAP_DEFAULT_POINT_.lng);
18
+ const [lat, setLat] = useState(_B_MAP_DEFAULT_POINT_.lat);
19
+ const GL = useRef(null);
20
+ const mapRef = useRef(null);
21
+
22
+ /** 初始化地图 */
23
+ useEffect(() => {
24
+ if (typeof window.BMapGL === 'undefined') {
25
+ message.error('未导入百度地图文件,生成地图失败!').then(() => null);
26
+ return;
27
+ }
28
+ const initLng = propLng || _B_MAP_DEFAULT_POINT_.lng;
29
+ const initLat = propLat || _B_MAP_DEFAULT_POINT_.lat;
30
+ setLng(initLng);
31
+ setLat(initLat);
32
+ const point = new window.BMapGL.Point(initLng, initLat);
33
+ const map = new window.BMapGL.Map(GL.current);
34
+ mapRef.current = map;
35
+ map.centerAndZoom(point, 18);
36
+ map.enableScrollWheelZoom(true);
37
+ map.addControl(new window.BMapGL.ScaleControl());
38
+ map.addControl(new window.BMapGL.ZoomControl());
39
+ map.addControl(new window.BMapGL.NavigationControl3D());
40
+ map.addControl(new window.BMapGL.CityListControl({
41
+ anchor: window.BMAP_ANCHOR_TOP_LEFT,
42
+ offset: new window.BMapGL.Size(10, 10),
43
+ onChangeSuccess: e => {
44
+ map.clearOverlays();
45
+ setLng(e.point.lng);
46
+ setLat(e.point.lat);
47
+ const p = new window.BMapGL.Point(e.point.lng, e.point.lat);
48
+ const marker = new window.BMapGL.Marker(p);
49
+ map.addOverlay(marker);
50
+ }
51
+ }));
52
+ const locationControl = new window.BMapGL.LocationControl({
53
+ anchor: window.BMAP_ANCHOR_BOTTOM_LEFT,
54
+ offset: new window.BMapGL.Size(20, 20)
55
+ });
56
+ locationControl.addEventListener('locationError', () => message.error('未知原因,定位失败!'));
57
+ map.addControl(locationControl);
58
+ const marker = new window.BMapGL.Marker(point);
59
+ map.addOverlay(marker);
60
+ map.addEventListener('click', e => {
61
+ map.clearOverlays();
62
+ setLng(e.latlng.lng);
63
+ setLat(e.latlng.lat);
64
+ const p = new window.BMapGL.Point(e.latlng.lng, e.latlng.lat);
65
+ const marker = new window.BMapGL.Marker(p);
66
+ map.addOverlay(marker);
67
+ });
68
+ setTimeout(() => {
69
+ const autoComplete = new window.BMapGL.Autocomplete({
70
+ input: _B_MAP_SEARCH_,
71
+ location: map
72
+ });
73
+ let myValue;
74
+ autoComplete.addEventListener('onconfirm', e => {
75
+ const value = e.item.value;
76
+ myValue = value.province + value.city + value.district + value.street + value.business;
77
+ setPlace();
78
+ });
79
+ function setPlace() {
80
+ const local = new window.BMapGL.LocalSearch(map, {
81
+ onSearchComplete: myFun
82
+ });
83
+ map.clearOverlays();
84
+ function myFun() {
85
+ const pp = local.getResults().getPoi(0).point;
86
+ setLng(pp.lng);
87
+ setLat(pp.lat);
88
+ map.centerAndZoom(pp, 18);
89
+ map.addOverlay(new window.BMapGL.Marker(pp));
90
+ }
91
+ local.search(myValue);
92
+ }
93
+ }, 500);
94
+ }, [propLng, propLat]);
95
+
96
+ /** 重置地图 */
97
+ const onResetMap = useCallback(() => {
98
+ if (!mapRef.current) return;
99
+ const map = mapRef.current;
100
+ map.clearOverlays();
101
+ setLng(_B_MAP_DEFAULT_POINT_.lng);
102
+ setLat(_B_MAP_DEFAULT_POINT_.lat);
103
+ const point = new window.BMapGL.Point(_B_MAP_DEFAULT_POINT_.lng, _B_MAP_DEFAULT_POINT_.lat);
104
+ const marker = new window.BMapGL.Marker(point);
105
+ map.centerAndZoom(_B_MAP_DEFAULT_POINT_, 18);
106
+ map.addOverlay(marker);
107
+ }, []);
108
+
109
+ /** 确认操作 */
110
+ const handleOk = useCallback(() => {
111
+ const map = mapRef.current;
112
+ if (!map) return;
113
+ const point = new window.BMapGL.Point(lng, lat);
114
+ const geocoder = new window.BMapGL.Geocoder();
115
+ geocoder.getLocation(point, (rs = {}) => {
116
+ const comp = rs?.addressComponents;
117
+ onOk && onOk({
118
+ lng,
119
+ lat,
120
+ comp,
121
+ compText: comp && [comp.province, comp.city, comp.district, comp.street, comp.streetNumber].join('') || undefined
122
+ });
123
+ });
124
+ }, [lng, lat, onOk]);
125
+ const hasMapScript = typeof window.BMapGL !== 'undefined';
126
+ return /*#__PURE__*/React.createElement(Modal, {
127
+ open: true,
128
+ destroyOnClose: true,
129
+ title: title,
130
+ width: width,
131
+ footer: hasMapScript && /*#__PURE__*/React.createElement(Row, {
132
+ align: "middle",
133
+ justify: "space-between"
134
+ }, /*#__PURE__*/React.createElement(Col, null, "\u5F53\u524D\u5750\u6807\uFF1A", [lng, lat].join('-')), /*#__PURE__*/React.createElement(Col, null, /*#__PURE__*/React.createElement(Button, {
135
+ ghost: true,
136
+ type: "primary",
137
+ style: {
138
+ marginRight: 12
139
+ },
140
+ onClick: onResetMap
141
+ }, "\u91CD\u7F6E\u5730\u56FE"), /*#__PURE__*/React.createElement(Button, {
142
+ type: "primary",
143
+ onClick: handleOk
144
+ }, "\u786E\u8BA4\u5750\u6807"))),
145
+ maskClosable: false,
146
+ onCancel: () => onCancel && onCancel()
147
+ }, hasMapScript ? /*#__PURE__*/React.createElement("div", {
148
+ style: {
149
+ position: 'relative'
150
+ }
151
+ }, /*#__PURE__*/React.createElement("div", {
152
+ ref: GL,
153
+ style: {
154
+ height: 500,
155
+ userSelect: 'none'
156
+ }
157
+ }), /*#__PURE__*/React.createElement("input", {
158
+ id: _B_MAP_SEARCH_,
159
+ type: "text",
160
+ maxLength: 30,
161
+ placeholder: "\u8BF7\u8F93\u5165\u5173\u952E\u5B57\u67E5\u8BE2"
162
+ })) : /*#__PURE__*/React.createElement(Result, {
163
+ status: "error",
164
+ title: "\u52A0\u8F7D\u5730\u56FE\u5931\u8D25\uFF0C\u7F3A\u5C11\u5FC5\u8981\u7684\u6587\u4EF6\uFF01"
165
+ }));
166
+ };
167
+ export default BMap;
@@ -0,0 +1,65 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import { Input as OriginInput, Select as OriginSelect, Cascader as OriginCascader, DatePicker as OriginDatePicker, TreeSelect as OriginTreeSelect } from 'antd';
4
+
5
+ /**
6
+ * 通用包裹组件
7
+ * @param {*} WrappedComponent antd 原生组件
8
+ * @param {*} extraProps 额外的透传配置
9
+ */
10
+ function withLabel(WrappedComponent, extraProps = {}) {
11
+ return function Wrapper(props) {
12
+ const {
13
+ label,
14
+ onChange,
15
+ ...restProps
16
+ } = props;
17
+ const handleChange = (val, ...args) => {
18
+ if (onChange) {
19
+ // 统一处理空字符串 -> undefined
20
+ onChange(val === '' ? undefined : val, ...args);
21
+ }
22
+ };
23
+ return /*#__PURE__*/React.createElement(WrappedComponent, _extends({
24
+ style: {
25
+ width: '100%'
26
+ },
27
+ prefix: label
28
+ }, extraProps, restProps, {
29
+ onChange: handleChange
30
+ }));
31
+ };
32
+ }
33
+
34
+ // ============ 输入类 ============
35
+ const Input = withLabel(OriginInput);
36
+
37
+ // ============ 选择类 ============
38
+ const Select = withLabel(OriginSelect, {
39
+ maxTagCount: 3
40
+ });
41
+ const Cascader = withLabel(OriginCascader, {
42
+ maxTagCount: 3
43
+ });
44
+ const TreeSelect = withLabel(OriginTreeSelect, {
45
+ showSearch: true,
46
+ allowClear: true,
47
+ showCheckedStrategy: OriginTreeSelect.SHOW_PARENT,
48
+ treeNodeFilterProp: 'title'
49
+ });
50
+
51
+ // ============ 日期类 ============
52
+ const DatePicker = withLabel(OriginDatePicker);
53
+ DatePicker.RangePicker = withLabel(OriginDatePicker.RangePicker);
54
+ DatePicker.TimePicker = withLabel(OriginDatePicker.TimePicker);
55
+ DatePicker.WeekPicker = withLabel(OriginDatePicker.WeekPicker);
56
+ DatePicker.MonthPicker = withLabel(OriginDatePicker.MonthPicker);
57
+ DatePicker.QuarterPicker = withLabel(OriginDatePicker.QuarterPicker);
58
+ DatePicker.YearPicker = withLabel(OriginDatePicker.YearPicker);
59
+ export default {
60
+ Input,
61
+ Select,
62
+ Cascader,
63
+ TreeSelect,
64
+ DatePicker
65
+ };
@@ -0,0 +1,38 @@
1
+ @com-prefix-cls: if(isdefined(@ant-prefix), @ant-prefix, ant);
2
+
3
+ .@{com-prefix-cls}-form-item-control-label-wrapper {
4
+ .@{com-prefix-cls}-form-item-control-label-span {
5
+ border: 1px solid #d9d9d9;
6
+ height: 32px;
7
+ line-height: 30px;
8
+ box-sizing: border-box;
9
+ margin-right: -1px;
10
+ padding: 0 2px 0 8px;
11
+ border-top-left-radius: 4px;
12
+ border-bottom-left-radius: 4px;
13
+ white-space: nowrap;
14
+ }
15
+
16
+ &.@{com-prefix-cls}-form-item-control-label-has {
17
+ .@{com-prefix-cls}-select-selector, .@{com-prefix-cls}-picker, .@{com-prefix-cls}-input, .@{com-prefix-cls}-input-affix-wrapper {
18
+ border-top-left-radius: 0;
19
+ border-bottom-left-radius: 0;
20
+ border-left-color: transparent !important;
21
+ &:hover, &:focus, &:focus-within{
22
+ border-left-color: @colorPrimary !important;
23
+ }
24
+ }
25
+ }
26
+
27
+ &-default {
28
+ .@{com-prefix-cls}-form-item-control-label-span {
29
+ border-color: #d9d9d9;
30
+ }
31
+ }
32
+
33
+ &-dark {
34
+ .@{com-prefix-cls}-form-item-control-label-span {
35
+ border-color: #424242;
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,310 @@
1
+ import '@wangeditor-next/editor/dist/css/style.css';
2
+ import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
3
+ import { message } from 'antd';
4
+ import { http, tools } from '@cqsjjb/jjb-common-lib';
5
+ import { createEditor, createToolbar } from '@wangeditor-next/editor';
6
+
7
+ /**
8
+ * 工具函数:标准化 HTML 内容为空值
9
+ */
10
+ function normalizeEmptyHtml(html) {
11
+ if (!html) return '';
12
+ const cleaned = html.replace(/\s+/g, '').toLowerCase();
13
+ return cleaned === '<p><br></p>' || cleaned === '<p></p>' || cleaned === '' ? '' : html;
14
+ }
15
+
16
+ /**
17
+ * 校验上传文件类型和大小
18
+ */
19
+ function validateFile(file, {
20
+ validTypes,
21
+ validExts,
22
+ maxSize,
23
+ typeName
24
+ }) {
25
+ const ext = file.name.split('.').pop().toLowerCase();
26
+ if (!validTypes.includes(file.type) && !validExts.includes(ext)) {
27
+ message.error(`只能上传${typeName}文件(${validExts.join(', ')})`);
28
+ return false;
29
+ }
30
+ if (file.size > maxSize) {
31
+ message.error(`${typeName}大小不能超过 ${maxSize / 1024 / 1024}MB`);
32
+ return false;
33
+ }
34
+ return true;
35
+ }
36
+
37
+ /**
38
+ * 通用上传函数
39
+ */
40
+ async function handleUpload(file, insertFn, options) {
41
+ const {
42
+ typeName,
43
+ validTypes,
44
+ validExts,
45
+ maxSize,
46
+ uploadServer,
47
+ uploadFileName,
48
+ uploadHeaders,
49
+ application,
50
+ uploadCustomRequest
51
+ } = options;
52
+ try {
53
+ if (!validateFile(file, {
54
+ validTypes,
55
+ validExts,
56
+ maxSize,
57
+ typeName
58
+ })) {
59
+ return;
60
+ }
61
+
62
+ // 自定义上传
63
+ if (typeof uploadCustomRequest === 'function') {
64
+ const url = await uploadCustomRequest(file);
65
+ insertFn(url, file.name);
66
+ return;
67
+ }
68
+
69
+ // 默认上传
70
+ const formData = new FormData();
71
+ formData.append(uploadFileName, file);
72
+ const resp = await fetch(uploadServer, {
73
+ method: 'POST',
74
+ headers: {
75
+ ...uploadHeaders,
76
+ ...(application ? {
77
+ tenantCode: application.tenantCode
78
+ } : {})
79
+ },
80
+ body: formData
81
+ });
82
+ const res = await resp.json();
83
+ if (res?.data?.fileUrl) {
84
+ insertFn(res.data.fileUrl, file.name);
85
+ } else if (Array.isArray(res?.data)) {
86
+ res.data.forEach(url => insertFn(url, file.name));
87
+ } else {
88
+ message.error(res?.respDesc || `${typeName}上传失败`);
89
+ }
90
+ } catch (e) {
91
+ console.error(e);
92
+ message.error(`${typeName}上传失败`);
93
+ }
94
+ }
95
+ const RCEditor = /*#__PURE__*/forwardRef(function RCEditor(props, ref) {
96
+ const {
97
+ value,
98
+ bordered = true,
99
+ mode = 'default',
100
+ height = 300,
101
+ disabled = false,
102
+ zIndex = 1000,
103
+ uploadUrl = `${window.process.env.app.API_HOST}/attachment/files/upload-speed-simple`,
104
+ uploadFileName = 'file',
105
+ uploadHeaders = {},
106
+ uploadCustomRequest,
107
+ placeholder = '请输入...',
108
+ uploadImageFileSize = 5 * 1024 * 1024,
109
+ uploadVideoFileSize = 50 * 1024 * 1024,
110
+ borderStyle = 'solid',
111
+ borderColor = '#e8e8e8',
112
+ borderWidth = 1,
113
+ borderRadius = 2,
114
+ onBlur = tools.noop,
115
+ onFocus = tools.noop,
116
+ onChange = tools.noop
117
+ } = props;
118
+
119
+ // 编辑器
120
+ const editorRef = useRef(null);
121
+ // 工具栏
122
+ const toolbarRef = useRef(null);
123
+ // 编辑器实例
124
+ const editorInstanceRef = useRef(null);
125
+ // 最后一次的html
126
+ const lastHtmlRef = useRef('');
127
+ // 是否是第一次聚焦
128
+ const isFirstFocusRef = useRef(true);
129
+ // 应用配置
130
+ const appConfig = tools.toObject(window.process?.env?.app);
131
+
132
+ // 上传地址
133
+ const uploadServer = useMemo(() => {
134
+ if (!appConfig) return uploadUrl;
135
+ return http.HTTP_URL_REG.test(uploadUrl) ? uploadUrl : `${appConfig.API_HOST}${uploadUrl}`;
136
+ }, [appConfig, uploadUrl]);
137
+
138
+ // 初始化编辑器
139
+ useEffect(() => {
140
+ if (!editorRef.current) return;
141
+ const editor = createEditor({
142
+ selector: editorRef.current,
143
+ config: {
144
+ placeholder,
145
+ readOnly: disabled,
146
+ onChange(editor) {
147
+ // 获取html
148
+ let html = editor.getHtml();
149
+ // 标准化html
150
+ html = normalizeEmptyHtml(html);
151
+ // 存储最后一次的html
152
+ lastHtmlRef.current = html;
153
+
154
+ // 如果不是第一次聚焦,并且有onChange函数,则调用onChange函数
155
+ if (!isFirstFocusRef.current && tools.isFunction(onChange)) {
156
+ onChange(html);
157
+ }
158
+ },
159
+ onFocus: () => {
160
+ // 如果是第一次聚焦,则设置为不是第一次聚焦
161
+ if (isFirstFocusRef.current) {
162
+ isFirstFocusRef.current = false;
163
+ return;
164
+ }
165
+ // 调用onFocus函数
166
+ tools.isFunction(onFocus) && onFocus();
167
+ },
168
+ onBlur: () => tools.isFunction(onBlur) && onBlur(),
169
+ // 菜单配置
170
+ MENU_CONF: {
171
+ uploadImage: {
172
+ server: uploadServer,
173
+ fieldName: uploadFileName,
174
+ maxFileSize: uploadImageFileSize,
175
+ headers: {
176
+ ...uploadHeaders,
177
+ ...(appConfig ? {
178
+ tenantCode: appConfig.tenantCode
179
+ } : {})
180
+ },
181
+ timeout: 60000,
182
+ customUpload: async (file, insertFn) => {
183
+ await handleUpload(file, insertFn, {
184
+ typeName: '图片',
185
+ validTypes: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp'],
186
+ validExts: ['png', 'jpg', 'jpeg', 'gif', 'webp'],
187
+ maxSize: uploadImageFileSize,
188
+ uploadServer,
189
+ uploadFileName,
190
+ uploadHeaders,
191
+ appConfig,
192
+ uploadCustomRequest
193
+ });
194
+ }
195
+ },
196
+ uploadVideo: {
197
+ server: uploadServer,
198
+ fieldName: uploadFileName,
199
+ maxFileSize: uploadVideoFileSize,
200
+ headers: {
201
+ ...uploadHeaders,
202
+ ...(appConfig ? {
203
+ tenantCode: appConfig.tenantCode
204
+ } : {})
205
+ },
206
+ timeout: 120000,
207
+ customUpload: async (file, insertFn) => {
208
+ await handleUpload(file, insertFn, {
209
+ typeName: '视频',
210
+ validTypes: ['video/mp4', 'video/webm', 'video/ogg', 'video/mkv'],
211
+ validExts: ['mp4', 'webm', 'ogg', 'mkv'],
212
+ maxSize: uploadVideoFileSize,
213
+ uploadServer,
214
+ uploadFileName,
215
+ uploadHeaders,
216
+ appConfig,
217
+ uploadCustomRequest
218
+ });
219
+ }
220
+ }
221
+ }
222
+ },
223
+ mode
224
+ });
225
+ createToolbar({
226
+ editor,
227
+ selector: toolbarRef.current,
228
+ config: {},
229
+ mode
230
+ });
231
+
232
+ // 初始化内容
233
+ const initialHtml = normalizeEmptyHtml(value || '');
234
+ // 设置html
235
+ editor.setHtml(initialHtml);
236
+ // 存储最后一次的html
237
+ lastHtmlRef.current = initialHtml;
238
+ // 禁用编辑器
239
+ if (disabled) editor.disable();
240
+ // 存储编辑器实例
241
+ editorInstanceRef.current = editor;
242
+ // 销毁编辑器
243
+ return () => {
244
+ try {
245
+ editor.destroy();
246
+ } catch (e) {}
247
+ editorInstanceRef.current = null;
248
+ };
249
+ }, []);
250
+
251
+ // 受控 value
252
+ useEffect(() => {
253
+ // 获取编辑器实例
254
+ const editor = editorInstanceRef.current;
255
+ if (!editor) return;
256
+ // 标准化html
257
+ const safeHtml = normalizeEmptyHtml(value || '');
258
+ if (safeHtml !== lastHtmlRef.current) {
259
+ editor.setHtml(safeHtml);
260
+ // 存储最后一次的html
261
+ lastHtmlRef.current = safeHtml;
262
+ }
263
+ }, [value]);
264
+
265
+ // disabled 切换
266
+ useEffect(() => {
267
+ const editor = editorInstanceRef.current;
268
+ if (!editor) return;
269
+ // 禁用编辑器
270
+ if (disabled) editor.disable();
271
+ // 启用编辑器
272
+ else editor.enable();
273
+ }, [disabled]);
274
+ // 暴露编辑器实例
275
+ useImperativeHandle(ref, () => ({
276
+ // 获取编辑器实例
277
+ getEditorInstance: () => editorInstanceRef.current,
278
+ // 获取html
279
+ getHtml: () => normalizeEmptyHtml(editorInstanceRef.current?.getHtml?.() || ''),
280
+ // 设置html
281
+ setHtml: html => {
282
+ if (!editorInstanceRef.current) return;
283
+ const safeHtml = normalizeEmptyHtml(html || '');
284
+ editorInstanceRef.current.setHtml(safeHtml);
285
+ lastHtmlRef.current = safeHtml;
286
+ },
287
+ // 获取纯文本
288
+ getPlainText: () => editorInstanceRef.current?.getText?.() || ''
289
+ }));
290
+ return /*#__PURE__*/React.createElement("div", {
291
+ style: {
292
+ zIndex,
293
+ border: bordered ? `${borderWidth}px ${borderStyle} ${borderColor}` : 'none',
294
+ overflow: 'hidden',
295
+ borderRadius
296
+ }
297
+ }, /*#__PURE__*/React.createElement("div", {
298
+ ref: toolbarRef,
299
+ style: {
300
+ borderBottom: bordered ? `${borderWidth}px ${borderStyle} ${borderColor}` : 'none'
301
+ }
302
+ }), /*#__PURE__*/React.createElement("div", {
303
+ ref: editorRef,
304
+ style: {
305
+ height,
306
+ overflowY: 'auto'
307
+ }
308
+ }));
309
+ });
310
+ export default RCEditor;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { Result } from 'antd';
3
+ export default class ErrorBoundary extends React.Component {
4
+ state = {
5
+ hasError: false,
6
+ errorInfo: '',
7
+ errorStack: undefined
8
+ };
9
+ componentDidCatch(error, info) {
10
+ this.setState({
11
+ hasError: true,
12
+ errorInfo: error.message,
13
+ errorStack: info.componentStack
14
+ });
15
+ }
16
+ render() {
17
+ if (this.state.hasError) {
18
+ return /*#__PURE__*/React.createElement(Result, {
19
+ status: "error",
20
+ title: "\u62B1\u6B49\uFF0C\u5E94\u7528\u5185\u90E8\u53D1\u751F\u5F02\u5E38\u9519\u8BEF\u3002",
21
+ subTitle: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", null, this.state.errorInfo), /*#__PURE__*/React.createElement("div", {
22
+ style: {
23
+ width: 700,
24
+ display: 'inline-block',
25
+ overflow: 'auto',
26
+ maxHeight: 400,
27
+ textAlign: 'left',
28
+ whiteSpace: 'pre-line'
29
+ }
30
+ }, this.state.errorStack))
31
+ });
32
+ }
33
+ return this.props.children;
34
+ }
35
+ }