dumi 2.0.0-beta.0 → 2.0.0-beta.2

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.
@@ -7,6 +7,8 @@ interface ISiteContext {
7
7
  }>;
8
8
  locales: NonNullable<ILocalesConfig>;
9
9
  themeConfig: IThemeConfig;
10
+ loading: boolean;
11
+ setLoading: (status: boolean) => void;
10
12
  }
11
13
  export declare const SiteContext: import("react").Context<ISiteContext>;
12
14
  export declare const useSiteData: () => ISiteContext;
@@ -2,7 +2,9 @@ import { createContext, useContext } from 'react';
2
2
  export var SiteContext = /*#__PURE__*/createContext({
3
3
  demos: {},
4
4
  locales: [],
5
- themeConfig: {}
5
+ themeConfig: {},
6
+ loading: false,
7
+ setLoading: function setLoading() {}
6
8
  });
7
9
  export var useSiteData = function useSiteData() {
8
10
  return useContext(SiteContext);
@@ -37,11 +37,11 @@ export var useNavData = function useNavData() {
37
37
  groups = _ref2[1];
38
38
 
39
39
  var meta = Object.values(routes).reduce(function (ret, route) {
40
- var _frontmatter$nav$orde;
40
+ var _route$meta, _frontmatter$nav$orde;
41
41
 
42
42
  // find routes which within the nav path
43
43
  if (route.path.startsWith(link.slice(1))) {
44
- switch (_typeof(route.meta.frontmatter.nav)) {
44
+ switch (_typeof((_route$meta = route.meta) === null || _route$meta === void 0 ? void 0 : _route$meta.frontmatter.nav)) {
45
45
  case 'object':
46
46
  ret.title = route.meta.frontmatter.nav.title || ret.title;
47
47
  ret.order = (_frontmatter$nav$orde = route.meta.frontmatter.nav.order) !== null && _frontmatter$nav$orde !== void 0 ? _frontmatter$nav$orde : ret.order;
@@ -1,8 +1,9 @@
1
+ import type { ISidebarGroup } from './types';
1
2
  /**
2
3
  * hook for get sidebar data for all nav
3
4
  */
4
- export declare const useFullSidebarData: () => any;
5
+ export declare const useFullSidebarData: () => Record<string, ISidebarGroup[]>;
5
6
  /**
6
7
  * hook for get sidebar data for current nav
7
8
  */
8
- export declare const useSidebarData: () => any;
9
+ export declare const useSidebarData: () => ISidebarGroup[];
@@ -4,7 +4,7 @@
4
4
  "paths": {
5
5
  "@/*": ["src/*"],
6
6
  "@@/*": ["src/.umi/*"],
7
- "dumi": ["src"],
7
+ "dumi": ["."],
8
8
  "dumi/theme": ["src/client/theme-api"],
9
9
  "dumi/theme/*": ["src/client/theme-default/*"]
10
10
  },
@@ -1,6 +1,8 @@
1
+ var __create = Object.create;
1
2
  var __defProp = Object.defineProperty;
2
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
4
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
7
  var __export = (target, all) => {
6
8
  for (var name in all)
@@ -14,6 +16,7 @@ var __copyProps = (to, from, except, desc) => {
14
16
  }
15
17
  return to;
16
18
  };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
17
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
21
 
19
22
  // src/features/locales.ts
@@ -22,6 +25,8 @@ __export(locales_exports, {
22
25
  default: () => locales_default
23
26
  });
24
27
  module.exports = __toCommonJS(locales_exports);
28
+ var import_path = __toESM(require("path"));
29
+ var import_plugin_utils = require("umi/plugin-utils");
25
30
  var locales_default = (api) => {
26
31
  var _a;
27
32
  api.describe({
@@ -71,7 +76,7 @@ export const messages = ${JSON.stringify(api.service.themeData.locales, null, 2)
71
76
  content: `
72
77
  import { history } from 'dumi';
73
78
  import React, { useState, type ReactNode } from 'react';
74
- import { RawIntlProvider, createIntl, createIntlCache } from 'react-intl';
79
+ import { RawIntlProvider, createIntl, createIntlCache } from '${(0, import_plugin_utils.winPath)(import_path.default.dirname(require.resolve("react-intl/package")))}';
75
80
  import { locales, messages } from './config';
76
81
 
77
82
  const cache = createIntlCache();
@@ -47,11 +47,12 @@ var routes_default = (api) => {
47
47
  ...((_b = (_a = api.userConfig.resolve) == null ? void 0 : _a.entityDirs) == null ? void 0 : _b.map(({ dir }) => dir)) || ["docs"],
48
48
  ...((_c = api.userConfig.resolve) == null ? void 0 : _c.docDirs) || []
49
49
  ].map((dir) => import_path.default.join(api.cwd, dir, "**/*.md"));
50
+ const pagesDir = import_path.default.join(api.cwd, ".dumi/pages");
50
51
  api.describe({ key: "dumi:routes" });
51
52
  api.addTmpGenerateWatcherPaths(() => extraWatchPaths);
52
53
  api.modifyConfig((memo) => {
53
54
  memo.conventionRoutes = {
54
- base: import_path.default.join(__dirname, "dumi-disable-default-routes")
55
+ base: pagesDir
55
56
  };
56
57
  return memo;
57
58
  });
@@ -67,9 +68,12 @@ var routes_default = (api) => {
67
68
  return memo;
68
69
  });
69
70
  api.modifyRoutes((oRoutes) => {
71
+ const pages = {};
70
72
  const routes = Object.values(oRoutes).reduce((ret, route) => {
71
73
  if (route.isLayout) {
72
74
  ret[route.id] = route;
75
+ } else {
76
+ pages[route.id] = route;
73
77
  }
74
78
  return ret;
75
79
  }, {});
@@ -101,6 +105,11 @@ var routes_default = (api) => {
101
105
  isLayout: true
102
106
  };
103
107
  }
108
+ Object.entries(pages).forEach(([, route]) => {
109
+ route.parentId = docLayoutId;
110
+ route.file = import_path.default.resolve(pagesDir, route.file);
111
+ routes[route.id] = route;
112
+ });
104
113
  docDirs.forEach((dir) => {
105
114
  const base = import_path.default.join(api.cwd, dir);
106
115
  const dirRoutes = (0, import_core.getConventionRoutes)({
@@ -131,13 +140,15 @@ var routes_default = (api) => {
131
140
  localizeUmiRoute(routes[routeId], api.config.locales);
132
141
  });
133
142
  });
134
- routes["404"] = {
135
- id: "404",
136
- path: "*",
137
- absPath: "/*",
138
- parentId: docLayoutId,
139
- file: require.resolve("../client/pages/404")
140
- };
143
+ if (Object.values(pages).every((route) => route.path !== "*")) {
144
+ routes["404"] = {
145
+ id: "404",
146
+ path: "*",
147
+ absPath: "/*",
148
+ parentId: docLayoutId,
149
+ file: require.resolve("../client/pages/404")
150
+ };
151
+ }
141
152
  routes["demo-render"] = {
142
153
  id: "demo-render",
143
154
  path: `${import_constants.SP_ROUTE_PREFIX}demos/:id`,
@@ -106,16 +106,31 @@ export { default } from '${item.source}';`
106
106
  api.writeTmpFile({
107
107
  noPluginDir: true,
108
108
  path: "dumi/theme/ContextWrapper.tsx",
109
- content: `import { useOutlet } from 'dumi';
109
+ content: `import React, { useState, useEffect } from 'react';
110
+ import { useOutlet, history } from 'dumi';
110
111
  import { SiteContext } from '${(0, import_plugin_utils.winPath)(require.resolve("../../client/theme-api/context"))}';
111
112
  import { demos } from '../meta';
112
113
  import { locales } from '../locales/config';
113
114
 
114
115
  export default function DumiContextWrapper() {
115
116
  const outlet = useOutlet();
117
+ const [loading, setLoading] = useState(true);
118
+
119
+ // mark loading when route change, page component will set false when loaded
120
+ useEffect(() => {
121
+ return history.listen(() => setLoading(true));
122
+ }, []);
116
123
 
117
124
  return (
118
- <SiteContext.Provider value={{ demos, locales, themeConfig: ${JSON.stringify(api.config.themeConfig)} }}>{outlet}</SiteContext.Provider>
125
+ <SiteContext.Provider value={{
126
+ demos,
127
+ locales,
128
+ loading,
129
+ setLoading,
130
+ themeConfig: ${JSON.stringify(api.config.themeConfig)},
131
+ }}>
132
+ {outlet}
133
+ </SiteContext.Provider>
119
134
  );
120
135
  }`
121
136
  });
package/dist/index.d.ts CHANGED
@@ -1,9 +1,5 @@
1
1
  import type { IDumiUserConfig } from "./types";
2
2
  declare let unistUtilVisit: typeof import('unist-util-visit');
3
3
  export * from 'umi';
4
- export * from './client/theme-api';
5
- export { IApi } from "./types";
6
- export type { Root as HastRoot } from 'hast';
7
- export type { Plugin as UnifiedPlugin, Transformer as UnifiedTransformer, } from 'unified';
8
4
  export { unistUtilVisit };
9
5
  export declare const defineConfig: (config: IDumiUserConfig) => IDumiUserConfig;
package/dist/index.js CHANGED
@@ -28,7 +28,6 @@ __export(src_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(src_exports);
30
30
  __reExport(src_exports, require("umi"), module.exports);
31
- __reExport(src_exports, require("./client/theme-api"), module.exports);
32
31
  var unistUtilVisit;
33
32
  (async () => {
34
33
  unistUtilVisit = await import("unist-util-visit");
@@ -72,11 +72,18 @@ export const toc = {{{toc}}}
72
72
  }));
73
73
  } else {
74
74
  cb(null, `${Object.values(opts.builtins).map((item) => `import ${item.specifier} from '${item.source}';`).join("\n")}
75
- import React from 'react';
75
+ import React, { useEffect } from 'react';
76
+ import { useSiteData } from 'dumi';
76
77
 
77
78
  // export named function for fastRefresh
78
79
  // ref: https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/docs/TROUBLESHOOTING.md#edits-always-lead-to-full-reload
79
80
  function DumiMarkdownContent() {
81
+ const { setLoading } = useSiteData();
82
+
83
+ useEffect(() => {
84
+ setLoading(false);
85
+ }, []);
86
+
80
87
  return ${ret.content};
81
88
  }
82
89
 
package/index.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export { Root as HastRoot } from 'hast';
2
+ export * from 'umi';
3
+ export {
4
+ Plugin as UnifiedPlugin,
5
+ Transformer as UnifiedTransformer,
6
+ } from 'unified';
7
+ export * from './dist';
8
+ // override umi exported defineConfig
9
+ export { defineConfig } from './dist';
10
+ export * from './dist/client/theme-api';
11
+ export { IApi } from './dist/types';
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
2
  "name": "dumi",
3
- "version": "2.0.0-beta.0",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "Framework for developing UI components",
5
5
  "keywords": [],
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
8
- "types": "dist/index.d.ts",
8
+ "types": "index.d.ts",
9
9
  "bin": "./bin/dumi.js",
10
10
  "files": [
11
11
  "bin",
12
12
  "dist",
13
13
  "compiled",
14
14
  "theme-default",
15
- "theme.d.ts"
15
+ "theme.d.ts",
16
+ "index.d.ts"
16
17
  ],
17
18
  "scripts": {
18
19
  "build": "father build",
@@ -21,10 +22,10 @@
21
22
  "dev": "father dev",
22
23
  "docs:build": "node ./bin/dumi.js build",
23
24
  "docs:dev": "node ./bin/dumi.js dev",
24
- "postinstall": "npm run build && node ./bin/dumi.js setup",
25
25
  "lint": "npm run lint:es && npm run lint:css",
26
26
  "lint:css": "stylelint \"{src,test}/**/*.{css,less}\"",
27
27
  "lint:es": "eslint \"{src,test}/**/*.{js,jsx,ts,tsx}\"",
28
+ "prepare": "npm run build && node ./bin/dumi.js setup",
28
29
  "prepublishOnly": "npm run build",
29
30
  "test": "cross-env NODE_OPTIONS=--experimental-vm-modules pnpm jest"
30
31
  },
@@ -52,6 +53,7 @@
52
53
  },
53
54
  "dependencies": {
54
55
  "@ant-design/icons-svg": "^4.2.1",
56
+ "@makotot/ghostui": "^2.0.0",
55
57
  "@swc/core": "^1.2.224",
56
58
  "@types/hast": "^2.3.4",
57
59
  "@types/mdast": "^3.0.10",
@@ -13,5 +13,6 @@ body {
13
13
 
14
14
  > main {
15
15
  display: flex;
16
+ align-items: flex-start;
16
17
  }
17
18
  }
@@ -34,6 +34,6 @@
34
34
  background-color: #fff;
35
35
  border-top-left-radius: 10px;
36
36
  border-top-right-radius: 10px;
37
- box-shadow: 0 4px 24px 0 rgb(0 0 0 / 5%);
37
+ box-shadow: 0 8px 24px 0 rgb(0 0 0 / 5%);
38
38
  }
39
39
  }
@@ -1,9 +1,17 @@
1
1
  @import (reference) '../../styles/variables.less';
2
2
 
3
3
  .@{prefix}-header {
4
+ position: sticky;
5
+ top: 0;
6
+ z-index: 10;
4
7
  display: flex;
8
+ margin: 0 -24px;
9
+ padding: 0 24px;
5
10
  align-items: center;
6
- height: 86px;
11
+ height: @s-header-height;
12
+ background-color: fadeout(@c-site-bg, 10%);
13
+ backdrop-filter: blur(6px);
14
+ box-sizing: border-box;
7
15
 
8
16
  &-left {
9
17
  width: @s-sidebar-width;
@@ -1,7 +1,7 @@
1
1
  @import (reference) '../../styles/variables.less';
2
2
 
3
3
  .@{prefix}-logo {
4
- display: flex;
4
+ display: inline-flex;
5
5
  align-items: center;
6
6
  color: @c-text;
7
7
  font-size: 22px;
@@ -1,10 +1,13 @@
1
1
  @import (reference) '../../styles/variables.less';
2
2
 
3
3
  .@{prefix}-sidebar {
4
+ position: sticky;
5
+ top: @s-header-height;
4
6
  width: @s-sidebar-width;
5
- min-height: 100vh;
7
+ max-height: calc(100vh - @s-header-height);
6
8
  padding: 20px 32px 24px 8px;
7
9
  box-sizing: border-box;
10
+ overflow: auto;
8
11
 
9
12
  > dl {
10
13
  margin: 0;
@@ -1,33 +1,81 @@
1
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
2
 
3
- import { useLocation, useRouteMeta } from 'dumi';
4
- import React from 'react';
3
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
4
+
5
+ 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."); }
6
+
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); }
8
+
9
+ 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; }
10
+
11
+ function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
12
+
13
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
+
15
+ import { Scrollspy as ScrollSpy } from '@makotot/ghostui/src/Scrollspy';
16
+ import { useLocation, useRouteMeta, useSiteData } from 'dumi';
17
+ import React, { useEffect, useRef, useState } from 'react';
5
18
  import "./index.less";
6
19
 
7
20
  var Toc = function Toc() {
8
21
  var _useLocation = useLocation(),
9
- hash = _useLocation.hash;
22
+ pathname = _useLocation.pathname;
23
+
24
+ var meta = useRouteMeta();
25
+
26
+ var _useSiteData = useSiteData(),
27
+ loading = _useSiteData.loading;
28
+
29
+ var prevIndexRef = useRef(0);
30
+
31
+ var _useState = useState([]),
32
+ _useState2 = _slicedToArray(_useState, 2),
33
+ sectionRefs = _useState2[0],
34
+ setSectionRefs = _useState2[1]; // only render h2 ~ h4
10
35
 
11
- var _useRouteMeta = useRouteMeta(),
12
- toc = _useRouteMeta.toc;
13
36
 
14
- return /*#__PURE__*/React.createElement("ul", {
15
- className: "dumi-default-toc"
16
- }, toc.filter(function (_ref) {
37
+ var toc = meta.toc.filter(function (_ref) {
17
38
  var depth = _ref.depth;
18
39
  return depth > 1 && depth < 4;
19
- }).map(function (item) {
20
- var link = "#".concat(encodeURIComponent(item.id));
21
- return /*#__PURE__*/React.createElement("li", {
22
- key: item.id,
23
- "data-depth": item.depth
24
- }, /*#__PURE__*/React.createElement("a", _extends({
25
- href: link,
26
- title: item.title
27
- }, link === hash ? {
28
- className: 'active'
29
- } : {}), item.title));
30
- }));
40
+ });
41
+ useEffect(function () {
42
+ // wait for page component ready (DOM ready)
43
+ if (!loading) {
44
+ // find all valid headings as ref elements
45
+ var refs = toc.map(function (_ref2) {
46
+ var id = _ref2.id;
47
+ return {
48
+ current: document.getElementById(id)
49
+ };
50
+ });
51
+ setSectionRefs(refs);
52
+ }
53
+ }, [pathname, loading]);
54
+ return sectionRefs.length ? /*#__PURE__*/React.createElement(ScrollSpy, {
55
+ sectionRefs: sectionRefs
56
+ }, function (_ref3) {
57
+ var currentElementIndexInViewport = _ref3.currentElementIndexInViewport;
58
+ // for keep prev item active when no item in viewport
59
+ if (currentElementIndexInViewport > -1) prevIndexRef.current = currentElementIndexInViewport;
60
+ return /*#__PURE__*/React.createElement("ul", {
61
+ className: "dumi-default-toc"
62
+ }, toc.filter(function (_ref4) {
63
+ var depth = _ref4.depth;
64
+ return depth > 1 && depth < 4;
65
+ }).map(function (item, i) {
66
+ var link = "#".concat(encodeURIComponent(item.id));
67
+ var activeIndex = currentElementIndexInViewport > -1 ? currentElementIndexInViewport : prevIndexRef.current;
68
+ return /*#__PURE__*/React.createElement("li", {
69
+ key: item.id,
70
+ "data-depth": item.depth
71
+ }, /*#__PURE__*/React.createElement("a", _extends({
72
+ href: link,
73
+ title: item.title
74
+ }, activeIndex === i ? {
75
+ className: 'active'
76
+ } : {}), item.title));
77
+ }));
78
+ }) : null;
31
79
  };
32
80
 
33
81
  export default Toc;
@@ -2,6 +2,7 @@
2
2
 
3
3
  @s-content-width: 1392px;
4
4
  @s-sidebar-width: 184px;
5
+ @s-header-height: 76px;
5
6
 
6
7
  @c-primary: #1677ff;
7
8
  @c-text: #333;