dumi 2.0.2 → 2.0.4

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/bin/dumi.js CHANGED
File without changes
@@ -1 +1 @@
1
- (function(){var e={226:function(e){var n=Object.defineProperty;var t=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var __export=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:true})};var __copyProps=(e,o,i,c)=>{if(o&&typeof o==="object"||typeof o==="function"){for(let s of r(o))if(!a.call(e,s)&&s!==i)n(e,s,{get:()=>o[s],enumerable:!(c=t(o,s))||c.enumerable})}return e};var __toCommonJS=e=>__copyProps(n({},"__esModule",{value:true}),e);var o={};__export(o,{default:()=>analytics_default});e.exports=__toCommonJS(o);var analytics_default=e=>{const n=process.env.GA_KEY;const t=process.env.GA_V2_KEY;const enableBy=e=>e.config.analytics||n;e.describe({key:"analytics",config:{schema(e){return e.alternatives().try(e.object({baidu:e.string(),ga:e.string(),ga_v2:e.string()}),e.boolean().invalid(true))},onChange:e.ConfigChangeType.reload},enableBy:enableBy});const baiduTpl=e=>`\n (function() {\n var hm = document.createElement('script');\n hm.src = '//hm.baidu.com/hm.js?${e}';\n var s = document.getElementsByTagName('script')[0];\n s.parentNode.insertBefore(hm, s);\n })();\n `;const gaTpl=e=>`\n (function(){\n if (!location.port) {\n (function (i, s, o, g, r, a, m) {\n i['GoogleAnalyticsObject'] = r;\n i[r] = i[r] || function () {\n (i[r].q = i[r].q || []).push(arguments)\n }, i[r].l = 1 * new Date();\n a = s.createElement(o),\n m = s.getElementsByTagName(o)[0];\n a.async = 1;\n a.src = g;\n m.parentNode.insertBefore(a, m)\n })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');\n ga('create', '${e}', 'auto');\n ga('send', 'pageview');\n }\n })();\n `;const gaV2Tpl=e=>`\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${e}');\n `.trim();e.addHTMLHeadScripts((()=>{const r=e.config.analytics||{};const{baidu:a,ga:o=n,ga_v2:i=t}=r;const c=[];if(a){c.push({content:"var _hmt = _hmt || [];"})}if(e.env!=="development"){if(a){c.push({content:baiduTpl(a)})}if(o){c.push({content:gaTpl(o)})}if(i){c.push({async:true,src:`//www.googletagmanager.com/gtag/js?id=${i}`},{content:gaV2Tpl(i)})}}return c.filter(Boolean)}))};0&&0}};var n={};function __nccwpck_require__(t){var r=n[t];if(r!==undefined){return r.exports}var a=n[t]={exports:{}};var o=true;try{e[t](a,a.exports,__nccwpck_require__);o=false}finally{if(o)delete n[t]}return a.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var t=__nccwpck_require__(226);module.exports=t})();
1
+ (function(){var e={814:function(e){var n=Object.defineProperty;var t=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var __export=(e,t)=>{for(var r in t)n(e,r,{get:t[r],enumerable:true})};var __copyProps=(e,o,i,c)=>{if(o&&typeof o==="object"||typeof o==="function"){for(let s of r(o))if(!a.call(e,s)&&s!==i)n(e,s,{get:()=>o[s],enumerable:!(c=t(o,s))||c.enumerable})}return e};var __toCommonJS=e=>__copyProps(n({},"__esModule",{value:true}),e);var o={};__export(o,{default:()=>analytics_default});e.exports=__toCommonJS(o);var analytics_default=e=>{const n=process.env.GA_KEY;const t=process.env.GA_V2_KEY;const enableBy=e=>e.config.analytics||n;e.describe({key:"analytics",config:{schema(e){return e.alternatives().try(e.object({baidu:e.string(),ga:e.string(),ga_v2:e.string()}),e.boolean().invalid(true))},onChange:e.ConfigChangeType.reload},enableBy:enableBy});const baiduTpl=e=>`\n (function() {\n var hm = document.createElement('script');\n hm.src = '//hm.baidu.com/hm.js?${e}';\n var s = document.getElementsByTagName('script')[0];\n s.parentNode.insertBefore(hm, s);\n })();\n `;const gaTpl=e=>`\n (function(){\n if (!location.port) {\n (function (i, s, o, g, r, a, m) {\n i['GoogleAnalyticsObject'] = r;\n i[r] = i[r] || function () {\n (i[r].q = i[r].q || []).push(arguments)\n }, i[r].l = 1 * new Date();\n a = s.createElement(o),\n m = s.getElementsByTagName(o)[0];\n a.async = 1;\n a.src = g;\n m.parentNode.insertBefore(a, m)\n })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');\n ga('create', '${e}', 'auto');\n ga('send', 'pageview');\n }\n })();\n `;const gaV2Tpl=e=>`\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${e}');\n `.trim();e.addHTMLHeadScripts((()=>{const r=e.config.analytics||{};const{baidu:a,ga:o=n,ga_v2:i=t}=r;const c=[];if(a){c.push({content:"var _hmt = _hmt || [];"})}if(e.env!=="development"){if(a){c.push({content:baiduTpl(a)})}if(o){c.push({content:gaTpl(o)})}if(i){c.push({async:true,src:`//www.googletagmanager.com/gtag/js?id=${i}`},{content:gaV2Tpl(i)})}}return c.filter(Boolean)}))};0&&0}};var n={};function __nccwpck_require__(t){var r=n[t];if(r!==undefined){return r.exports}var a=n[t]={exports:{}};var o=true;try{e[t](a,a.exports,__nccwpck_require__);o=false}finally{if(o)delete n[t]}return a.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var t=__nccwpck_require__(814);module.exports=t})();
@@ -1 +1 @@
1
- {"name":"@umijs/plugins","version":"4.0.30","authors":["chencheng <sorrycc@gmail.com> (https://github.com/sorrycc)"],"license":"MIT","_lastModified":"2022-11-13T07:05:33.094Z"}
1
+ {"name":"@umijs/plugins","version":"4.0.32","authors":["chencheng <sorrycc@gmail.com> (https://github.com/sorrycc)"],"license":"MIT","_lastModified":"2022-11-20T09:58:00.334Z"}
@@ -75,7 +75,7 @@ var compile_default = (api) => {
75
75
  });
76
76
  memo.module.rule("dumi-page").type("javascript/auto").test(/\.(j|t)sx?$/).resourceQuery(/meta$/).use("page-meta-loader").loader(require.resolve("../../loaders/page"));
77
77
  memo.module.rule("dumi-demo").type("javascript/auto").test(/\..+$/).enforce("pre").resourceQuery(/techStack/).use("demo-loader").loader(require.resolve("../../loaders/demo")).options({ techStacks, cwd: api.cwd });
78
- memo.module.rule("dumi-raw").post().resourceQuery(/dumi-raw/).use("raw-loader").loader(require.resolve("raw-loader"));
78
+ memo.module.rule("dumi-raw").post().resourceQuery(/dumi-raw/).use("raw-loader").loader(require.resolve("raw-loader")).end().use("pre-raw-loader").loader(require.resolve("../../loaders/pre-raw"));
79
79
  if (api.env === "development" && memo.plugins.has("fastRefresh")) {
80
80
  memo.plugin("fastRefresh").tap(([params]) => [
81
81
  {
@@ -71,16 +71,19 @@ var derivative_default = (api) => {
71
71
  };
72
72
  api.describe({ key: "dumi:derivative" });
73
73
  api.onCheck(() => {
74
- var _a;
74
+ var _a, _b;
75
75
  (0, import_assert.default)(!api.config.mpa, "MPA mode is not supported in dumi!");
76
76
  (0, import_assert.default)(!api.config.vite, "Vite mode is not supported yet!");
77
77
  (0, import_assert.default)(((_a = api.config.mfsu) == null ? void 0 : _a.strategy) !== "eager", "MFSU eager mode is not supported yet!");
78
78
  (0, import_assert.default)(!api.config.ssr || api.config.ssr.builder === "webpack", "Only `webpack` builder is supported in SSR mode!");
79
+ if (((_b = api.userConfig.history) == null ? void 0 : _b.type) === "hash") {
80
+ import_plugin_utils.logger.warn("Hash history is temporarily incompatible, it is recommended to use browser history for now.");
81
+ }
79
82
  });
80
83
  safeExcludeInMFSU(api, [new RegExp("dumi/dist/client")]);
81
84
  api.modifyDefaultConfig((memo) => {
82
85
  if (api.userConfig.mfsu !== false) {
83
- if (import_fs.default.existsSync(import_path.default.join(api.cwd, "node_modules", ".pnpm"))) {
86
+ if (import_fs.default.existsSync(import_path.default.join(api.cwd, "node_modules", ".pnpm")) || process.platform === "win32") {
84
87
  memo.mfsu = false;
85
88
  } else {
86
89
  memo.mfsu.strategy = "normal";
@@ -43,7 +43,7 @@ var meta_default = (api) => {
43
43
  if (!route.isLayout && !/\*|:/.test(route.path) && route.file && !(0, import_tabs.isTabRouteFile)(route.file)) {
44
44
  metaFiles.push({
45
45
  index: metaFiles.length,
46
- file: route.file,
46
+ file: (0, import_plugin_utils.winPath)(route.file),
47
47
  id: route.id
48
48
  });
49
49
  }
@@ -143,14 +143,15 @@ function rehypeDemo(opts) {
143
143
  parseOpts.fileAbsPath = codeNode.properties.src;
144
144
  parseOpts.id = getCodeId(opts.cwd, opts.fileAbsPath, import_path.default.parse(parseOpts.fileAbsPath).name, vFile.data.frontmatter.atomId);
145
145
  component = `React.lazy(() => import( /* webpackChunkName: "${chunkName}" */ '${(0, import_plugin_utils.winPath)(parseOpts.fileAbsPath)}?techStack=${techStack.name}'))`;
146
- codeNode.properties.title = codeValue || void 0;
146
+ if (codeValue)
147
+ codeNode.properties.title = codeValue;
147
148
  (_a2 = codeNode.properties).filename ?? (_a2.filename = (0, import_plugin_utils.winPath)(import_path.default.relative(opts.cwd, parseOpts.fileAbsPath)));
148
149
  } else {
149
150
  parseOpts.fileAbsPath = opts.fileAbsPath.replace(".md", ".tsx");
150
151
  parseOpts.id = getCodeId(opts.cwd, opts.fileAbsPath, String(index++), vFile.data.frontmatter.atomId);
151
152
  component = techStack.transformCode(codeValue, {
152
153
  type: "code-block",
153
- fileAbsPath: opts.fileAbsPath
154
+ fileAbsPath: parseOpts.fileAbsPath
154
155
  });
155
156
  }
156
157
  const propDemo = { id: parseOpts.id };
@@ -35,12 +35,16 @@ var EMBED_CLOSE_TAG = "</embed>";
35
35
  var unified;
36
36
  var remarkParse;
37
37
  var remarkFrontmatter;
38
+ var remarkDirective;
39
+ var remarkGfm;
38
40
  var visit;
39
41
  (async () => {
40
42
  ({ visitParents: visit } = await import("unist-util-visit-parents"));
41
43
  ({ unified } = await import("unified"));
42
44
  ({ default: remarkParse } = await import("remark-parse"));
43
45
  ({ default: remarkFrontmatter } = await import("remark-frontmatter"));
46
+ ({ default: remarkDirective } = await import("remark-directive"));
47
+ ({ default: remarkGfm } = await import("remark-gfm"));
44
48
  })();
45
49
  function remarkRawAST() {
46
50
  this.Compiler = function Compiler(ast) {
@@ -79,7 +83,7 @@ function remarkEmbed(opts) {
79
83
  const {
80
84
  result: mdast,
81
85
  data: { embeds }
82
- } = unified().use(remarkParse).use(remarkEmbed, { ...opts, fileAbsPath: absPath }).use(remarkFrontmatter).use(remarkRawAST).processSync(content);
86
+ } = unified().use(remarkParse).use(remarkEmbed, { ...opts, fileAbsPath: absPath }).use(remarkFrontmatter).use(remarkDirective).use(remarkGfm).use(remarkRawAST).processSync(content);
83
87
  if (!node.value.endsWith(EMBED_CLOSE_TAG)) {
84
88
  for (let j = i; j < parent.children.length; j++) {
85
89
  const sibling = parent.children[j];
@@ -0,0 +1,4 @@
1
+ /**
2
+ * loader for discard frontmatter from code file content
3
+ */
4
+ export default function preRawLoader(this: any, raw: string): string;
@@ -0,0 +1,33 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/loaders/pre-raw/index.ts
20
+ var pre_raw_exports = {};
21
+ __export(pre_raw_exports, {
22
+ default: () => preRawLoader
23
+ });
24
+ module.exports = __toCommonJS(pre_raw_exports);
25
+ var import_utils = require("../../utils");
26
+ function preRawLoader(raw) {
27
+ if (/\.(j|t)sx?$/.test(this.resourcePath)) {
28
+ return (0, import_utils.parseCodeFrontmatter)(raw).code;
29
+ }
30
+ return raw;
31
+ }
32
+ // Annotate the CommonJS export names for ESM import in node:
33
+ 0 && (module.exports = {});
@@ -3,7 +3,7 @@ export declare class DumiService extends Service {
3
3
  constructor();
4
4
  getPaths(): Promise<{
5
5
  cwd: string;
6
- absSrcPath: string;
6
+ absSrcPath: any;
7
7
  absPagesPath: string;
8
8
  absApiRoutesPath: string;
9
9
  absTmpPath: string;
@@ -38,8 +38,9 @@ var DumiService = class extends import_umi.Service {
38
38
  });
39
39
  }
40
40
  async getPaths() {
41
+ var _a;
41
42
  const cwd = this.cwd;
42
- const absSrcPath = cwd;
43
+ const absSrcPath = ((_a = this.userConfig.alias) == null ? void 0 : _a["@"]) ?? cwd;
43
44
  const absPagesPath = winJoin(absSrcPath, "pages");
44
45
  const absApiRoutesPath = winJoin(absSrcPath, "api");
45
46
  const tmp = this.env === import_core.Env.development ? `tmp` : `tmp-${this.env}`;
package/package.json CHANGED
@@ -1,8 +1,26 @@
1
1
  {
2
2
  "name": "dumi",
3
- "version": "2.0.2",
4
- "description": "Framework for developing UI components",
5
- "keywords": [],
3
+ "version": "2.0.4",
4
+ "description": "📖 Documentation Generator of React Component",
5
+ "keywords": [
6
+ "generator",
7
+ "umi",
8
+ "webpack",
9
+ "react",
10
+ "static site generator",
11
+ "jamstack",
12
+ "markdown",
13
+ "components",
14
+ "documentation"
15
+ ],
16
+ "homepage": "https://d.umijs.org",
17
+ "bugs": {
18
+ "url": "https://github.com/umijs/dumi/issues"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/umijs/dumi"
23
+ },
6
24
  "license": "MIT",
7
25
  "main": "dist/index.js",
8
26
  "types": "index.d.ts",
@@ -12,7 +30,9 @@
12
30
  "dist",
13
31
  "compiled",
14
32
  "theme-default",
15
- "index.d.ts"
33
+ "index.d.ts",
34
+ "plugin-utils.js",
35
+ "plugin-utils.d.ts"
16
36
  ],
17
37
  "scripts": {
18
38
  "build": "father build",
@@ -22,6 +42,7 @@
22
42
  "docs:build": "node ./bin/dumi.js build",
23
43
  "docs:dev": "node ./bin/dumi.js dev",
24
44
  "docs:sync": "node ./scripts/sync-from-umi.js",
45
+ "format": "prettier --cache --write .",
25
46
  "lint": "npm run lint:es && npm run lint:css",
26
47
  "lint:css": "stylelint \"{src,test}/**/*.{css,less}\"",
27
48
  "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
@@ -36,19 +57,19 @@
36
57
  },
37
58
  "lint-staged": {
38
59
  "*.{md,json}": [
39
- "prettier --write --no-error-on-unmatched-pattern"
60
+ "prettier --cache --write --no-error-on-unmatched-pattern"
40
61
  ],
41
62
  "*.{css,less}": [
42
63
  "stylelint --fix",
43
- "prettier --write"
64
+ "prettier --cache --write"
44
65
  ],
45
66
  "*.{js,jsx}": [
46
67
  "eslint --fix",
47
- "prettier --write"
68
+ "prettier --cache --write"
48
69
  ],
49
70
  "*.{ts,tsx}": [
50
71
  "eslint --fix",
51
- "prettier --parser=typescript --write"
72
+ "prettier --cache --parser=typescript --write"
52
73
  ]
53
74
  },
54
75
  "dependencies": {
@@ -81,6 +102,7 @@
81
102
  "mdast-util-to-string": "^3.1.0",
82
103
  "pluralize": "^8.0.0",
83
104
  "prism-react-renderer": "^1.3.5",
105
+ "prism-themes": "^1.9.0",
84
106
  "prismjs": "^1.29.0",
85
107
  "raw-loader": "^4.0.2",
86
108
  "rc-tabs": "12.1.0-alpha.1",
@@ -118,7 +140,7 @@
118
140
  "@types/react": "^18.0.16",
119
141
  "@types/react-copy-to-clipboard": "^5.0.4",
120
142
  "@umijs/lint": "^4.0.32",
121
- "@umijs/plugins": "^4.0.32",
143
+ "@umijs/plugins": "4.0.32",
122
144
  "eslint": "^8.20.0",
123
145
  "father": "^4.1.0",
124
146
  "husky": "^8.0.1",
@@ -0,0 +1 @@
1
+ export * from 'umi/plugin-utils';
@@ -0,0 +1 @@
1
+ module.exports = require('umi/plugin-utils');
@@ -1,5 +1,5 @@
1
1
  import { type Language } from 'prism-react-renderer';
2
- import 'prismjs/themes/prism-coy.css';
2
+ import 'prism-themes/themes/prism-one-light.css';
3
3
  import { type FC } from 'react';
4
4
  import './index.less';
5
5
  declare const SourceCode: FC<{
@@ -15,7 +15,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
15
15
  import { ReactComponent as IconCheck } from '@ant-design/icons-svg/inline-svg/outlined/check.svg';
16
16
  import { ReactComponent as IconCopy } from '@ant-design/icons-svg/inline-svg/outlined/copy.svg';
17
17
  import Highlight, { defaultProps } from 'prism-react-renderer';
18
- import 'prismjs/themes/prism-coy.css';
18
+ import 'prism-themes/themes/prism-one-light.css';
19
19
  import React, { useRef, useState } from 'react';
20
20
  import { CopyToClipboard } from 'react-copy-to-clipboard';
21
21
  import "./index.less";
@@ -8,6 +8,10 @@
8
8
  color: @c-primary;
9
9
  }
10
10
 
11
+ img {
12
+ max-width: 100%;
13
+ }
14
+
11
15
  // inline code
12
16
  *:not(pre) code {
13
17
  padding: 2px 5px;
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ declare type NativeInputProps = React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
3
+ export declare const Input: React.ForwardRefExoticComponent<{
4
+ onChange: (keywords: string) => void;
5
+ } & Pick<NativeInputProps, "onFocus" | "onBlur"> & React.RefAttributes<HTMLInputElement>>;
6
+ export {};
@@ -0,0 +1,40 @@
1
+ import { useIntl } from 'dumi';
2
+ import React, { forwardRef, useImperativeHandle, useRef } from 'react';
3
+ export var Input = /*#__PURE__*/forwardRef(function (props, ref) {
4
+ var intl = useIntl();
5
+ var imeWaiting = useRef(false);
6
+ var nativeInputRef = useRef(null);
7
+ useImperativeHandle(ref, function () {
8
+ return nativeInputRef.current;
9
+ });
10
+ return /*#__PURE__*/React.createElement("input", {
11
+ className: "dumi-default-search-bar-input",
12
+ onCompositionStart: function onCompositionStart() {
13
+ return imeWaiting.current = true;
14
+ },
15
+ onCompositionEnd: function onCompositionEnd(ev) {
16
+ imeWaiting.current = false; // special case: press Enter open IME panel will not trigger onChange
17
+
18
+ props.onChange(ev.currentTarget.value);
19
+ },
20
+ onFocus: props.onFocus,
21
+ onBlur: props.onBlur,
22
+ onKeyDown: function onKeyDown(ev) {
23
+ if (['ArrowDown', 'ArrowUp'].includes(ev.key)) ev.preventDefault(); // esc to blur input
24
+
25
+ if (ev.key === 'Escape' && !imeWaiting.current) ev.currentTarget.blur();
26
+ },
27
+ onChange: function onChange(ev) {
28
+ // wait for onCompositionEnd event be triggered
29
+ setTimeout(function () {
30
+ if (!imeWaiting.current) {
31
+ props.onChange(ev.target.value);
32
+ }
33
+ }, 1);
34
+ },
35
+ placeholder: intl.formatMessage({
36
+ id: 'header.search.placeholder'
37
+ }),
38
+ ref: nativeInputRef
39
+ });
40
+ });
@@ -0,0 +1,9 @@
1
+ import { type FC, type ReactNode } from 'react';
2
+ declare type MaskProps = {
3
+ visible: boolean;
4
+ children: ReactNode;
5
+ onMaskClick?: () => void;
6
+ onClose?: () => void;
7
+ };
8
+ export declare const Mask: FC<MaskProps>;
9
+ export {};
@@ -0,0 +1,21 @@
1
+ import React, { useEffect } from 'react';
2
+ export var Mask = function Mask(props) {
3
+ useEffect(function () {
4
+ if (props.visible) {
5
+ document.body.style.overflow = 'hidden';
6
+ } else {
7
+ var _props$onClose;
8
+
9
+ document.body.style.overflow = '';
10
+ (_props$onClose = props.onClose) === null || _props$onClose === void 0 ? void 0 : _props$onClose.call(props);
11
+ }
12
+ }, [props.visible]);
13
+ return props.visible ? /*#__PURE__*/React.createElement("div", {
14
+ className: "dumi-default-search-modal"
15
+ }, /*#__PURE__*/React.createElement("div", {
16
+ className: "dumi-default-search-modal-mask",
17
+ onClick: props.onMaskClick
18
+ }), /*#__PURE__*/React.createElement("div", {
19
+ className: "dumi-default-search-modal-content"
20
+ }, props.children)) : null;
21
+ };
@@ -1,4 +1,6 @@
1
1
  import { type FC } from 'react';
2
2
  import './index.less';
3
+ export { Input as SearchInput } from './Input';
4
+ export { Mask as SearchMask } from './Mask';
3
5
  declare const SearchBar: FC;
4
6
  export default SearchBar;
@@ -12,23 +12,27 @@ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Sy
12
12
 
13
13
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
14
 
15
+ import { ReactComponent as IconArrowDown } from '@ant-design/icons-svg/inline-svg/outlined/arrow-down.svg';
16
+ import { ReactComponent as IconArrowUp } from '@ant-design/icons-svg/inline-svg/outlined/arrow-up.svg';
15
17
  import { ReactComponent as IconSearch } from '@ant-design/icons-svg/inline-svg/outlined/search.svg';
16
- import { useIntl, useSiteSearch } from 'dumi';
18
+ import { useSiteSearch } from 'dumi';
17
19
  import React, { useEffect, useRef, useState } from 'react';
18
20
  import SearchResult from "../SearchResult";
19
21
  import "./index.less";
22
+ import { Input } from "./Input";
23
+ import { Mask } from "./Mask";
24
+ export { Input as SearchInput } from "./Input";
25
+ export { Mask as SearchMask } from "./Mask";
20
26
  var isAppleDevice = /(mac|iphone|ipod|ipad)/i.test(typeof navigator !== 'undefined' ? (_navigator = navigator) === null || _navigator === void 0 ? void 0 : _navigator.platform : '');
21
27
 
22
28
  var SearchBar = function SearchBar() {
23
- var intl = useIntl();
24
- var imeWaiting = useRef(false);
25
-
26
29
  var _useState = useState(false),
27
30
  _useState2 = _slicedToArray(_useState, 2),
28
31
  focusing = _useState2[0],
29
32
  setFocusing = _useState2[1];
30
33
 
31
- var input = useRef(null);
34
+ var inputRef = useRef(null);
35
+ var modalInputRef = useRef(null);
32
36
 
33
37
  var _useState3 = useState('⌘'),
34
38
  _useState4 = _slicedToArray(_useState3, 2),
@@ -41,6 +45,11 @@ var SearchBar = function SearchBar() {
41
45
  result = _useSiteSearch.result,
42
46
  loading = _useSiteSearch.loading;
43
47
 
48
+ var _useState5 = useState(false),
49
+ _useState6 = _slicedToArray(_useState5, 2),
50
+ modalVisible = _useState6[0],
51
+ setModalVisible = _useState6[1];
52
+
44
53
  useEffect(function () {
45
54
  // why put useEffect?
46
55
  // to avoid Text content mismatch between server & client in ssr
@@ -49,11 +58,35 @@ var SearchBar = function SearchBar() {
49
58
  }
50
59
 
51
60
  var handler = function handler(ev) {
52
- if ((isAppleDevice ? ev.metaKey : ev.ctrlKey) && ev.key === 'k') {
53
- var _input$current;
61
+ if ((isAppleDevice ? ev.metaKey : ev.ctrlKey) && ev.key === 'k' || ev.key === '/') {
62
+ ev.preventDefault();
63
+
64
+ if (inputRef.current) {
65
+ var _inputRef$current$get = inputRef.current.getBoundingClientRect(),
66
+ top = _inputRef$current$get.top,
67
+ bottom = _inputRef$current$get.bottom,
68
+ left = _inputRef$current$get.left,
69
+ right = _inputRef$current$get.right;
70
+
71
+ var isInViewport = top >= 0 && left >= 0 && bottom <= window.innerHeight && right <= window.innerWidth;
72
+
73
+ if (isInViewport) {
74
+ inputRef.current.focus();
75
+ } else {
76
+ setKeywords('');
77
+ setModalVisible(true);
78
+ setTimeout(function () {
79
+ var _modalInputRef$curren;
80
+
81
+ (_modalInputRef$curren = modalInputRef.current) === null || _modalInputRef$curren === void 0 ? void 0 : _modalInputRef$curren.focus();
82
+ });
83
+ }
84
+ }
85
+ }
54
86
 
55
- (_input$current = input.current) === null || _input$current === void 0 ? void 0 : _input$current.focus();
87
+ if (ev.key === 'Escape') {
56
88
  ev.preventDefault();
89
+ setModalVisible(false);
57
90
  }
58
91
  };
59
92
 
@@ -64,15 +97,9 @@ var SearchBar = function SearchBar() {
64
97
  }, []);
65
98
  return /*#__PURE__*/React.createElement("div", {
66
99
  className: "dumi-default-search-bar"
67
- }, /*#__PURE__*/React.createElement(IconSearch, null), /*#__PURE__*/React.createElement("input", {
68
- onCompositionStart: function onCompositionStart() {
69
- return imeWaiting.current = true;
70
- },
71
- onCompositionEnd: function onCompositionEnd(ev) {
72
- imeWaiting.current = false; // special case: press Enter open IME panel will not trigger onChange
73
-
74
- setKeywords(ev.currentTarget.value);
75
- },
100
+ }, /*#__PURE__*/React.createElement(IconSearch, {
101
+ className: "dumi-default-search-bar-svg"
102
+ }), /*#__PURE__*/React.createElement(Input, {
76
103
  onFocus: function onFocus() {
77
104
  return setFocusing(true);
78
105
  },
@@ -82,31 +109,74 @@ var SearchBar = function SearchBar() {
82
109
  setFocusing(false);
83
110
  }, 1);
84
111
  },
85
- onKeyDown: function onKeyDown(ev) {
86
- if (['ArrowDown', 'ArrowUp'].includes(ev.key)) ev.preventDefault(); // esc to blur input
87
-
88
- if (ev.key === 'Escape' && !imeWaiting.current) ev.currentTarget.blur();
112
+ onChange: function onChange(keywords) {
113
+ return setKeywords(keywords);
89
114
  },
90
- onChange: function onChange(ev) {
91
- // wait for onCompositionEnd event be triggered
92
- setTimeout(function () {
93
- if (!imeWaiting.current) {
94
- setKeywords(ev.target.value);
95
- }
96
- }, 1);
97
- },
98
- placeholder: intl.formatMessage({
99
- id: 'header.search.placeholder'
100
- }),
101
- ref: input
115
+ ref: inputRef
102
116
  }), /*#__PURE__*/React.createElement("span", {
103
117
  className: "dumi-default-search-shortcut"
104
- }, symbol, " K"), keywords.trim() && focusing && (result.length || !loading) && /*#__PURE__*/React.createElement("div", {
118
+ }, symbol, " K"), keywords.trim() && focusing && (result.length || !loading) && !modalVisible && /*#__PURE__*/React.createElement("div", {
105
119
  className: "dumi-default-search-popover"
106
120
  }, /*#__PURE__*/React.createElement("section", null, /*#__PURE__*/React.createElement(SearchResult, {
107
121
  data: result,
108
122
  loading: loading
109
- }))));
123
+ }))), /*#__PURE__*/React.createElement(Mask, {
124
+ visible: modalVisible,
125
+ onMaskClick: function onMaskClick() {
126
+ setModalVisible(false);
127
+ },
128
+ onClose: function onClose() {
129
+ return setKeywords('');
130
+ }
131
+ }, /*#__PURE__*/React.createElement("div", {
132
+ style: {
133
+ position: 'relative'
134
+ }
135
+ }, /*#__PURE__*/React.createElement(IconSearch, {
136
+ className: "dumi-default-search-bar-svg"
137
+ }), /*#__PURE__*/React.createElement(Input, {
138
+ onFocus: function onFocus() {
139
+ return setFocusing(true);
140
+ },
141
+ onBlur: function onBlur() {
142
+ // wait for item click
143
+ setTimeout(function () {
144
+ setFocusing(false);
145
+ }, 1);
146
+ },
147
+ onChange: function onChange(keywords) {
148
+ return setKeywords(keywords);
149
+ },
150
+ ref: modalInputRef
151
+ })), /*#__PURE__*/React.createElement(SearchResult, {
152
+ data: result,
153
+ loading: loading,
154
+ onItemSelect: function onItemSelect() {
155
+ setModalVisible(false);
156
+ }
157
+ }), /*#__PURE__*/React.createElement("footer", null, /*#__PURE__*/React.createElement("ul", {
158
+ className: "dumi-default-search-modal-commands"
159
+ }, /*#__PURE__*/React.createElement("li", {
160
+ className: "dumi-default-search-modal-commands-arrow"
161
+ }, /*#__PURE__*/React.createElement("span", {
162
+ className: "dumi-default-search-modal-shortcut"
163
+ }, /*#__PURE__*/React.createElement(IconArrowUp, {
164
+ width: "10px",
165
+ height: "10px",
166
+ fill: "rgba(0, 0, 0, 0.45)"
167
+ })), /*#__PURE__*/React.createElement("span", {
168
+ className: "dumi-default-search-modal-shortcut"
169
+ }, /*#__PURE__*/React.createElement(IconArrowDown, {
170
+ width: "10px",
171
+ height: "10px",
172
+ fill: "rgba(0, 0, 0, 0.45)"
173
+ })), /*#__PURE__*/React.createElement("span", {
174
+ className: "dumi-default-search-modal-commands-text"
175
+ }, "to navigate")), /*#__PURE__*/React.createElement("li", null, /*#__PURE__*/React.createElement("span", {
176
+ className: "dumi-default-search-modal-shortcut"
177
+ }, "esc"), /*#__PURE__*/React.createElement("span", {
178
+ className: "dumi-default-search-modal-commands-text"
179
+ }, "to close"))))));
110
180
  };
111
181
 
112
182
  export default SearchBar;
@@ -12,7 +12,7 @@
12
12
  margin-inline-end: 28px;
13
13
  }
14
14
 
15
- > svg {
15
+ &-svg {
16
16
  position: absolute;
17
17
  top: 50%;
18
18
  margin-top: 1px;
@@ -22,7 +22,7 @@
22
22
  transform: translateY(-50%);
23
23
  }
24
24
 
25
- > input {
25
+ &-input {
26
26
  width: 280px;
27
27
  height: 40px;
28
28
  padding: 0;
@@ -104,4 +104,89 @@
104
104
  border-radius: inherit;
105
105
  }
106
106
  }
107
+
108
+ .@{prefix}-search-modal {
109
+ position: fixed;
110
+ top: 0;
111
+ inset-inline-start: 0;
112
+ z-index: 1000;
113
+ width: 100vw;
114
+ height: 100vh;
115
+ display: flex;
116
+ justify-content: center;
117
+
118
+ &-mask {
119
+ background-color: rgb(0 0 0 / 45%);
120
+ width: 100%;
121
+ height: 100%;
122
+ }
123
+
124
+ &-content {
125
+ position: absolute;
126
+ top: 60px;
127
+ background-color: #fff;
128
+ width: 500px;
129
+ padding: 12px;
130
+ box-sizing: border-box;
131
+ box-shadow: inset 1px 1px 0 0 hsl(0deg 0% 100% / 50%), 0 3px 8px 0 #555a64;
132
+ border-radius: 8px;
133
+ }
134
+
135
+ .@{prefix}-search-bar-input {
136
+ width: 100%;
137
+ border-radius: 4px;
138
+ }
139
+
140
+ .@{prefix}-search-result {
141
+ min-height: 60px;
142
+ margin-top: 12px;
143
+
144
+ > dl > dd {
145
+ margin: 0 auto;
146
+ }
147
+ }
148
+
149
+ &-commands {
150
+ justify-content: flex-start;
151
+ font-size: 12px;
152
+ color: @c-text-note;
153
+ list-style: none;
154
+ padding: 0;
155
+ margin: 0;
156
+ border-top: 1px solid @c-border-light;
157
+ padding-top: 12px;
158
+ display: flex;
159
+ align-items: center;
160
+ user-select: none;
161
+
162
+ > li {
163
+ margin-inline-end: 10px;
164
+ }
165
+
166
+ &-arrow {
167
+ .@{prefix}-search-modal-shortcut {
168
+ margin-inline-end: 4px;
169
+ }
170
+ }
171
+
172
+ &-text {
173
+ margin-inline-start: 5px;
174
+ }
175
+ }
176
+
177
+ &-shortcut {
178
+ display: inline-block;
179
+ padding: 4px 8px;
180
+ color: @c-text-note;
181
+ font-size: 12px;
182
+ line-height: 1;
183
+ white-space: nowrap;
184
+ background-color: @c-site-bg;
185
+ border-radius: 3px;
186
+ border: 1px solid @c-border;
187
+ border-bottom-width: 2px;
188
+ transition: all 0.3s;
189
+ pointer-events: none;
190
+ }
191
+ }
107
192
  }
@@ -5,5 +5,6 @@ declare type ISearchResult = ReturnType<typeof useSiteSearch>['result'];
5
5
  declare const SearchResult: FC<{
6
6
  data: ISearchResult;
7
7
  loading: boolean;
8
+ onItemSelect?: (item: ISearchResult[0]['hints'][0]) => void;
8
9
  }>;
9
10
  export default SearchResult;
@@ -125,10 +125,13 @@ var SearchResult = function SearchResult(props) {
125
125
  } else if (ev.key === 'ArrowUp') {
126
126
  setActiveIndex((activeIndex + histsCount - 1) % histsCount);
127
127
  } else if (ev.key === 'Enter' && activeIndex >= 0) {
128
- var item = data.find(function (item) {
128
+ var _props$onItemSelect;
129
+
130
+ var _item = data.find(function (item) {
129
131
  return item.type === 'hint' && item.activeIndex === activeIndex;
130
132
  }).value;
131
- history.push(item.link);
133
+ history.push(_item.link);
134
+ (_props$onItemSelect = props.onItemSelect) === null || _props$onItemSelect === void 0 ? void 0 : _props$onItemSelect.call(props, _item);
132
135
  document.activeElement.blur();
133
136
  }
134
137
 
@@ -161,7 +164,12 @@ var SearchResult = function SearchResult(props) {
161
164
  key: String(i)
162
165
  }, /*#__PURE__*/React.createElement(Link, {
163
166
  to: item.value.link,
164
- "data-active": activeIndex === item.activeIndex || undefined
167
+ "data-active": activeIndex === item.activeIndex || undefined,
168
+ onClick: function onClick() {
169
+ var _props$onItemSelect2;
170
+
171
+ return (_props$onItemSelect2 = props.onItemSelect) === null || _props$onItemSelect2 === void 0 ? void 0 : _props$onItemSelect2.call(props, item.value);
172
+ }
165
173
  }, /*#__PURE__*/React.createElement(ICONS_MAPPING[item.value.type]), /*#__PURE__*/React.createElement("h4", null, /*#__PURE__*/React.createElement(Highlight, {
166
174
  texts: item.value.highlightTitleTexts
167
175
  })), /*#__PURE__*/React.createElement("p", null, /*#__PURE__*/React.createElement(Highlight, {