@blocklet/ui-react 3.0.38 → 3.0.39

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.
@@ -1,52 +1,52 @@
1
1
  import { jsx as i } from "react/jsx-runtime";
2
2
  import "iconify-icon";
3
- import { use as I, useMemo as b, useLayoutEffect as v } from "react";
3
+ import { use as I, useMemo as v, useLayoutEffect as w } from "react";
4
4
  import t from "prop-types";
5
5
  import { SessionContext as R } from "@arcblock/did-connect/lib/Session";
6
6
  import { useLocaleContext as T } from "@arcblock/ux/lib/Locale/context";
7
- import C from "@arcblock/ux/lib/Img";
8
- import D from "@arcblock/ux/lib/Layout/dashboard";
9
- import M from "@arcblock/ux/lib/hooks/use-blocklet-logo";
10
- import { SessionManagerProps as A, BlockletMetaProps as O } from "../types.js";
11
- import { mapRecursive as j, flatRecursive as H, matchPaths as S } from "../utils.js";
12
- import { formatBlockletInfo as E, getLocalizedNavigation as U, filterNavByRole as _, publicPath as h } from "../blocklets.js";
13
- import q from "../common/header-addons.js";
14
- import { useWalletHiddenTopbar as F } from "../common/wallet-hidden-topbar.js";
15
- function G({
7
+ import z from "@arcblock/ux/lib/Img";
8
+ import A from "@arcblock/ux/lib/Layout/dashboard";
9
+ import C from "@arcblock/ux/lib/hooks/use-blocklet-logo";
10
+ import { SessionManagerProps as D, BlockletMetaProps as M } from "../types.js";
11
+ import { mapRecursive as O, flatRecursive as j, matchPaths as H } from "../utils.js";
12
+ import { formatBlockletInfo as S, getLocalizedNavigation as _, filterNavByRole as E, publicPath as m } from "../blocklets.js";
13
+ import U from "../common/header-addons.js";
14
+ import { useWalletHiddenTopbar as q } from "../common/wallet-hidden-topbar.js";
15
+ function F({
16
16
  meta: s = {},
17
- fallbackUrl: a = h,
17
+ fallbackUrl: a = m,
18
18
  invalidPathFallback: l = null,
19
19
  headerAddons: k = void 0,
20
20
  sessionManagerProps: L = {
21
21
  showRole: !0,
22
22
  // dashboard 默认退出登录行为: 跳转到 (root) blocklet 首页
23
23
  onLogout: () => {
24
- window.location.href = h;
24
+ window.location.href = m;
25
25
  }
26
26
  },
27
27
  links: c = [],
28
- showDomainWarningDialog: P = !0,
29
- ...d
28
+ showDomainWarningDialog: N = !0,
29
+ ...h
30
30
  }) {
31
- F();
32
- const f = I(R)?.session?.user, g = f?.role, { locale: x } = T() || {}, r = b(() => {
31
+ q();
32
+ const d = I(R)?.session?.user, g = d?.role, { locale: x } = T() || {}, r = v(() => {
33
33
  const e = Object.assign({}, window.blocklet, s);
34
34
  try {
35
- return E(e);
35
+ return S(e);
36
36
  } catch (n) {
37
37
  return console.error("Failed to format blocklet info", n, e), e;
38
38
  }
39
- }, [s]), { localizedNav: w, flattened: p, matchedIndex: y } = b(() => {
40
- let e = U(r?.navigation?.dashboard, x) || [];
41
- e = _(e, g), e = j(
39
+ }, [s]), { localizedNav: y, flattened: f, matchedIndex: b } = v(() => {
40
+ let e = _(r?.navigation?.dashboard, x) || [];
41
+ e = E(e, g), e = O(
42
42
  e,
43
43
  (o) => {
44
- let m = null;
45
- return o.icon && (o.icon.startsWith("http") || o.icon.startsWith("data:") ? m = /* @__PURE__ */ i(C, { src: o.icon }) : m = /* @__PURE__ */ i("iconify-icon", { height: "100%", width: "100%", icon: o.icon })), {
44
+ let u = null;
45
+ return o.icon && (o.icon.startsWith("http") || o.icon.startsWith("data:") ? u = /* @__PURE__ */ i(z, { src: o.icon }) : u = /* @__PURE__ */ i("iconify-icon", { height: "100%", width: "100%", icon: o.icon })), {
46
46
  id: o.id,
47
47
  title: o.title,
48
48
  url: o.link,
49
- icon: m,
49
+ icon: u,
50
50
  // https://github.com/ArcBlock/ux/issues/755#issuecomment-1208692620
51
51
  external: !0,
52
52
  children: o.items
@@ -54,56 +54,55 @@ function G({
54
54
  },
55
55
  "items"
56
56
  );
57
- const n = H(e).filter((o) => !!o.url), u = S(n.map((o) => o.url));
58
- return u !== -1 && (n[u].active = !0), { localizedNav: e, flattened: n, matchedIndex: u };
59
- }, [r, x, g]), W = typeof c == "function" ? c(w) : [...w, ...c], N = M({
57
+ const n = j(e).filter((o) => !!o.url), p = H(n.map((o) => o.url));
58
+ return p !== -1 && (n[p].active = !0), { localizedNav: e, flattened: n, matchedIndex: p };
59
+ }, [r, x, g]), P = typeof c == "function" ? c(y) : [...y, ...c], W = C({
60
60
  meta: s
61
61
  });
62
- if (v(() => {
63
- f && !p?.length && a && (window.location.href = a);
64
- }, [a]), v(() => {
65
- f && p?.length && y === -1 && l && l();
66
- }, [l, p, y]), !r.appName)
62
+ if (w(() => {
63
+ d && !f?.length && a && (window.location.href = a);
64
+ }, [a]), w(() => {
65
+ d && f?.length && b === -1 && l && l();
66
+ }, [l, f, b]), !r.appName)
67
67
  return null;
68
- const { appName: z } = r, B = /* @__PURE__ */ i(
69
- q,
70
- {
71
- formattedBlocklet: r,
72
- addons: k,
73
- sessionManagerProps: L,
74
- showDomainWarningDialog: P,
75
- showWizard: d.headerProps?.showWizard
76
- }
77
- );
68
+ const { appName: B } = r;
78
69
  return /* @__PURE__ */ i(
79
- D,
70
+ A,
80
71
  {
81
- title: z,
72
+ title: B,
82
73
  fullWidth: !0,
83
74
  sidebarWidth: 128,
84
75
  legacy: !1,
85
- links: W,
86
- ...d,
76
+ links: P,
77
+ ...h,
87
78
  headerProps: {
88
- homeLink: h,
89
- logo: /* @__PURE__ */ i("img", { src: N, alt: "logo" }),
90
- addons: B,
91
- ...d.headerProps
79
+ homeLink: m,
80
+ logo: /* @__PURE__ */ i("img", { src: W, alt: "logo" }),
81
+ addons: /* @__PURE__ */ i(
82
+ U,
83
+ {
84
+ formattedBlocklet: r,
85
+ addons: k,
86
+ sessionManagerProps: L,
87
+ showDomainWarningDialog: N
88
+ }
89
+ ),
90
+ ...h.headerProps
92
91
  }
93
92
  }
94
93
  );
95
94
  }
96
- G.propTypes = {
97
- meta: O,
95
+ F.propTypes = {
96
+ meta: M,
98
97
  // 如果当前用户没有权限访问任何导航菜单, 则自动跳转到 fallbackUrl, 默认值为 publicPath, 设置为 null 表示禁用自动跳转
99
98
  fallbackUrl: t.string,
100
99
  // 当前路径未匹配任何 nav links 时的 fallback, 默认行为跳转到首个可用的 nav link
101
100
  invalidPathFallback: t.func,
102
101
  headerAddons: t.oneOfType([t.func, t.node]),
103
- sessionManagerProps: A,
102
+ sessionManagerProps: D,
104
103
  links: t.oneOfType([t.array, t.func]),
105
104
  showDomainWarningDialog: t.bool
106
105
  };
107
106
  export {
108
- G as default
107
+ F as default
109
108
  };
@@ -18,7 +18,6 @@ type HeaderProps = {
18
18
  align?: 'left' | 'right';
19
19
  maxWidth?: false | Breakpoint;
20
20
  showDomainWarningDialog?: boolean;
21
- showWizard?: boolean;
22
21
  };
23
22
  declare const _default: import('react').ComponentType<HeaderProps & Omit<BoxProps, keyof HeaderProps>>;
24
23
  export default _default;
@@ -1,41 +1,41 @@
1
1
  import { jsx as n } from "react/jsx-runtime";
2
- import { useMemo as v } from "react";
3
- import { useMemoizedFn as N } from "ahooks";
4
- import { withErrorBoundary as H } from "react-error-boundary";
5
- import { ErrorFallback as y } from "@arcblock/ux/lib/ErrorBoundary";
6
- import { styled as C, useTheme as T, deepmerge as _, ThemeProvider as E } from "@arcblock/ux/lib/Theme";
7
- import { ResponsiveHeader as B } from "@arcblock/ux/lib/Header";
8
- import F, { Products as L } from "@arcblock/ux/lib/NavMenu";
9
- import { useLocaleContext as P } from "@arcblock/ux/lib/Locale/context";
10
- import { translate as R } from "@arcblock/ux/lib/Locale/util";
11
- import z from "@arcblock/ux/lib/hooks/use-blocklet-logo";
12
- import A from "lodash/omit";
13
- import M from "lodash/isFinite";
14
- import W from "clsx";
15
- import j from "../Icon/index.js";
16
- import { mapRecursive as S, flatRecursive as U, matchPaths as K } from "../utils.js";
17
- import { formatBlockletInfo as O, getLocalizedNavigation as q, publicPath as D } from "../blocklets.js";
18
- import G from "../common/header-addons.js";
19
- import { useWalletHiddenTopbar as J } from "../common/wallet-hidden-topbar.js";
20
- import Q from "../libs/with-hide-when-embed.js";
21
- const V = {
2
+ import { useMemo as k } from "react";
3
+ import { useMemoizedFn as $ } from "ahooks";
4
+ import { withErrorBoundary as N } from "react-error-boundary";
5
+ import { ErrorFallback as H } from "@arcblock/ux/lib/ErrorBoundary";
6
+ import { styled as y, useTheme as C, deepmerge as T, ThemeProvider as _ } from "@arcblock/ux/lib/Theme";
7
+ import { ResponsiveHeader as E } from "@arcblock/ux/lib/Header";
8
+ import B, { Products as F } from "@arcblock/ux/lib/NavMenu";
9
+ import { useLocaleContext as L } from "@arcblock/ux/lib/Locale/context";
10
+ import { translate as P } from "@arcblock/ux/lib/Locale/util";
11
+ import R from "@arcblock/ux/lib/hooks/use-blocklet-logo";
12
+ import z from "lodash/omit";
13
+ import A from "lodash/isFinite";
14
+ import M from "clsx";
15
+ import W from "../Icon/index.js";
16
+ import { mapRecursive as j, flatRecursive as S, matchPaths as U } from "../utils.js";
17
+ import { formatBlockletInfo as K, getLocalizedNavigation as O, publicPath as q } from "../blocklets.js";
18
+ import D from "../common/header-addons.js";
19
+ import { useWalletHiddenTopbar as G } from "../common/wallet-hidden-topbar.js";
20
+ import J from "../libs/with-hide-when-embed.js";
21
+ const Q = {
22
22
  en: {
23
23
  products: "Products"
24
24
  },
25
25
  zh: {
26
26
  products: "产品"
27
27
  }
28
- }, X = (e) => {
28
+ }, V = (e) => {
29
29
  if (!e?.length)
30
30
  return { navItems: [], activeId: null };
31
31
  let r = 1;
32
- const i = S(e, (o) => {
33
- const d = o.icon ? /* @__PURE__ */ n(j, { icon: o.icon }) : null;
32
+ const s = j(e, (o) => {
33
+ const i = o.icon ? /* @__PURE__ */ n(W, { icon: o.icon }) : null;
34
34
  if (o.items)
35
35
  return {
36
36
  id: `${r++}`,
37
37
  label: o.title,
38
- icon: d,
38
+ icon: i,
39
39
  children: o.items
40
40
  };
41
41
  let l = {};
@@ -45,74 +45,72 @@ const V = {
45
45
  }), {
46
46
  id: `${r++}`,
47
47
  label: /* @__PURE__ */ n("a", { href: o.link, ...l, children: o.title }),
48
- icon: d,
48
+ icon: i,
49
49
  description: o.description,
50
50
  link: o.link
51
51
  };
52
- }, "items"), a = U(i), s = K(a.map((o) => o.link));
53
- return { navItems: i, activeId: s >= 0 ? a[s].id : null };
52
+ }, "items"), a = S(s), d = U(a.map((o) => o.link));
53
+ return { navItems: s, activeId: d >= 0 ? a[d].id : null };
54
54
  };
55
- function Y({
55
+ function X({
56
56
  meta: e = {},
57
57
  addons: r = void 0,
58
58
  sessionManagerProps: u = {
59
59
  showRole: !0
60
60
  },
61
- homeLink: i = D,
61
+ homeLink: s = q,
62
62
  theme: a = void 0,
63
- hideNavMenu: s = !1,
63
+ hideNavMenu: d = !1,
64
64
  showDomainWarningDialog: o = !0,
65
- showWizard: d = !1,
66
- ...l
65
+ ...i
67
66
  }) {
68
- J();
69
- const h = T(), { locale: b } = P() || {}, x = N((t, f = {}) => R(V, t, b, "en", f)), m = v(() => {
67
+ G();
68
+ const l = C(), { locale: h } = L() || {}, v = $((t, f = {}) => P(Q, t, h, "en", f)), m = k(() => {
70
69
  const t = Object.assign({}, window.blocklet, e);
71
70
  try {
72
- return O(t);
71
+ return K(t);
73
72
  } catch (f) {
74
73
  return console.error("Failed to format blocklet info", f, t), t;
75
74
  }
76
- }, [e]), c = v(() => _(h, a), [h, a]), I = z({
75
+ }, [e]), c = k(() => T(l, a), [l, a]), x = R({
77
76
  meta: e,
78
77
  theme: a
79
78
  });
80
79
  if (!m.appName)
81
80
  return null;
82
- const w = q(m?.navigation?.header, b), g = X(w), { navItems: p, activeId: $ } = g, k = parseInt(window.blocklet?.USE_ARCBLOCK_THEME, 10);
83
- return M(k) && p.splice(k, 0, {
84
- label: x("products"),
81
+ const I = O(m?.navigation?.header, h), b = V(I), { navItems: p, activeId: w } = b, g = parseInt(window.blocklet?.USE_ARCBLOCK_THEME, 10);
82
+ return A(g) && p.splice(g, 0, {
83
+ label: v("products"),
85
84
  // eslint-disable-next-line react/no-unstable-nested-components
86
- children: ({ isOpen: t }) => /* @__PURE__ */ n(L, { isOpen: t })
87
- }), /* @__PURE__ */ n(E, { theme: c, children: /* @__PURE__ */ n(
88
- Z,
85
+ children: ({ isOpen: t }) => /* @__PURE__ */ n(F, { isOpen: t })
86
+ }), /* @__PURE__ */ n(_, { theme: c, children: /* @__PURE__ */ n(
87
+ Y,
89
88
  {
90
- homeLink: i,
91
- logo: /* @__PURE__ */ n("img", { src: I, alt: "logo" }),
89
+ homeLink: s,
90
+ logo: /* @__PURE__ */ n("img", { src: x, alt: "logo" }),
92
91
  addons: (
93
92
  // @ts-ignore
94
93
  /* @__PURE__ */ n(
95
- G,
94
+ D,
96
95
  {
97
96
  formattedBlocklet: m,
98
- addons: typeof r == "function" ? (t) => r(t, { navigation: g }) : r,
97
+ addons: typeof r == "function" ? (t) => r(t, { navigation: b }) : r,
99
98
  sessionManagerProps: u,
100
- showDomainWarningDialog: o,
101
- showWizard: d
99
+ showDomainWarningDialog: o
102
100
  }
103
101
  )
104
102
  ),
105
- ...A(l, ["bordered"]),
106
- $bordered: l?.bordered,
103
+ ...z(i, ["bordered"]),
104
+ $bordered: i?.bordered,
107
105
  $bgcolor: c.palette.background.default,
108
- className: W("blocklet__header", l.className),
109
- children: s || !p?.length ? null : ({ isMobile: t }) => (
106
+ className: M("blocklet__header", i.className),
107
+ children: d || !p?.length ? null : ({ isMobile: t }) => (
110
108
  // @ts-ignore
111
109
  /* @__PURE__ */ n(
112
- F,
110
+ B,
113
111
  {
114
112
  mode: t ? "inline" : "horizontal",
115
- activeId: $,
113
+ activeId: w,
116
114
  items: p,
117
115
  className: "header-nav",
118
116
  bgColor: "transparent",
@@ -124,7 +122,7 @@ function Y({
124
122
  }
125
123
  ) });
126
124
  }
127
- const Z = C(B)`
125
+ const Y = y(E)`
128
126
  ${({ $bgcolor: e }) => `background-color: ${e || "#fff"};`}
129
127
  .header-logo {
130
128
  min-width: 44px;
@@ -135,9 +133,9 @@ const Z = C(B)`
135
133
  min-width: 32px;
136
134
  }
137
135
  }
138
- `, $o = H(Q(Y), {
139
- FallbackComponent: y
136
+ `, wo = N(J(X), {
137
+ FallbackComponent: H
140
138
  });
141
139
  export {
142
- $o as default
140
+ wo as default
143
141
  };
@@ -1,13 +1,12 @@
1
1
  import { default as PropTypes } from 'prop-types';
2
2
  import { SessionManagerProps } from '../types';
3
- declare function HeaderAddons({ formattedBlocklet, addons, showDomainWarningDialog, sessionManagerProps, showWizard, }: {
3
+ declare function HeaderAddons({ formattedBlocklet, addons, showDomainWarningDialog, sessionManagerProps, }: {
4
4
  formattedBlocklet: any;
5
5
  addons?: null | undefined;
6
6
  showDomainWarningDialog?: boolean | undefined;
7
7
  sessionManagerProps?: {
8
8
  showRole: boolean;
9
9
  } | undefined;
10
- showWizard?: boolean | undefined;
11
10
  }): import('react').FunctionComponentElement<import('react').FragmentProps>;
12
11
  declare namespace HeaderAddons {
13
12
  namespace propTypes {
@@ -15,7 +14,6 @@ declare namespace HeaderAddons {
15
14
  export let addons: PropTypes.Requireable<NonNullable<((...args: any[]) => any) | PropTypes.ReactNodeLike>>;
16
15
  export { SessionManagerProps as sessionManagerProps };
17
16
  export let showDomainWarningDialog: PropTypes.Requireable<boolean>;
18
- export let showWizard: PropTypes.Requireable<boolean>;
19
17
  }
20
18
  }
21
19
  export default HeaderAddons;
@@ -1,132 +1,71 @@
1
- import { jsx as e, Fragment as x } from "react/jsx-runtime";
1
+ import { jsx as s, Fragment as v } from "react/jsx-runtime";
2
2
  import "iconify-icon";
3
- import { useState as h, useEffect as L, use as N, createElement as W } from "react";
4
- import s from "prop-types";
5
- import { Tooltip as M, IconButton as R } from "@mui/material";
6
- import B from "@iconify-icons/tabler/wand";
7
- import { SessionContext as D } from "@arcblock/did-connect/lib/Session";
8
- import E from "@arcblock/ux/lib/SessionUser";
9
- import O from "@arcblock/ux/lib/SessionBlocklet";
10
- import P from "@arcblock/ux/lib/Locale/selector";
11
- import { useLocaleContext as g } from "@arcblock/ux/lib/Locale/context";
12
- import j from "@arcblock/ux/lib/Config/theme-mode-toggle";
13
- import { SessionManagerProps as F } from "../types.js";
14
- import { getLocalizedNavigation as I, filterNavByRole as q } from "../blocklets.js";
15
- import H from "./notification-addon.js";
16
- import U from "./domain-warning.js";
17
- import V from "./wizard-modal.js";
18
- const $ = () => !!(window?.blocklet?.navigation ?? []).find((i) => i.id === "/userCenter/notification");
19
- function G({
20
- formattedBlocklet: m,
21
- addons: i = null,
22
- showDomainWarningDialog: y = !0,
23
- sessionManagerProps: w = { showRole: !0 },
24
- showWizard: T = !1
3
+ import r from "prop-types";
4
+ import { use as b, createElement as k } from "react";
5
+ import { SessionContext as w } from "@arcblock/did-connect/lib/Session";
6
+ import L from "@arcblock/ux/lib/Config/theme-mode-toggle";
7
+ import { useLocaleContext as N } from "@arcblock/ux/lib/Locale/context";
8
+ import T from "@arcblock/ux/lib/Locale/selector";
9
+ import C from "@arcblock/ux/lib/SessionBlocklet";
10
+ import R from "@arcblock/ux/lib/SessionUser";
11
+ import { getLocalizedNavigation as S, filterNavByRole as M } from "../blocklets.js";
12
+ import { SessionManagerProps as B } from "../types.js";
13
+ import D from "./domain-warning.js";
14
+ import P from "./notification-addon.js";
15
+ const j = () => !!(window?.blocklet?.navigation ?? []).find((o) => o.id === "/userCenter/notification");
16
+ function x({
17
+ formattedBlocklet: l,
18
+ addons: o = null,
19
+ showDomainWarningDialog: m = !0,
20
+ sessionManagerProps: u = { showRole: !0 }
25
21
  }) {
26
- const [d, p] = h(!1), [t, c] = h(!1), { t: b } = g();
27
- L(() => {
28
- let o;
29
- return t && (o = setTimeout(() => {
30
- c(!1);
31
- }, 3e3)), () => {
32
- o && clearTimeout(o);
33
- };
34
- }, [t]);
35
- const n = N(D), { locale: r, languages: z } = g() || {}, { enableConnect: A = !0, enableLocale: k = !0 } = m, v = !!n?.session?.user;
36
- let f = I(m?.navigation?.sessionManager, r) || [];
37
- f = q(f, n?.session?.user?.role);
38
- const u = (() => {
39
- if (i && typeof i != "function")
40
- return Array.isArray(i) ? i : [i];
41
- let o = [];
42
- if ($() && o.push(/* @__PURE__ */ e(H, { session: n.session }, "notification-addon")), k && r && z.length > 1 && o.push(/* @__PURE__ */ e(P, { showText: !1 }, "locale-selector")), o.push(/* @__PURE__ */ e(j, {}, "theme-mode-toggle")), T && o.push(
43
- /* @__PURE__ */ e(
44
- M,
45
- {
46
- title: b("setup.wizardTooltip"),
47
- open: t,
48
- placement: "bottom",
49
- arrow: !0,
50
- children: /* @__PURE__ */ e(
51
- R,
52
- {
53
- size: "small",
54
- onClick: () => {
55
- p(!0), c(!1);
56
- },
57
- sx: {
58
- display: { xs: "none", md: "flex" },
59
- color: "text.secondary",
60
- ...t && {
61
- backgroundColor: "action.hover",
62
- "@keyframes pulse": {
63
- "0%": { opacity: 0.8 },
64
- "50%": { opacity: 0.5 },
65
- "100%": { opacity: 0.8 }
66
- },
67
- animation: "pulse 2s infinite"
68
- }
69
- },
70
- children: /* @__PURE__ */ e("iconify-icon", { icon: B, height: 20 })
71
- }
72
- )
73
- },
74
- `wizard-toggle-${t}`
75
- ),
76
- /* @__PURE__ */ e(
77
- V,
78
- {
79
- show: d,
80
- onChangeVisible: (a) => {
81
- p(a), !a && d && c(!0);
82
- },
83
- onFinished: () => {
84
- p(!1), c(!1);
85
- }
86
- },
87
- "wizard-modal"
88
- )
89
- ), A && n) {
90
- const a = [];
91
- v && (f ? f.slice(0, 5) : []).forEach((l) => {
92
- a.push({
93
- label: l.title,
94
- icon: l.icon ? /* @__PURE__ */ e("iconify-icon", { icon: l.icon, height: 24, style: { marginRight: 8 } }) : null,
22
+ const n = b(w), { locale: i, languages: p } = N() || {}, { enableConnect: g = !0, enableLocale: d = !0 } = l, h = !!n?.session?.user;
23
+ let a = S(l?.navigation?.sessionManager, i) || [];
24
+ a = M(a, n?.session?.user?.role);
25
+ const c = (() => {
26
+ if (o && typeof o != "function")
27
+ return Array.isArray(o) ? o : [o];
28
+ let e = [];
29
+ if (j() && e.push(/* @__PURE__ */ s(P, { session: n.session }, "notification-addon")), d && i && p.length > 1 && e.push(/* @__PURE__ */ s(T, { showText: !1 }, "locale-selector")), e.push(/* @__PURE__ */ s(L, {}, "theme-mode-toggle")), g && n) {
30
+ const f = [];
31
+ h && (a ? a.slice(0, 5) : []).forEach((t) => {
32
+ f.push({
33
+ label: t.title,
34
+ icon: t.icon ? /* @__PURE__ */ s("iconify-icon", { icon: t.icon, height: 24, style: { marginRight: 8 } }) : null,
95
35
  component: "a",
96
- href: l.link,
97
- key: l.link
36
+ href: t.link,
37
+ key: t.link
98
38
  });
99
- }), o.push(/* @__PURE__ */ e(O, { session: n.session, locale: r }, "session-blocklet")), o.push(
100
- /* @__PURE__ */ e(
101
- E,
39
+ }), e.push(/* @__PURE__ */ s(C, { session: n.session, locale: i }, "session-blocklet")), e.push(
40
+ /* @__PURE__ */ s(
41
+ R,
102
42
  {
103
43
  session: n.session,
104
- locale: r,
105
- menu: a,
44
+ locale: i,
45
+ menu: f,
106
46
  showRole: !0,
107
- ...w
47
+ ...u
108
48
  },
109
49
  "session-user"
110
50
  )
111
51
  );
112
52
  }
113
- return typeof i == "function" && (o = i(o) || []), o;
114
- })(), C = Array.isArray(u) ? u : [u], S = [
115
- y ? /* @__PURE__ */ e(U, { session: n?.session, locale: r }) : null,
116
- ...C
53
+ return typeof o == "function" && (e = o(e) || []), e;
54
+ })(), y = Array.isArray(c) ? c : [c], A = [
55
+ m ? /* @__PURE__ */ s(D, { session: n?.session, locale: i }) : null,
56
+ ...y
117
57
  ].filter(Boolean);
118
- return W(x, null, ...S);
58
+ return k(v, null, ...A);
119
59
  }
120
- G.propTypes = {
121
- formattedBlocklet: s.object.isRequired,
60
+ x.propTypes = {
61
+ formattedBlocklet: r.object.isRequired,
122
62
  // 需要考虑 定制的 addons 与内置的 连接钱包/选择语言 addons 共存的情况
123
63
  // - PropTypes.func: 可以把自定义 addons 插在 session-manager 或 locale-selector (如果存在的话) 前/中/后
124
64
  // - PropTypes.node: 将 addons 原样传给 UX Header 组件
125
- addons: s.oneOfType([s.func, s.node]),
126
- sessionManagerProps: F,
127
- showDomainWarningDialog: s.bool,
128
- showWizard: s.bool
65
+ addons: r.oneOfType([r.func, r.node]),
66
+ sessionManagerProps: B,
67
+ showDomainWarningDialog: r.bool
129
68
  };
130
69
  export {
131
- G as default
70
+ x as default
132
71
  };
@@ -1,14 +1,16 @@
1
1
  import { default as PropTypes } from 'prop-types';
2
- declare function WizardModal({ onFinished, show, onChangeVisible }: {
2
+ declare function WizardModal({ onFinished, show, onChangeVisible, loadingText, }: {
3
3
  onFinished?: (() => void) | undefined;
4
4
  show?: boolean | undefined;
5
5
  onChangeVisible?: (() => void) | undefined;
6
+ loadingText?: string | undefined;
6
7
  }): import("react/jsx-runtime").JSX.Element | null;
7
8
  declare namespace WizardModal {
8
9
  namespace propTypes {
9
10
  let onFinished: PropTypes.Requireable<(...args: any[]) => any>;
10
11
  let show: PropTypes.Requireable<boolean>;
11
12
  let onChangeVisible: PropTypes.Requireable<(...args: any[]) => any>;
13
+ let loadingText: PropTypes.Requireable<PropTypes.ReactNodeLike>;
12
14
  }
13
15
  }
14
16
  export default WizardModal;
@@ -1,46 +1,51 @@
1
- import { jsxs as I, jsx as m } from "react/jsx-runtime";
2
- import { useLocaleContext as U } from "@arcblock/ux/lib/Locale/context";
3
- import { useTheme as W, useMediaQuery as P, Dialog as T, Box as j, CircularProgress as E } from "@mui/material";
4
- import p from "prop-types";
5
- import { useState as w, useRef as g, useEffect as a } from "react";
6
- import { withQuery as M, joinURL as A } from "ufo";
7
- const h = "/.well-known/service/wizard/bind-account";
8
- function D({ onFinished: b = () => {
9
- }, show: o = !1, onChangeVisible: x = () => {
10
- } }) {
11
- const [r, n] = w(o), [i, s] = w(!1), [y, l] = w(() => localStorage.getItem("wizard-current-url") || h), z = g(b), c = g(), d = g(null), { locale: R } = U(), C = W(), u = P(C.breakpoints.down("sm"));
12
- if (z.current = b, c.current = () => {
13
- if (d.current?.contentWindow)
1
+ import { jsxs as x, jsx as i } from "react/jsx-runtime";
2
+ import { useLocaleContext as P } from "@arcblock/ux/lib/Locale/context";
3
+ import { useTheme as T, useMediaQuery as j, Dialog as D, Box as R, CircularProgress as E, Typography as M } from "@mui/material";
4
+ import a from "prop-types";
5
+ import { useState as g, useRef as h, useEffect as s } from "react";
6
+ import { withQuery as A, joinURL as F } from "ufo";
7
+ const b = "/.well-known/service/wizard/bind-account";
8
+ function B({
9
+ onFinished: y = () => {
10
+ },
11
+ show: o = !1,
12
+ onChangeVisible: v = () => {
13
+ },
14
+ loadingText: l = ""
15
+ }) {
16
+ const [r, n] = g(o), [c, d] = g(!1), [C, u] = g(() => localStorage.getItem("wizard-current-url") || b), z = h(y), f = h(), m = h(null), { locale: I } = P(), L = T(), p = j(L.breakpoints.down("sm"));
17
+ if (z.current = y, f.current = () => {
18
+ if (m.current?.contentWindow)
14
19
  try {
15
- const t = new URL(d.current.contentWindow.location.href).pathname;
16
- localStorage.setItem("wizard-current-url", t), l(t);
20
+ const t = new URL(m.current.contentWindow.location.href).pathname;
21
+ localStorage.setItem("wizard-current-url", t), u(t);
17
22
  } catch (e) {
18
- l(h), console.warn("Failed to save wizard URL:", e);
23
+ u(b), console.warn("Failed to save wizard URL:", e);
19
24
  }
20
- localStorage.setItem("wizard-completed", "true"), n(!1), x(!1);
21
- }, a(() => {
25
+ localStorage.setItem("wizard-completed", "true"), n(!1), v(!1);
26
+ }, s(() => {
22
27
  o !== r && n(o);
23
- }, [o]), a(() => {
24
- !r && i && s(!1);
25
- }, [r]), a(() => {
28
+ }, [o]), s(() => {
29
+ !r && c && d(!1);
30
+ }, [r]), s(() => {
26
31
  const e = (t) => {
27
32
  if (t.origin !== window.location.origin)
28
33
  return;
29
- const { type: L, data: S } = t.data || {};
30
- switch (L) {
34
+ const { type: k, data: U } = t.data || {};
35
+ switch (k) {
31
36
  case "wizard.loaded":
32
- s(!0);
37
+ d(!0);
33
38
  break;
34
39
  case "wizard.finished": {
35
- n(!1), l(h), localStorage.removeItem("wizard-current-url"), localStorage.setItem("wizard-completed", "true");
36
- const f = z.current?.(S);
37
- f instanceof Promise ? f.then((k) => {
38
- k !== !1 && window.location.reload();
39
- }) : f !== !1 && window.location.reload();
40
+ n(!1), u(b), localStorage.removeItem("wizard-current-url"), localStorage.setItem("wizard-completed", "true");
41
+ const w = z.current?.(U);
42
+ w instanceof Promise ? w.then((W) => {
43
+ W !== !1 && window.location.reload();
44
+ }) : w !== !1 && window.location.reload();
40
45
  break;
41
46
  }
42
47
  case "wizard.close": {
43
- c.current();
48
+ f.current();
44
49
  break;
45
50
  }
46
51
  }
@@ -48,21 +53,21 @@ function D({ onFinished: b = () => {
48
53
  return window.addEventListener("message", e), () => {
49
54
  window.removeEventListener("message", e);
50
55
  };
51
- }, []), a(() => {
56
+ }, []), s(() => {
52
57
  localStorage.getItem("wizard-completed") || n(!0);
53
58
  }, []), !r)
54
59
  return null;
55
- const v = M(A(window.location.origin, y), {
56
- locale: R
60
+ const S = A(F(window.location.origin, C), {
61
+ locale: I
57
62
  });
58
- return /* @__PURE__ */ I(
59
- T,
63
+ return /* @__PURE__ */ x(
64
+ D,
60
65
  {
61
66
  open: r,
62
- onClose: () => c.current(),
67
+ onClose: () => f.current(),
63
68
  fullWidth: !0,
64
- maxWidth: u ? !1 : "md",
65
- fullScreen: u,
69
+ maxWidth: p ? !1 : "md",
70
+ fullScreen: p,
66
71
  slotProps: {
67
72
  paper: {
68
73
  sx: {
@@ -70,7 +75,7 @@ function D({ onFinished: b = () => {
70
75
  borderRadius: 0,
71
76
  position: "relative",
72
77
  overflow: "hidden",
73
- ...u ? { borderRadius: 0 } : {
78
+ ...p ? { borderRadius: 0 } : {
74
79
  borderRadius: 1,
75
80
  height: "max(800px, 80vh)"
76
81
  }
@@ -83,11 +88,11 @@ function D({ onFinished: b = () => {
83
88
  }
84
89
  },
85
90
  children: [
86
- /* @__PURE__ */ m(
91
+ /* @__PURE__ */ i(
87
92
  "iframe",
88
93
  {
89
- ref: d,
90
- src: v,
94
+ ref: m,
95
+ src: S,
91
96
  title: "Setup Wizard",
92
97
  style: {
93
98
  width: "100%",
@@ -95,14 +100,14 @@ function D({ onFinished: b = () => {
95
100
  border: 0,
96
101
  padding: 0,
97
102
  margin: 0,
98
- opacity: i ? 1 : 0,
103
+ opacity: c ? 1 : 0,
99
104
  transition: "opacity 0.3s ease-in-out"
100
105
  },
101
- onLoad: () => s(!0)
106
+ onLoad: () => d(!0)
102
107
  }
103
108
  ),
104
- i ? null : /* @__PURE__ */ m(
105
- j,
109
+ c ? null : /* @__PURE__ */ i(
110
+ R,
106
111
  {
107
112
  sx: {
108
113
  position: "absolute",
@@ -115,18 +120,22 @@ function D({ onFinished: b = () => {
115
120
  alignItems: "center",
116
121
  bgcolor: "background.paper"
117
122
  },
118
- children: /* @__PURE__ */ m(E, {})
123
+ children: /* @__PURE__ */ x(R, { sx: { display: "flex", alignItems: "center", flexDirection: "column", gap: 1 }, children: [
124
+ /* @__PURE__ */ i(E, {}),
125
+ typeof l == "string" ? /* @__PURE__ */ i(M, { variant: "body1", children: l }) : l
126
+ ] })
119
127
  }
120
128
  )
121
129
  ]
122
130
  }
123
131
  );
124
132
  }
125
- D.propTypes = {
126
- onFinished: p.func,
127
- show: p.bool,
128
- onChangeVisible: p.func
133
+ B.propTypes = {
134
+ onFinished: a.func,
135
+ show: a.bool,
136
+ onChangeVisible: a.func,
137
+ loadingText: a.node
129
138
  };
130
139
  export {
131
- D as default
140
+ B as default
132
141
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/ui-react",
3
- "version": "3.0.38",
3
+ "version": "3.0.39",
4
4
  "description": "Some useful front-end web components that can be used in Blocklets.",
5
5
  "keywords": [
6
6
  "react",
@@ -35,9 +35,9 @@
35
35
  "dependencies": {
36
36
  "@abtnode/constant": "^1.16.46",
37
37
  "@abtnode/util": "^1.16.46",
38
- "@arcblock/bridge": "3.0.38",
39
- "@arcblock/icons": "3.0.38",
40
- "@arcblock/react-hooks": "3.0.38",
38
+ "@arcblock/bridge": "3.0.39",
39
+ "@arcblock/icons": "3.0.39",
40
+ "@arcblock/react-hooks": "3.0.39",
41
41
  "@arcblock/ws": "^1.21.0",
42
42
  "@blocklet/constant": "^1.16.46",
43
43
  "@blocklet/did-space-react": "^1.1.11",
@@ -91,5 +91,5 @@
91
91
  "jest": "^29.7.0",
92
92
  "unbuild": "^2.0.0"
93
93
  },
94
- "gitHead": "643c8e01d5f5cb421b3315d4625177d1ccfa1ea1"
94
+ "gitHead": "0b0937b6a161c7332622ae0001849a7d3b2904f1"
95
95
  }
@@ -129,7 +129,6 @@ function Dashboard({
129
129
  addons={headerAddons}
130
130
  sessionManagerProps={sessionManagerProps}
131
131
  showDomainWarningDialog={showDomainWarningDialog}
132
- showWizard={rest.headerProps?.showWizard}
133
132
  />
134
133
  );
135
134
 
@@ -93,7 +93,6 @@ type HeaderProps = {
93
93
  align?: 'left' | 'right';
94
94
  maxWidth?: false | Breakpoint;
95
95
  showDomainWarningDialog?: boolean;
96
- showWizard?: boolean;
97
96
  };
98
97
 
99
98
  /**
@@ -111,7 +110,6 @@ function Header({
111
110
  theme: themeOverrides = undefined,
112
111
  hideNavMenu = false,
113
112
  showDomainWarningDialog = true,
114
- showWizard = false,
115
113
  ...rest
116
114
  }: HeaderProps & Omit<BoxProps, keyof HeaderProps>) {
117
115
  useWalletHiddenTopbar();
@@ -166,7 +164,6 @@ function Header({
166
164
  // @ts-ignore
167
165
  sessionManagerProps={sessionManagerProps}
168
166
  showDomainWarningDialog={showDomainWarningDialog}
169
- showWizard={showWizard}
170
167
  />
171
168
  );
172
169
 
@@ -1,24 +1,21 @@
1
1
  import 'iconify-icon';
2
2
 
3
- import { use, createElement, useState, useEffect } from 'react';
4
3
  import PropTypes from 'prop-types';
5
- import { IconButton, Tooltip } from '@mui/material';
6
- import WandIcon from '@iconify-icons/tabler/wand';
4
+ import { createElement, use } from 'react';
7
5
 
8
6
  // FIXME: 直接从 react 中 import Fragment 可能会在 vite 下出错,先暂时从 react/jsx-runtime 导入 Fragment 来跳过这个问题
9
- import { Fragment } from 'react/jsx-runtime';
10
7
  import { SessionContext } from '@arcblock/did-connect/lib/Session';
11
- import SessionUser from '@arcblock/ux/lib/SessionUser';
12
- import SessionBlocklet from '@arcblock/ux/lib/SessionBlocklet';
13
- import LocaleSelector from '@arcblock/ux/lib/Locale/selector';
14
- import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
15
8
  import ThemeModeToggle from '@arcblock/ux/lib/Config/theme-mode-toggle';
9
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
10
+ import LocaleSelector from '@arcblock/ux/lib/Locale/selector';
11
+ import SessionBlocklet from '@arcblock/ux/lib/SessionBlocklet';
12
+ import SessionUser from '@arcblock/ux/lib/SessionUser';
13
+ import { Fragment } from 'react/jsx-runtime';
16
14
 
15
+ import { filterNavByRole, getLocalizedNavigation } from '../blocklets';
17
16
  import { SessionManagerProps } from '../types';
18
- import { getLocalizedNavigation, filterNavByRole } from '../blocklets';
19
- import NotificationAddon from './notification-addon';
20
17
  import DomainWarning from './domain-warning';
21
- import WizardModal from './wizard-modal';
18
+ import NotificationAddon from './notification-addon';
22
19
 
23
20
  const hasNotification = () => {
24
21
  const navigations = window?.blocklet?.navigation ?? [];
@@ -31,25 +28,7 @@ export default function HeaderAddons({
31
28
  addons = null,
32
29
  showDomainWarningDialog = true,
33
30
  sessionManagerProps = { showRole: true },
34
- showWizard = false,
35
31
  }) {
36
- const [wizardOpen, setWizardOpen] = useState(false);
37
- const [showTooltip, setShowTooltip] = useState(false);
38
- const { t } = useLocaleContext();
39
-
40
- // 处理 tooltip 倒计时
41
- useEffect(() => {
42
- let timer;
43
- if (showTooltip) {
44
- timer = setTimeout(() => {
45
- setShowTooltip(false);
46
- }, 3000); // 3秒后自动隐藏
47
- }
48
- return () => {
49
- if (timer) clearTimeout(timer);
50
- };
51
- }, [showTooltip]);
52
-
53
32
  const sessionCtx = use(SessionContext);
54
33
  const { locale, languages } = useLocaleContext() || {};
55
34
  const { enableConnect = true, enableLocale = true } = formattedBlocklet;
@@ -77,54 +56,6 @@ export default function HeaderAddons({
77
56
  // 切换明暗主题
78
57
  addonsArray.push(<ThemeModeToggle key="theme-mode-toggle" />);
79
58
 
80
- // Wizard 开关
81
- if (showWizard) {
82
- addonsArray.push(
83
- <Tooltip
84
- key={`wizard-toggle-${showTooltip}`}
85
- title={t('setup.wizardTooltip')}
86
- open={showTooltip}
87
- placement="bottom"
88
- arrow>
89
- <IconButton
90
- size="small"
91
- onClick={() => {
92
- setWizardOpen(true);
93
- setShowTooltip(false); // 点击后隐藏 tooltip
94
- }}
95
- sx={{
96
- display: { xs: 'none', md: 'flex' },
97
- color: 'text.secondary',
98
- ...(showTooltip && {
99
- backgroundColor: 'action.hover',
100
- '@keyframes pulse': {
101
- '0%': { opacity: 0.8 },
102
- '50%': { opacity: 0.5 },
103
- '100%': { opacity: 0.8 },
104
- },
105
- animation: 'pulse 2s infinite',
106
- }),
107
- }}>
108
- <iconify-icon icon={WandIcon} height={20} />
109
- </IconButton>
110
- </Tooltip>,
111
- <WizardModal
112
- key="wizard-modal"
113
- show={wizardOpen}
114
- onChangeVisible={(visible) => {
115
- setWizardOpen(visible);
116
- if (!visible && wizardOpen) {
117
- setShowTooltip(true);
118
- }
119
- }}
120
- onFinished={() => {
121
- setWizardOpen(false);
122
- setShowTooltip(false);
123
- }}
124
- />
125
- );
126
- }
127
-
128
59
  // 启用了连接钱包并且检测到了 session context
129
60
  if (enableConnect && sessionCtx) {
130
61
  const menu = [];
@@ -180,5 +111,4 @@ HeaderAddons.propTypes = {
180
111
  addons: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
181
112
  sessionManagerProps: SessionManagerProps,
182
113
  showDomainWarningDialog: PropTypes.bool,
183
- showWizard: PropTypes.bool,
184
114
  };
@@ -1,12 +1,17 @@
1
1
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
2
- import { Box, CircularProgress, Dialog, useMediaQuery, useTheme } from '@mui/material';
2
+ import { Box, CircularProgress, Dialog, Typography, useMediaQuery, useTheme } from '@mui/material';
3
3
  import PropTypes from 'prop-types';
4
4
  import { useEffect, useRef, useState } from 'react';
5
5
  import { joinURL, withQuery } from 'ufo';
6
6
 
7
7
  const DEFAULT_WIZARD_PATH = '/.well-known/service/wizard/bind-account';
8
8
 
9
- export default function WizardModal({ onFinished = () => {}, show = false, onChangeVisible = () => {} }) {
9
+ export default function WizardModal({
10
+ onFinished = () => {},
11
+ show = false,
12
+ onChangeVisible = () => {},
13
+ loadingText = '',
14
+ }) {
10
15
  const [open, setOpen] = useState(show);
11
16
  const [loaded, setLoaded] = useState(false);
12
17
  const [currentUrl, setCurrentUrl] = useState(() => {
@@ -169,7 +174,10 @@ export default function WizardModal({ onFinished = () => {}, show = false, onCha
169
174
  alignItems: 'center',
170
175
  bgcolor: 'background.paper',
171
176
  }}>
172
- <CircularProgress />
177
+ <Box sx={{ display: 'flex', alignItems: 'center', flexDirection: 'column', gap: 1 }}>
178
+ <CircularProgress />
179
+ {typeof loadingText === 'string' ? <Typography variant="body1">{loadingText}</Typography> : loadingText}
180
+ </Box>
173
181
  </Box>
174
182
  )}
175
183
  </Dialog>
@@ -180,4 +188,5 @@ WizardModal.propTypes = {
180
188
  onFinished: PropTypes.func,
181
189
  show: PropTypes.bool,
182
190
  onChangeVisible: PropTypes.func,
191
+ loadingText: PropTypes.node,
183
192
  };
@@ -1,168 +0,0 @@
1
- # WizardModal 使用示例
2
-
3
- WizardModal 是一个自动弹窗的 iframe 组件,用于在页面加载时显示向导界面。
4
-
5
- ## 基本用法
6
-
7
- ### 在 Header 组件中使用
8
-
9
- ```jsx
10
- import { Header } from '@arcblock/blocklet-ui-react';
11
-
12
- function App() {
13
- return (
14
- <Header
15
- meta={blockletMeta}
16
- // 默认不显示 wizard 按钮,设置为 true 启用
17
- showWizard={true}
18
- />
19
- );
20
- }
21
- ```
22
-
23
- ### 默认行为
24
-
25
- ```jsx
26
- // 默认不显示 wizard 按钮
27
- <Header meta={blockletMeta} />
28
-
29
- // 显示 wizard 按钮
30
- <Header meta={blockletMeta} showWizard={true} />
31
- ```
32
-
33
- ### 重置向导状态
34
-
35
- ```javascript
36
- // 清除已完成标记,下次刷新页面时会重新显示向导
37
- localStorage.removeItem('wizard-completed');
38
- window.location.reload();
39
- ```
40
-
41
- ### 启用向导
42
-
43
- ```jsx
44
- <Header
45
- meta={blockletMeta}
46
- showWizard={true} // 设置为 true 显示向导按钮
47
- />
48
- ```
49
-
50
- ### 自定义向导 URL
51
-
52
- ```jsx
53
- <Header
54
- meta={blockletMeta}
55
- wizardUrl="/.well-known/service/wizard/custom-setup"
56
- onWizardFinished={(data) => {
57
- console.log('自定义向导完成:', data);
58
- }}
59
- />
60
- ```
61
-
62
- ### 使用外部 URL
63
-
64
- ```jsx
65
- <Header
66
- meta={blockletMeta}
67
- wizardUrl="https://external-wizard.example.com/setup"
68
- onWizardFinished={(data) => {
69
- console.log('外部向导完成:', data);
70
- }}
71
- />
72
- ```
73
-
74
- ## 直接使用 WizardModal 组件
75
-
76
- ```jsx
77
- import { WizardModal } from '@arcblock/blocklet-ui-react/lib/common/wizard-modal';
78
-
79
- function MyComponent() {
80
- const [showWizard, setShowWizard] = useState(false);
81
-
82
- return (
83
- <div>
84
- <button onClick={() => setShowWizard(true)}>打开向导</button>
85
-
86
- <WizardModal
87
- open={showWizard}
88
- wizardUrl="/.well-known/service/wizard/bind-account"
89
- onFinished={(data) => {
90
- console.log('向导完成:', data);
91
- setShowWizard(false);
92
- }}
93
- />
94
- </div>
95
- );
96
- }
97
- ```
98
-
99
- ## 向导页面消息通信
100
-
101
- 向导页面可以通过 postMessage 与父页面通信:
102
-
103
- ### 向导页面发送消息
104
-
105
- ```javascript
106
- // 通知父页面向导已加载完成
107
- window.parent.postMessage(
108
- {
109
- type: 'wizard.loaded',
110
- },
111
- window.location.origin
112
- );
113
-
114
- // 通知父页面向导已完成
115
- window.parent.postMessage(
116
- {
117
- type: 'wizard.finished',
118
- data: { success: true, result: 'setup-complete' },
119
- },
120
- window.location.origin
121
- );
122
-
123
- // 通知父页面关闭向导
124
- window.parent.postMessage(
125
- {
126
- type: 'wizard.close',
127
- },
128
- window.location.origin
129
- );
130
- ```
131
-
132
- ## Props 说明
133
-
134
- ### Header 组件新增 Props
135
-
136
- | 属性 | 类型 | 默认值 | 说明 |
137
- | ---------- | ------- | ------ | ---------------- |
138
- | showWizard | boolean | false | 是否显示向导按钮 |
139
-
140
- ### WizardModal 组件 Props
141
-
142
- | 属性 | 类型 | 默认值 | 说明 |
143
- | --------------- | -------- | --------- | ------------------------------------ |
144
- | show | boolean | false | 控制弹窗显示状态 |
145
- | onFinished | function | undefined | 向导完成回调函数 |
146
- | onChangeVisible | function | undefined | 弹窗显示状态变化回调 |
147
- | onClose | function | undefined | 弹窗关闭回调(isCompleted: boolean) |
148
-
149
- ## 新增功能特性
150
-
151
- ### 1. 智能提示系统
152
-
153
- - 点击遮罩关闭时显示 tooltip 提示:"想要再次打开 wizard 可以点击这里"
154
- - Tooltip 显示 5 秒后自动消失
155
- - 完成向导后不显示 tooltip
156
- - 按钮在提示期间有闪烁动画效果
157
-
158
- ### 2. URL 状态保存
159
-
160
- - 关闭 wizard 时自动保存当前 iframe 的 URL 到 localStorage
161
- - 下次打开时直接加载上次的位置,继续之前的进度
162
- - 完成向导后重置为默认 URL
163
-
164
- ### 3. 交互优化
165
-
166
- - 点击遮罩或 ESC 键可以关闭弹窗
167
- - 关闭时会保存当前进度
168
- - 完成后自动清理临时状态