dumi 2.3.0-alpha.8 → 2.3.0-beta.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 (87) hide show
  1. package/compiled/crates/swc_plugin_react_demo.wasm +0 -0
  2. package/dist/assetParsers/block.d.ts +7 -1
  3. package/dist/assetParsers/block.js +14 -6
  4. package/dist/client/pages/Demo/index.js +19 -5
  5. package/dist/client/pages/Loading.d.ts +1 -0
  6. package/dist/client/pages/Loading.js +2 -0
  7. package/dist/client/theme-api/DumiDemo/index.js +4 -4
  8. package/dist/client/theme-api/{context/index.d.ts → context.d.ts} +4 -12
  9. package/dist/client/theme-api/context.js +16 -0
  10. package/dist/client/theme-api/index.d.ts +2 -3
  11. package/dist/client/theme-api/index.js +2 -3
  12. package/dist/client/theme-api/types.d.ts +6 -4
  13. package/dist/client/theme-api/useLiveDemo.d.ts +6 -0
  14. package/dist/client/theme-api/useLiveDemo.js +70 -0
  15. package/dist/client/theme-api/useRouteMeta.js +73 -20
  16. package/dist/client/theme-api/useSiteSearch/index.d.ts +1 -1
  17. package/dist/client/theme-api/useSiteSearch/index.js +20 -48
  18. package/dist/client/theme-api/useSiteSearch/useSearchData.d.ts +9 -6
  19. package/dist/client/theme-api/useSiteSearch/useSearchData.js +55 -60
  20. package/dist/client/theme-api/useTabMeta.js +1 -1
  21. package/dist/client/theme-api/utils.d.ts +10 -0
  22. package/dist/client/theme-api/utils.js +25 -0
  23. package/dist/constants.d.ts +0 -1
  24. package/dist/constants.js +0 -4
  25. package/dist/features/compile/index.js +11 -18
  26. package/dist/features/exports.js +3 -3
  27. package/dist/features/meta.js +12 -31
  28. package/dist/features/theme/index.js +8 -5
  29. package/dist/loaders/markdown/index.d.ts +1 -7
  30. package/dist/loaders/markdown/index.js +39 -113
  31. package/dist/loaders/markdown/transformer/index.d.ts +1 -1
  32. package/dist/loaders/markdown/transformer/rehypeDemo.js +8 -2
  33. package/dist/loaders/page/index.js +1 -3
  34. package/dist/preset.js +1 -2
  35. package/dist/templates/ContextWrapper.ts.tpl +2 -10
  36. package/dist/templates/meta/exports.ts.tpl +160 -0
  37. package/dist/templates/meta/index.ts.tpl +26 -0
  38. package/dist/templates/{meta-runtime.ts.tpl → meta/runtime.ts.tpl} +11 -22
  39. package/dist/types.d.ts +2 -2
  40. package/index.d.ts +1 -4
  41. package/package.json +2 -1
  42. package/theme-default/builtins/Previewer/index.d.ts +1 -1
  43. package/theme-default/builtins/Previewer/index.js +35 -33
  44. package/theme-default/builtins/Previewer/index.less +34 -0
  45. package/theme-default/builtins/SourceCode/index.d.ts +2 -1
  46. package/theme-default/builtins/SourceCode/index.js +3 -3
  47. package/theme-default/builtins/SourceCode/index.less +1 -0
  48. package/theme-default/locales/en-US.json +2 -0
  49. package/theme-default/locales/zh-CN.json +2 -0
  50. package/theme-default/slots/Loading/index.d.ts +5 -0
  51. package/theme-default/slots/Loading/index.js +18 -0
  52. package/theme-default/slots/Loading/index.less +20 -0
  53. package/theme-default/slots/PreviewerActions/index.d.ts +7 -1
  54. package/theme-default/slots/PreviewerActions/index.js +49 -6
  55. package/theme-default/slots/PreviewerActions/index.less +58 -14
  56. package/theme-default/slots/SearchBar/Mask.js +1 -1
  57. package/theme-default/slots/SearchBar/index.js +1 -1
  58. package/theme-default/slots/SearchResult/index.js +1 -10
  59. package/theme-default/slots/SourceCodeEditor/index.d.ts +18 -0
  60. package/theme-default/slots/SourceCodeEditor/index.js +106 -0
  61. package/theme-default/slots/SourceCodeEditor/index.less +45 -0
  62. package/dist/client/theme-api/context/index.js +0 -50
  63. package/dist/client/theme-api/context/use.d.ts +0 -10
  64. package/dist/client/theme-api/context/use.js +0 -25
  65. package/dist/client/theme-api/evalCode.d.ts +0 -2
  66. package/dist/client/theme-api/evalCode.js +0 -17
  67. package/dist/client/theme-api/live/LiveProvider.d.ts +0 -16
  68. package/dist/client/theme-api/live/LiveProvider.js +0 -74
  69. package/dist/client/theme-api/live/index.d.ts +0 -3
  70. package/dist/client/theme-api/live/index.js +0 -3
  71. package/dist/client/theme-api/live/useDemoScopes.d.ts +0 -2
  72. package/dist/client/theme-api/live/useDemoScopes.js +0 -15
  73. package/dist/features/live.d.ts +0 -3
  74. package/dist/features/live.js +0 -74
  75. package/dist/templates/live/demo-scopes.ts.tpl +0 -22
  76. package/dist/templates/live/disabled.ts.tpl +0 -1
  77. package/dist/templates/meta-demos.ts.tpl +0 -34
  78. package/dist/templates/meta-frontmatter.ts.tpl +0 -9
  79. package/dist/templates/meta-route.ts.tpl +0 -43
  80. package/dist/templates/meta-search.ts.tpl +0 -41
  81. package/theme-default/slots/LiveDemo/index.d.ts +0 -3
  82. package/theme-default/slots/LiveDemo/index.js +0 -8
  83. package/theme-default/slots/LiveEditor/index.d.ts +0 -4
  84. package/theme-default/slots/LiveEditor/index.js +0 -20
  85. package/theme-default/slots/LiveError/index.d.ts +0 -4
  86. package/theme-default/slots/LiveError/index.js +0 -15
  87. package/theme-default/slots/LiveError/index.less +0 -22
@@ -1,27 +1,32 @@
1
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
1
3
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
4
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
5
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
6
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
7
  function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
6
8
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
- function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
8
- function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
9
+ import { ReactComponent as IconError } from '@ant-design/icons-svg/inline-svg/filled/close-circle.svg';
9
10
  import classnames from 'classnames';
10
- import { LiveContext, LiveProvider, isLiveEnabled, useLocation } from 'dumi';
11
- import LiveDemo from 'dumi/theme/slots/LiveDemo';
12
- import LiveEditor from 'dumi/theme/slots/LiveEditor';
13
- import LiveError from 'dumi/theme/slots/LiveError';
11
+ import { useLiveDemo, useLocation } from 'dumi';
14
12
  import PreviewerActions from 'dumi/theme/slots/PreviewerActions';
15
- import React, { useContext, useRef } from 'react';
13
+ import React, { useRef, useState } from 'react';
16
14
  import "./index.less";
17
- var InternalPreviewer = function InternalPreviewer(props) {
15
+ var Previewer = function Previewer(props) {
18
16
  var _demoContainer$curren;
19
17
  var demoContainer = useRef(null);
20
18
  var _useLocation = useLocation(),
21
19
  hash = _useLocation.hash;
22
20
  var link = "#".concat(props.asset.id);
23
- var _useContext = useContext(LiveContext),
24
- enabled = _useContext.enabled;
21
+ var _useLiveDemo = useLiveDemo(props.asset.id),
22
+ liveDemoNode = _useLiveDemo.node,
23
+ liveDemoError = _useLiveDemo.error,
24
+ setLiveDemoSources = _useLiveDemo.setSources;
25
+ var _useState = useState(null),
26
+ _useState2 = _slicedToArray(_useState, 2),
27
+ editorError = _useState2[0],
28
+ setEditorError = _useState2[1];
29
+ var combineError = liveDemoError || editorError;
25
30
  return /*#__PURE__*/React.createElement("div", {
26
31
  id: props.asset.id,
27
32
  className: classnames('dumi-default-previewer', props.className),
@@ -42,7 +47,9 @@ var InternalPreviewer = function InternalPreviewer(props) {
42
47
  height: Number(props.iframe)
43
48
  } : {},
44
49
  src: props.demoUrl
45
- }) : enabled ? /*#__PURE__*/React.createElement(LiveDemo, null) : props.children), /*#__PURE__*/React.createElement("div", {
50
+ }) : liveDemoNode || props.children), combineError && /*#__PURE__*/React.createElement("div", {
51
+ className: "dumi-default-previewer-demo-error"
52
+ }, /*#__PURE__*/React.createElement(IconError, null), combineError.toString()), /*#__PURE__*/React.createElement("div", {
46
53
  className: "dumi-default-previewer-meta"
47
54
  }, (props.title || props.debug) && /*#__PURE__*/React.createElement("div", {
48
55
  className: "dumi-default-previewer-desc"
@@ -54,28 +61,23 @@ var InternalPreviewer = function InternalPreviewer(props) {
54
61
  __html: props.description
55
62
  }
56
63
  })), /*#__PURE__*/React.createElement(PreviewerActions, _extends({}, props, {
57
- demoContainer: props.iframe ? (_demoContainer$curren = demoContainer.current) === null || _demoContainer$curren === void 0 ? void 0 : _demoContainer$curren.firstElementChild : demoContainer.current,
58
- sourceCode: enabled ? /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(LiveEditor, null), /*#__PURE__*/React.createElement(LiveError, null)) : null
64
+ onSourcesTranspile: function onSourcesTranspile(_ref) {
65
+ var err = _ref.err,
66
+ sources = _ref.sources;
67
+ if (err) {
68
+ setEditorError(err);
69
+ } else {
70
+ setEditorError(null);
71
+ setLiveDemoSources(sources);
72
+ if (props.iframe) {
73
+ demoContainer.current.querySelector('iframe').contentWindow.postMessage({
74
+ type: 'dumi.liveDemo.setSources',
75
+ value: sources
76
+ });
77
+ }
78
+ }
79
+ },
80
+ demoContainer: props.iframe ? (_demoContainer$curren = demoContainer.current) === null || _demoContainer$curren === void 0 ? void 0 : _demoContainer$curren.firstElementChild : demoContainer.current
59
81
  }))));
60
82
  };
61
- var Previewer = function Previewer(props) {
62
- var children = /*#__PURE__*/React.createElement(InternalPreviewer, props);
63
-
64
- // Only Single File
65
- if (!isLiveEnabled() || props.live === false || Object.entries(props.asset.dependencies).filter(function (_ref) {
66
- var _ref2 = _slicedToArray(_ref, 2),
67
- type = _ref2[1].type;
68
- return type === 'FILE';
69
- }).length > 1) {
70
- return children;
71
- }
72
- return /*#__PURE__*/React.createElement(LiveProvider, {
73
- initialCode: Object.entries(props.asset.dependencies).filter(function (_ref3) {
74
- var _ref4 = _slicedToArray(_ref3, 2),
75
- type = _ref4[1].type;
76
- return type === 'FILE';
77
- })[0][1].value,
78
- demoId: props.asset.id
79
- }, children);
80
- };
81
83
  export default Previewer;
@@ -78,6 +78,40 @@
78
78
  }
79
79
  }
80
80
 
81
+ &-demo-error {
82
+ @height: 30px;
83
+ @color: darken(desaturate(@c-error, 20%), 1%);
84
+
85
+ margin-top: -@height;
86
+ height: @height;
87
+ padding: 0 24px;
88
+ line-height: @height;
89
+ color: @color;
90
+ font-size: 13px;
91
+ white-space: nowrap;
92
+ text-overflow: ellipsis;
93
+ background: lighten(@c-error, 51%);
94
+ box-sizing: border-box;
95
+
96
+ @{dark-selector} & {
97
+ @color: lighten(desaturate(@c-error, 20%), 5%);
98
+
99
+ color: @color;
100
+ background: darken(@c-error-dark, 22%);
101
+
102
+ > svg {
103
+ fill: @color;
104
+ }
105
+ }
106
+
107
+ > svg {
108
+ width: 14px;
109
+ padding-right: 4px;
110
+ fill: @c-error;
111
+ vertical-align: -0.14em;
112
+ }
113
+ }
114
+
81
115
  &-meta {
82
116
  border-top: 1px solid @c-border-light;
83
117
 
@@ -1,11 +1,12 @@
1
1
  import { type Language } from 'prism-react-renderer';
2
2
  import 'prism-themes/themes/prism-one-light.css';
3
- import { type FC } from 'react';
3
+ import { type FC, type ReactNode } from 'react';
4
4
  import './index.less';
5
5
  interface SourceCodeProps {
6
6
  children: string;
7
7
  lang: Language;
8
8
  highlightLines?: number[];
9
+ extra?: ReactNode;
9
10
  }
10
11
  declare const SourceCode: FC<SourceCodeProps>;
11
12
  export default SourceCode;
@@ -11,7 +11,7 @@ import classNames from 'classnames';
11
11
  import { useSiteData } from 'dumi';
12
12
  import Highlight, { defaultProps } from 'prism-react-renderer';
13
13
  import 'prism-themes/themes/prism-one-light.css';
14
- import React, { useRef, useState, useEffect } from 'react';
14
+ import React, { useEffect, useRef, useState } from 'react';
15
15
  import { CopyToClipboard } from 'react-copy-to-clipboard';
16
16
  import "./index.less";
17
17
 
@@ -62,7 +62,7 @@ var SourceCode = function SourceCode(props) {
62
62
  className: "dumi-default-source-code-copy",
63
63
  "data-copied": isCopied || undefined
64
64
  }, isCopied ? /*#__PURE__*/React.createElement(IconCheck, null) : /*#__PURE__*/React.createElement(IconCopy, null))), /*#__PURE__*/React.createElement(Highlight, _extends({}, defaultProps, {
65
- code: children.trim(),
65
+ code: children,
66
66
  language: SIMILAR_DSL[lang] || lang,
67
67
  theme: undefined
68
68
  }), function (_ref) {
@@ -102,6 +102,6 @@ var SourceCode = function SourceCode(props) {
102
102
  );
103
103
  })));
104
104
  }));
105
- }));
105
+ }), props.extra);
106
106
  };
107
107
  export default SourceCode;
@@ -90,6 +90,7 @@
90
90
 
91
91
  &-copy {
92
92
  position: absolute;
93
+ z-index: 2;
93
94
  top: 9px;
94
95
  right: 12px;
95
96
  display: inline-block;
@@ -13,6 +13,8 @@
13
13
  "header.social.linkedin": "Linkedin",
14
14
  "previewer.actions.code.expand": "Show Code",
15
15
  "previewer.actions.code.shrink": "Hide Code",
16
+ "previewer.actions.code.editable": "Edit code with real-time preview",
17
+ "previewer.actions.code.readonly": "Only index file is editable",
16
18
  "previewer.actions.sketch": "Copy to Sketch app",
17
19
  "previewer.actions.sketch.group": "Copy as Sketch Group",
18
20
  "previewer.actions.sketch.symbol": "Copy as Sketch Symbol",
@@ -13,6 +13,8 @@
13
13
  "header.social.linkedin": "Linkedin",
14
14
  "previewer.actions.code.expand": "展开代码",
15
15
  "previewer.actions.code.shrink": "收起代码",
16
+ "previewer.actions.code.editable": "编辑代码可实时预览",
17
+ "previewer.actions.code.readonly": "仅 index 可编辑",
16
18
  "previewer.actions.codesandbox": "在 CodeSandbox 中打开",
17
19
  "previewer.actions.sketch": "拷贝到 Sketch",
18
20
  "previewer.actions.sketch.group": "拷贝为 Sketch Group",
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import 'react-loading-skeleton/dist/skeleton.css';
3
+ import './index.less';
4
+ declare const Loading: React.FC;
5
+ export default Loading;
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import Skeleton from 'react-loading-skeleton';
3
+ import 'react-loading-skeleton/dist/skeleton.css';
4
+ import "./index.less";
5
+ var Loading = function Loading() {
6
+ return /*#__PURE__*/React.createElement("div", {
7
+ className: "dumi-default-loading-skeleton"
8
+ }, /*#__PURE__*/React.createElement(Skeleton, {
9
+ className: "first-line",
10
+ count: 1
11
+ }), /*#__PURE__*/React.createElement(Skeleton, {
12
+ count: 2
13
+ }), /*#__PURE__*/React.createElement(Skeleton, {
14
+ count: 1,
15
+ width: "75%"
16
+ }));
17
+ };
18
+ export default Loading;
@@ -0,0 +1,20 @@
1
+ @import (reference) '../../styles/variables.less';
2
+
3
+ @skeleton-cls: react-loading-skeleton;
4
+
5
+ .@{prefix}-loading-skeleton {
6
+ .@{skeleton-cls} {
7
+ margin-block-end: 0.38em;
8
+
9
+ &.first-line {
10
+ width: calc(100% - 2em);
11
+ margin-inline-start: 2em;
12
+ }
13
+
14
+ // ======== dark mode ========
15
+ @{dark-selector} & {
16
+ --highlight-color: fade(@c-text-dark, @dark-light-amount);
17
+ --base-color: @c-text;
18
+ }
19
+ }
20
+ }
@@ -9,7 +9,13 @@ export interface IPreviewerActionsProps extends IPreviewerProps {
9
9
  extra?: ReactNode;
10
10
  forceShowCode?: boolean;
11
11
  demoContainer: HTMLDivElement | HTMLIFrameElement;
12
- sourceCode?: ReactNode;
12
+ onSourcesTranspile?: (args: {
13
+ err: Error;
14
+ sources?: null;
15
+ } | {
16
+ err?: null;
17
+ sources: Record<string, string>;
18
+ }) => void;
13
19
  }
14
20
  declare const PreviewerActions: FC<IPreviewerActionsProps>;
15
21
  export default PreviewerActions;
@@ -1,3 +1,7 @@
1
+ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
2
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
3
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
4
+ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
1
5
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
2
6
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
7
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -6,12 +10,15 @@ function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefine
6
10
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
7
11
  import { ReactComponent as IconCheck } from '@ant-design/icons-svg/inline-svg/outlined/check.svg';
8
12
  import { ReactComponent as IconCodeSandbox } from '@ant-design/icons-svg/inline-svg/outlined/code-sandbox.svg';
13
+ import { ReactComponent as IconEdit } from '@ant-design/icons-svg/inline-svg/outlined/edit.svg';
9
14
  import { ReactComponent as IconSketch } from '@ant-design/icons-svg/inline-svg/outlined/sketch.svg';
10
15
  import { ReactComponent as IconStackBlitz } from '@ant-design/icons-svg/inline-svg/outlined/thunderbolt.svg';
16
+ import classNames from 'classnames';
11
17
  import copy from 'copy-to-clipboard';
12
18
  import { getSketchJSON, openCodeSandbox, openStackBlitz, useIntl } from 'dumi';
13
19
  import SourceCode from 'dumi/theme/builtins/SourceCode';
14
20
  import PreviewerActionsExtra from 'dumi/theme/slots/PreviewerActionsExtra';
21
+ import SourceCodeEditor from 'dumi/theme/slots/SourceCodeEditor';
15
22
  import Tabs from 'rc-tabs';
16
23
  import React, { useRef, useState } from 'react';
17
24
  import "./index.less";
@@ -152,8 +159,8 @@ var PreviewerActions = function PreviewerActions(props) {
152
159
  })
153
160
  }, showCode ? /*#__PURE__*/React.createElement(IconCodeExpand, null) : /*#__PURE__*/React.createElement(IconCode, null))), showCode && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
154
161
  className: "dumi-default-previewer-sources"
155
- }, !isSingleFile && /*#__PURE__*/React.createElement(Tabs, {
156
- className: "dumi-default-previewer-tabs",
162
+ }, /*#__PURE__*/React.createElement(Tabs, {
163
+ className: classNames('dumi-default-previewer-tabs', isSingleFile && 'dumi-default-previewer-tabs-single'),
157
164
  prefixCls: "dumi-default-tabs",
158
165
  moreIcon: "\xB7\xB7\xB7",
159
166
  defaultActiveKey: String(activeKey),
@@ -165,11 +172,47 @@ var PreviewerActions = function PreviewerActions(props) {
165
172
  filename = _ref4[0];
166
173
  return {
167
174
  key: String(i),
168
- label: filename
175
+ // remove leading ./ prefix
176
+ label: filename.replace(/^\.\//, ''),
177
+ // only support to edit entry file currently
178
+ children: i === 0 ? /*#__PURE__*/React.createElement(SourceCodeEditor, {
179
+ lang: lang,
180
+ initialValue: files[i][1].value.trim(),
181
+ onTranspile: function onTranspile(_ref5) {
182
+ var err = _ref5.err,
183
+ code = _ref5.code;
184
+ if (err) {
185
+ var _props$onSourcesTrans;
186
+ (_props$onSourcesTrans = props.onSourcesTranspile) === null || _props$onSourcesTrans === void 0 ? void 0 : _props$onSourcesTrans.call(props, {
187
+ err: err
188
+ });
189
+ } else {
190
+ var _props$onSourcesTrans2;
191
+ (_props$onSourcesTrans2 = props.onSourcesTranspile) === null || _props$onSourcesTrans2 === void 0 ? void 0 : _props$onSourcesTrans2.call(props, {
192
+ sources: _defineProperty({}, files[i][0], code)
193
+ });
194
+ }
195
+ },
196
+ extra: /*#__PURE__*/React.createElement("button", {
197
+ type: "button",
198
+ className: "dumi-default-previewer-editor-tip-btn",
199
+ "data-dumi-tooltip": intl.formatMessage({
200
+ id: 'previewer.actions.code.editable'
201
+ })
202
+ }, /*#__PURE__*/React.createElement(IconEdit, null))
203
+ }) : /*#__PURE__*/React.createElement(SourceCode, {
204
+ lang: lang,
205
+ extra: /*#__PURE__*/React.createElement("button", {
206
+ type: "button",
207
+ className: "dumi-default-previewer-editor-tip-btn",
208
+ "data-dumi-tooltip": intl.formatMessage({
209
+ id: 'previewer.actions.code.readonly'
210
+ }),
211
+ "data-readonly": true
212
+ }, /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement(IconEdit, null))
213
+ }, files[activeKey][1].value.trim())
169
214
  };
170
215
  })
171
- })), props.sourceCode || /*#__PURE__*/React.createElement(SourceCode, {
172
- lang: lang
173
- }, files[activeKey][1].value)));
216
+ }))));
174
217
  };
175
218
  export default PreviewerActions;
@@ -66,29 +66,53 @@
66
66
  }
67
67
  }
68
68
 
69
- &-tabs {
70
- position: relative;
71
- padding: 0 12px;
69
+ // hide tabs when only one tab pane
70
+ &-tabs-single .@{prefix}-tabs-nav {
71
+ display: none;
72
+ }
72
73
 
73
- &::after {
74
- content: '';
75
- position: absolute;
76
- left: 0;
77
- bottom: 0;
78
- width: 100%;
79
- height: 0;
80
- border-bottom: 1px dashed @c-border-light;
74
+ &-editor-tip-btn {
75
+ position: absolute;
76
+ appearance: none;
77
+ z-index: 2;
78
+ right: 42px;
79
+ top: 9px;
80
+ padding: 8px 12px;
81
+ cursor: help;
82
+ background: transparent;
83
+ border: 0;
84
+ transition: all 0.2s;
85
+
86
+ > svg {
87
+ width: 16px;
88
+ fill: darken(@c-border, 20%);
81
89
 
82
90
  @{dark-selector} & {
83
- border-bottom-color: @c-border-less-dark;
91
+ fill: lighten(@c-border-dark, 20%);
92
+ }
93
+ }
94
+
95
+ &[data-readonly] {
96
+ > span {
97
+ position: absolute;
98
+ top: 50%;
99
+ left: 50%;
100
+ display: block;
101
+ width: 16px;
102
+ height: 2px;
103
+ background: darken(@c-border, 20%);
104
+ transform: rotate(45deg) translate(-50%, 120%);
84
105
  }
85
106
  }
107
+
108
+ .@{prefix}-tabs-tabpane:not(:hover) & {
109
+ opacity: 0;
110
+ visibility: hidden;
111
+ }
86
112
  }
87
113
  }
88
114
 
89
115
  .@{prefix}-tabs {
90
- overflow: hidden;
91
-
92
116
  &-top {
93
117
  flex-direction: column;
94
118
 
@@ -98,7 +122,23 @@
98
122
  }
99
123
 
100
124
  &-nav {
125
+ position: relative;
101
126
  display: flex;
127
+ padding: 0 12px;
128
+
129
+ &::after {
130
+ content: '';
131
+ position: absolute;
132
+ left: 0;
133
+ bottom: 0;
134
+ width: 100%;
135
+ height: 0;
136
+ border-bottom: 1px dashed @c-border-light;
137
+
138
+ @{dark-selector} & {
139
+ border-bottom-color: @c-border-less-dark;
140
+ }
141
+ }
102
142
 
103
143
  &-wrap {
104
144
  display: flex;
@@ -223,4 +263,8 @@
223
263
  display: none;
224
264
  }
225
265
  }
266
+
267
+ &-tabpane-hidden {
268
+ display: none;
269
+ }
226
270
  }
@@ -3,7 +3,7 @@ export var Mask = function Mask(props) {
3
3
  useEffect(function () {
4
4
  if (props.visible) {
5
5
  document.body.style.overflow = 'hidden';
6
- } else {
6
+ } else if (document.body.style.overflow) {
7
7
  var _props$onClose;
8
8
  document.body.style.overflow = '';
9
9
  (_props$onClose = props.onClose) === null || _props$onClose === void 0 ? void 0 : _props$onClose.call(props);
@@ -38,7 +38,7 @@ var SearchBar = function SearchBar() {
38
38
  setKeywords = _useSiteSearch.setKeywords,
39
39
  result = _useSiteSearch.result,
40
40
  loading = _useSiteSearch.loading,
41
- loadSearchData = _useSiteSearch.loadSearchData;
41
+ loadSearchData = _useSiteSearch.load;
42
42
  var _useState5 = useState(false),
43
43
  _useState6 = _slicedToArray(_useState5, 2),
44
44
  modalVisible = _useState6[0],
@@ -98,15 +98,6 @@ var SearchResult = function SearchResult(props) {
98
98
  _useState4 = _slicedToArray(_useState3, 2),
99
99
  activeIndex = _useState4[0],
100
100
  setActiveIndex = _useState4[1];
101
- var _useState5 = useState(props.loading),
102
- _useState6 = _slicedToArray(_useState5, 2),
103
- loading = _useState6[0],
104
- setLoading = _useState6[1];
105
- useEffect(function () {
106
- if (!props.loading) {
107
- setLoading(false);
108
- }
109
- }, [props.loading]);
110
101
  useEffect(function () {
111
102
  var handler = function handler(ev) {
112
103
  // TODO: scroll into view for invisible items
@@ -133,7 +124,7 @@ var SearchResult = function SearchResult(props) {
133
124
  };
134
125
  });
135
126
  var returnNode = null;
136
- if (loading) {
127
+ if (props.loading) {
137
128
  returnNode = /*#__PURE__*/React.createElement("div", {
138
129
  className: "dumi-default-search-empty"
139
130
  }, /*#__PURE__*/React.createElement(IconInbox, null), /*#__PURE__*/React.createElement(FormattedMessage, {
@@ -0,0 +1,18 @@
1
+ import SourceCode from 'dumi/theme/builtins/SourceCode';
2
+ import { type ComponentProps, type FC } from 'react';
3
+ import './index.less';
4
+ interface ISourceCodeEditorProps extends Omit<ComponentProps<typeof SourceCode>, 'children'> {
5
+ initialValue: string;
6
+ onTranspile?: (args: {
7
+ err: Error;
8
+ code?: null;
9
+ } | {
10
+ err?: null;
11
+ code: string;
12
+ }) => void;
13
+ }
14
+ /**
15
+ * simple source code editor based on textarea
16
+ */
17
+ declare const SourceCodeEditor: FC<ISourceCodeEditorProps>;
18
+ export default SourceCodeEditor;
@@ -0,0 +1,106 @@
1
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
2
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
3
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
5
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
6
+ function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
7
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
8
+ import SourceCode from 'dumi/theme/builtins/SourceCode';
9
+ import throttle from 'lodash.throttle';
10
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
11
+ import "./index.less";
12
+ /**
13
+ * simple source code editor based on textarea
14
+ */
15
+ var SourceCodeEditor = function SourceCodeEditor(props) {
16
+ var elm = useRef(null);
17
+ var _useState = useState(),
18
+ _useState2 = _slicedToArray(_useState, 2),
19
+ style = _useState2[0],
20
+ setStyle = _useState2[1];
21
+ var _useState3 = useState(props.initialValue),
22
+ _useState4 = _slicedToArray(_useState3, 2),
23
+ code = _useState4[0],
24
+ setCode = _useState4[1];
25
+ var sucraseDefer = useRef();
26
+ var transpile = useCallback(throttle(function (value) {
27
+ // transform code when change
28
+ sucraseDefer.current.then(function (transform) {
29
+ try {
30
+ var _props$onTranspile;
31
+ (_props$onTranspile = props.onTranspile) === null || _props$onTranspile === void 0 ? void 0 : _props$onTranspile.call(props, {
32
+ code: transform(value, {
33
+ transforms: ['typescript', 'jsx', 'imports']
34
+ }).code
35
+ });
36
+ } catch (err) {
37
+ var _props$onTranspile2;
38
+ (_props$onTranspile2 = props.onTranspile) === null || _props$onTranspile2 === void 0 ? void 0 : _props$onTranspile2.call(props, {
39
+ err: err
40
+ });
41
+ }
42
+ });
43
+ }, 500), [props.onTranspile]);
44
+
45
+ // generate style from pre element, for adapting to the custom theme
46
+ useEffect(function () {
47
+ var _elm$current;
48
+ var pre = (_elm$current = elm.current) === null || _elm$current === void 0 ? void 0 : _elm$current.querySelector('pre');
49
+ if (pre) {
50
+ var preStyle = window.getComputedStyle(pre);
51
+ setStyle({
52
+ fontSize: preStyle.fontSize,
53
+ fontFamily: preStyle.fontFamily,
54
+ lineHeight: preStyle.lineHeight,
55
+ padding: preStyle.padding,
56
+ margin: preStyle.margin
57
+ });
58
+ } else {
59
+ console.warn('[dumi] pre element not found in SourceCode component, the SourceCodeEditor will be disabled, you can report an issue to dumi repository.');
60
+ }
61
+ }, []);
62
+ return /*#__PURE__*/React.createElement("div", {
63
+ className: "dumi-default-source-code-editor",
64
+ ref: elm
65
+ }, /*#__PURE__*/React.createElement(SourceCode, _extends({}, props, {
66
+ extra: style && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("textarea", {
67
+ className: "dumi-default-source-code-editor-textarea",
68
+ style: style,
69
+ value: code,
70
+ onFocus: function onFocus() {
71
+ // load sucrase when focus on editor
72
+ if (!sucraseDefer.current) {
73
+ sucraseDefer.current = import('sucrase').then(function (_ref) {
74
+ var transform = _ref.transform;
75
+ return transform;
76
+ });
77
+ }
78
+ },
79
+ onChange: function onChange(ev) {
80
+ setCode(ev.target.value);
81
+ transpile(ev.target.value);
82
+ },
83
+ onKeyDown: function onKeyDown(ev) {
84
+ // support tab to space
85
+ if (ev.key === 'Tab') {
86
+ ev.preventDefault();
87
+ var _elm = ev.currentTarget;
88
+ var start = _elm.selectionStart,
89
+ end = _elm.selectionEnd;
90
+ var before = _elm.value.substring(0, start);
91
+ var after = _elm.value.substring(end);
92
+ var spaces = ' ';
93
+ var pos = spaces.length + start;
94
+ setCode("".concat(before).concat(spaces).concat(after));
95
+ setTimeout(function () {
96
+ _elm.setSelectionRange(pos, pos);
97
+ });
98
+ }
99
+ },
100
+ autoComplete: "off",
101
+ autoCorrect: "off",
102
+ autoSave: "off"
103
+ }), props.extra)
104
+ }), code));
105
+ };
106
+ export default SourceCodeEditor;