@blocklet/launcher-layout 2.13.69 → 3.0.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.
@@ -1,254 +1,163 @@
1
- import { createElement } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { getDisplayName } from '@blocklet/meta/lib/util';
4
- import DID from '@arcblock/ux/lib/DID';
5
- import get from 'lodash/get';
6
- import styled from '@emotion/styled';
7
- import MarkdownPreview from '@uiw/react-markdown-preview';
8
- import { Box, Typography } from '@mui/material';
9
- import RehypeReact from 'rehype-react';
10
- import joinURL from 'url-join';
11
- import { useCreation, useRequest } from 'ahooks';
12
- import MarkdownBody from '../markdown-body';
13
- import InfoList from '../info-list';
14
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
15
- const isFreeBlocklet = meta => {
16
- if (!meta.payment) {
17
- return true;
18
- }
19
- const priceList = (meta.payment.price || []).map(x => x.value || 0);
20
- return priceList.every(x => x === 0);
21
- };
22
- const renderAst = new RehypeReact({
23
- createElement
24
- }).Compiler;
25
- const localeData = {
1
+ import { jsxs as n, jsx as r, Fragment as b } from "react/jsx-runtime";
2
+ import { createElement as B } from "react";
3
+ import y from "prop-types";
4
+ import { getDisplayName as g } from "@blocklet/meta/lib/util";
5
+ import z from "@arcblock/ux/lib/DID";
6
+ import o from "lodash/get";
7
+ import D from "@emotion/styled";
8
+ import j from "@uiw/react-markdown-preview";
9
+ import { Typography as q, Box as N } from "@mui/material";
10
+ import R from "rehype-react";
11
+ import x from "url-join";
12
+ import { useRequest as S, useCreation as C } from "ahooks";
13
+ import I from "../markdown-body.js";
14
+ import T from "../info-list.js";
15
+ const A = (l) => l.payment ? (l.payment.price || []).map((m) => m.value || 0).every((m) => m === 0) : !0, E = new R({ createElement: B }).Compiler, i = {
26
16
  zh: {
27
17
  appinfo: {
28
- name: '应用名',
29
- version: '版本号',
30
- author: '开发者',
31
- description: '描述',
32
- community: '社区地址',
33
- documentation: '文档手册',
34
- support: '服务支持',
35
- overview: '概述',
36
- requirements: '节点版本要求'
18
+ name: "应用名",
19
+ version: "版本号",
20
+ author: "开发者",
21
+ description: "描述",
22
+ community: "社区地址",
23
+ documentation: "文档手册",
24
+ support: "服务支持",
25
+ overview: "概述",
26
+ requirements: "节点版本要求"
37
27
  }
38
28
  },
39
29
  en: {
40
30
  appinfo: {
41
- name: 'Name',
42
- version: 'Version',
43
- author: 'Author',
44
- description: 'Description',
45
- community: 'Community',
46
- documentation: 'Documentation',
47
- support: 'Support',
48
- overview: 'Overview',
49
- requirements: 'Server requirements'
31
+ name: "Name",
32
+ version: "Version",
33
+ author: "Author",
34
+ description: "Description",
35
+ community: "Community",
36
+ documentation: "Documentation",
37
+ support: "Support",
38
+ overview: "Overview",
39
+ requirements: "Server requirements"
50
40
  }
51
41
  }
52
42
  };
53
- function WizardDesc({
54
- blockletMeta,
55
- locale,
56
- handleDescEle
57
- }) {
58
- const {
59
- data
60
- } = blockletMeta;
61
-
62
- // FIXME: @zhanghan 暂且假定这里是有 registryUrl 的值的,后续需要更好的方式来判断一个 blocklet 来源于哪个 registryUrl
63
- const {
64
- registryUrl,
65
- did
66
- } = data;
67
- const name = getDisplayName({
68
- meta: data
69
- });
70
- const readmeState = useRequest(() => {
71
- if (registryUrl && did) {
72
- return fetch(joinURL(registryUrl, '/api/blocklets', did, 'readme')).then(res => res.json());
73
- }
74
- return null;
75
- }, {
76
- refreshDeps: [registryUrl, did]
77
- });
78
- const markdownSource = useCreation(() => {
79
- if (!readmeState.data) {
80
- return '';
43
+ function L({ blockletMeta: l, locale: t, handleDescEle: m = "" }) {
44
+ const { data: e } = l, { registryUrl: d, did: f } = e, u = g({
45
+ meta: e
46
+ }), p = S(
47
+ () => d && f ? fetch(x(d, "/api/blocklets", f, "readme")).then((a) => a.json()) : null,
48
+ {
49
+ refreshDeps: [d, f]
81
50
  }
82
- return readmeState.data[locale] || readmeState.data.en || readmeState.data[Object.keys(readmeState.data)[0]];
83
- }, [readmeState]);
84
- const blockletDesc = data && data.htmlAst ? renderAst(data.htmlAst) : '';
85
- const isFree = isFreeBlocklet(data);
86
- let authorInfo = get(data, 'owner.fullName');
87
- if (authorInfo) {
88
- const ownerDid = get(data, 'owner.did');
89
- if (ownerDid) {
90
- authorInfo = /*#__PURE__*/_jsxs(Box, {
91
- sx: {
92
- display: 'flex',
93
- alignItems: 'center',
94
- gap: 1
95
- },
96
- children: [authorInfo, /*#__PURE__*/_jsx(DID, {
51
+ ), k = C(() => p.data ? p.data[t] || p.data.en || p.data[Object.keys(p.data)[0]] : "", [p]), h = e && e.htmlAst ? E(e.htmlAst) : "", w = A(e);
52
+ let c = o(e, "owner.fullName");
53
+ if (c) {
54
+ const a = o(e, "owner.did");
55
+ a && (c = /* @__PURE__ */ n(N, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
56
+ c,
57
+ /* @__PURE__ */ r(
58
+ z,
59
+ {
97
60
  sx: {
98
- lineHeight: 'initial',
99
- '&::before': {
61
+ lineHeight: "initial",
62
+ "&::before": {
100
63
  content: '"("'
101
64
  },
102
- '&::after': {
65
+ "&::after": {
103
66
  content: '")"'
104
67
  }
105
68
  },
106
- did: ownerDid,
107
- compact: true,
69
+ did: a,
70
+ compact: !0,
108
71
  size: 14,
109
- locale: locale
110
- })]
111
- });
112
- }
113
- } else {
114
- authorInfo = get(data, 'author.name');
115
- }
116
- const infos = [{
117
- key: get(localeData[locale], 'appinfo.name'),
118
- value: getDisplayName({
119
- meta: data
120
- })
121
- }, {
122
- key: get(localeData[locale], 'appinfo.version'),
123
- value: data.version
124
- }, {
125
- key: get(localeData[locale], 'appinfo.author'),
126
- value: authorInfo
127
- }, {
128
- type: 'description',
129
- key: get(localeData[locale], 'appinfo.description'),
130
- value: data.description
131
- }];
132
- if (data.requirements) {
133
- infos.push({
134
- key: get(localeData[locale], 'appinfo.requirements'),
135
- value: data.requirements.server
136
- });
137
- }
138
- if (data.community) {
139
- infos.push({
140
- key: get(localeData[locale], 'appinfo.community'),
141
- value: /*#__PURE__*/_jsx("a", {
142
- href: data.community,
143
- target: "_blank",
144
- rel: "noreferrer",
145
- children: data.community
146
- })
147
- });
148
- }
149
- if (data.documentation) {
150
- infos.push({
151
- key: get(localeData[locale], 'appinfo.documentation'),
152
- value: /*#__PURE__*/_jsx("a", {
153
- href: data.documentation,
154
- target: "_blank",
155
- rel: "noreferrer",
156
- children: data.documentation
72
+ locale: t
73
+ }
74
+ )
75
+ ] }));
76
+ } else
77
+ c = o(e, "author.name");
78
+ const s = [
79
+ {
80
+ key: o(i[t], "appinfo.name"),
81
+ value: g({
82
+ meta: e
157
83
  })
158
- });
159
- }
160
- if (data.support) {
161
- infos.push({
162
- key: get(localeData[locale], 'appinfo.support'),
163
- value: /*#__PURE__*/_jsx("a", {
164
- href: `mailto:${data.support}`,
165
- target: "_blank",
166
- rel: "noreferrer",
167
- children: data.support
168
- })
169
- });
170
- }
171
- if (blockletDesc) {
172
- infos.push({
173
- key: get(localeData[locale], 'appinfo.overview'),
174
- value: ''
175
- });
176
- }
177
- let descEle;
178
- if (locale === 'zh') {
179
- descEle = /*#__PURE__*/_jsxs(_Fragment, {
180
- children: [isFree ? /*#__PURE__*/_jsxs("p", {
181
- children: ["\u60A8\u53EF\u4EE5\u514D\u8D39\u4F7F\u7528 ", /*#__PURE__*/_jsx("b", {
182
- children: name
183
- }), "\uFF1B"]
184
- }) : /*#__PURE__*/_jsxs("p", {
185
- children: ["\u60A8\u9700\u8981\u8D2D\u4E70\u624D\u80FD\u4F7F\u7528 ", /*#__PURE__*/_jsx("b", {
186
- children: name
187
- }), "\uFF1B"]
188
- }), /*#__PURE__*/_jsx("p", {
189
- children: "\u5728\u5E94\u7528\u542F\u52A8\u524D\uFF0C\u9700\u8981\u9009\u62E9\u60A8\u7684\u8282\u70B9\uFF1B"
190
- }), /*#__PURE__*/_jsx("p", {
191
- children: "\u5982\u679C\u60A8\u6CA1\u6709\u8282\u70B9\uFF0C\u6211\u4EEC\u4F1A\u5F15\u5BFC\u60A8\u521B\u5EFA\u65B0\u7684\u8282\u70B9\uFF1B"
192
- }), /*#__PURE__*/_jsx("p", {
193
- children: "\u4E0B\u9762\u4E3A\u8BE5\u5E94\u7528\u7684\u4FE1\u606F\uFF1A"
194
- })]
195
- });
196
- } else {
197
- descEle = /*#__PURE__*/_jsxs(_Fragment, {
198
- children: [isFree ? /*#__PURE__*/_jsxs("p", {
199
- children: ["You can use ", /*#__PURE__*/_jsx("b", {
200
- children: name
201
- }), " for free;"]
202
- }) : /*#__PURE__*/_jsxs("p", {
203
- children: ["You need to purchase before launch ", /*#__PURE__*/_jsx("b", {
204
- children: name
205
- }), ";"]
206
- }), /*#__PURE__*/_jsx("p", {
207
- children: "Before the blocklet starts, you need to select your Blocklet Server; "
208
- }), /*#__PURE__*/_jsx("p", {
209
- children: "If you do not have any Blocklet Server, we will guide you to create a new one; "
210
- }), /*#__PURE__*/_jsx("p", {
211
- children: "Below is the information for the blocklet: "
212
- })]
213
- });
214
- }
215
- return /*#__PURE__*/_jsxs(Container, {
216
- children: [handleDescEle || descEle, /*#__PURE__*/_jsx(InfoList, {
217
- infoList: infos
218
- }), markdownSource ? /*#__PURE__*/_jsxs("div", {
219
- className: "app-overview",
220
- children: [/*#__PURE__*/_jsx(Typography, {
221
- variant: "h5",
222
- gutterBottom: true,
223
- children: get(localeData[locale], 'appinfo.overview')
224
- }), /*#__PURE__*/_jsx(MarkdownBody, {
225
- children: /*#__PURE__*/_jsx(PostContent, {
226
- component: "div",
227
- className: "content-wrapper post-content",
228
- children: /*#__PURE__*/_jsx(MarkdownPreview, {
229
- source: markdownSource,
230
- wrapperElement: {
231
- 'data-color-mode': 'light'
232
- }
233
- // 先保留后面两个参数,可用于精细判断
234
- // eslint-disable-next-line no-unused-vars
235
- ,
236
- urlTransform: (url, key, node) => {
237
- if (url.startsWith('/')) {
238
- return joinURL(registryUrl, url);
239
- }
240
- return url;
241
- }
242
- })
243
- })
244
- })]
245
- }) : blockletDesc ? /*#__PURE__*/_jsx("div", {
246
- className: "app-overview",
247
- children: blockletDesc
248
- }) : null]
84
+ },
85
+ {
86
+ key: o(i[t], "appinfo.version"),
87
+ value: e.version
88
+ },
89
+ {
90
+ key: o(i[t], "appinfo.author"),
91
+ value: c
92
+ },
93
+ {
94
+ type: "description",
95
+ key: o(i[t], "appinfo.description"),
96
+ value: e.description
97
+ }
98
+ ];
99
+ e.requirements && s.push({
100
+ key: o(i[t], "appinfo.requirements"),
101
+ value: e.requirements.server
102
+ }), e.community && s.push({
103
+ key: o(i[t], "appinfo.community"),
104
+ value: /* @__PURE__ */ r("a", { href: e.community, target: "_blank", rel: "noreferrer", children: e.community })
105
+ }), e.documentation && s.push({
106
+ key: o(i[t], "appinfo.documentation"),
107
+ value: /* @__PURE__ */ r("a", { href: e.documentation, target: "_blank", rel: "noreferrer", children: e.documentation })
108
+ }), e.support && s.push({
109
+ key: o(i[t], "appinfo.support"),
110
+ value: /* @__PURE__ */ r("a", { href: `mailto:${e.support}`, target: "_blank", rel: "noreferrer", children: e.support })
111
+ }), h && s.push({
112
+ key: o(i[t], "appinfo.overview"),
113
+ value: ""
249
114
  });
115
+ let v;
116
+ return t === "zh" ? v = /* @__PURE__ */ n(b, { children: [
117
+ w ? /* @__PURE__ */ n("p", { children: [
118
+ "您可以免费使用 ",
119
+ /* @__PURE__ */ r("b", { children: u }),
120
+ ";"
121
+ ] }) : /* @__PURE__ */ n("p", { children: [
122
+ "您需要购买才能使用 ",
123
+ /* @__PURE__ */ r("b", { children: u }),
124
+ ";"
125
+ ] }),
126
+ /* @__PURE__ */ r("p", { children: "在应用启动前,需要选择您的节点;" }),
127
+ /* @__PURE__ */ r("p", { children: "如果您没有节点,我们会引导您创建新的节点;" }),
128
+ /* @__PURE__ */ r("p", { children: "下面为该应用的信息:" })
129
+ ] }) : v = /* @__PURE__ */ n(b, { children: [
130
+ w ? /* @__PURE__ */ n("p", { children: [
131
+ "You can use ",
132
+ /* @__PURE__ */ r("b", { children: u }),
133
+ " for free;"
134
+ ] }) : /* @__PURE__ */ n("p", { children: [
135
+ "You need to purchase before launch ",
136
+ /* @__PURE__ */ r("b", { children: u }),
137
+ ";"
138
+ ] }),
139
+ /* @__PURE__ */ r("p", { children: "Before the blocklet starts, you need to select your Blocklet Server; " }),
140
+ /* @__PURE__ */ r("p", { children: "If you do not have any Blocklet Server, we will guide you to create a new one; " }),
141
+ /* @__PURE__ */ r("p", { children: "Below is the information for the blocklet: " })
142
+ ] }), /* @__PURE__ */ n(M, { children: [
143
+ m || v,
144
+ /* @__PURE__ */ r(T, { infoList: s }),
145
+ k ? /* @__PURE__ */ n("div", { className: "app-overview", children: [
146
+ /* @__PURE__ */ r(q, { variant: "h5", gutterBottom: !0, children: o(i[t], "appinfo.overview") }),
147
+ /* @__PURE__ */ r(I, { children: /* @__PURE__ */ r(F, { component: "div", className: "content-wrapper post-content", children: /* @__PURE__ */ r(
148
+ j,
149
+ {
150
+ source: k,
151
+ wrapperElement: {
152
+ "data-color-mode": "light"
153
+ },
154
+ urlTransform: (a, P, _) => a.startsWith("/") ? x(d, a) : a
155
+ }
156
+ ) }) })
157
+ ] }) : h ? /* @__PURE__ */ r("div", { className: "app-overview", children: h }) : null
158
+ ] });
250
159
  }
251
- const PostContent = styled(Typography)`
160
+ const F = D(q)`
252
161
  width: 100%;
253
162
  word-wrap: break-word;
254
163
  word-break: break-word;
@@ -266,8 +175,7 @@ const PostContent = styled(Typography)`
266
175
  iframe {
267
176
  width: 100% !important;
268
177
  }
269
- `;
270
- const Container = styled.div`
178
+ `, M = D.div`
271
179
  .info-table {
272
180
  a {
273
181
  word-break: break-all;
@@ -298,12 +206,11 @@ const Container = styled.div`
298
206
  }
299
207
  }
300
208
  `;
301
- WizardDesc.propTypes = {
302
- blockletMeta: PropTypes.object.isRequired,
303
- locale: PropTypes.string.isRequired,
304
- handleDescEle: PropTypes.node
209
+ L.propTypes = {
210
+ blockletMeta: y.object.isRequired,
211
+ locale: y.string.isRequired,
212
+ handleDescEle: y.node
305
213
  };
306
- WizardDesc.defaultProps = {
307
- handleDescEle: ''
214
+ export {
215
+ L as default
308
216
  };
309
- export default WizardDesc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/launcher-layout",
3
- "version": "2.13.69",
3
+ "version": "3.0.0",
4
4
  "description": "Common ux components of launcher",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -13,7 +13,6 @@
13
13
  "license": "ISC",
14
14
  "main": "lib/index.js",
15
15
  "files": [
16
- "es",
17
16
  "lib",
18
17
  "LICENSE",
19
18
  "package.json",
@@ -26,9 +25,9 @@
26
25
  "scripts": {
27
26
  "lint": "eslint src",
28
27
  "lint:fix": "npm run lint -- --fix",
29
- "build": "babel src --out-dir lib --copy-files --no-copy-ignored",
28
+ "build": "vite build",
30
29
  "autoexports": "node tools/auto-exports.js",
31
- "watch": "babel src --out-dir lib -w --copy-files",
30
+ "watch": "vite build --watch",
32
31
  "precommit": "CI=1 npm run lint",
33
32
  "prepush": "CI=1 npm run lint",
34
33
  "prepublish": "npm run build"
@@ -37,33 +36,24 @@
37
36
  "url": "https://github.com/ArcBlock/ux/issues"
38
37
  },
39
38
  "peerDependencies": {
40
- "@arcblock/did-connect": "^2.11.42",
41
- "@arcblock/ux": "^2.11.42",
42
- "@mui/icons-material": "^5.15.15",
43
- "@mui/material": "^5.15.15",
44
- "react": "^18.2.0"
39
+ "@arcblock/did-connect": "workspace:*",
40
+ "@arcblock/ux": "workspace:*",
41
+ "@mui/icons-material": "^7.1.2",
42
+ "@mui/material": "^7.1.2",
43
+ "react": "^19.0.0"
45
44
  },
46
45
  "dependencies": {
47
- "@arcblock/icons": "^2.13.69",
46
+ "@arcblock/icons": "3.0.0",
48
47
  "@blocklet/meta": "^1.16.44",
49
- "@emotion/react": "^11.13.0",
50
- "@emotion/styled": "^11.13.0",
51
- "@uiw/react-markdown-preview": "^5.1.2",
52
- "ahooks": "^3.8.1",
48
+ "@emotion/react": "^11.14.0",
49
+ "@emotion/styled": "^11.14.0",
50
+ "@uiw/react-markdown-preview": "^5.1.4",
51
+ "ahooks": "^3.8.5",
53
52
  "is-empty": "^1.2.0",
54
53
  "lodash": "^4.17.21",
55
54
  "prop-types": "^15.8.1",
56
55
  "rehype-react": "^7.2.0",
57
56
  "url-join": "^4.0.1"
58
57
  },
59
- "devDependencies": {
60
- "@babel/cli": "^7.24.8",
61
- "@babel/core": "^7.25.2",
62
- "@babel/preset-env": "^7.25.3",
63
- "@babel/preset-react": "^7.24.7",
64
- "@storybook/react": "^6.5.16",
65
- "babel-plugin-inline-react-svg": "^2.0.2",
66
- "glob": "^10.4.5"
67
- },
68
- "gitHead": "d8a03a6d869bf5f7be34b448463a07c435b21cea"
58
+ "gitHead": "b001c32ca85d40d8a0784ca581bfd54d90550b24"
69
59
  }
@@ -1,82 +0,0 @@
1
- import { Grid } from '@mui/material';
2
- import Button from '@arcblock/ux/lib/Button';
3
- import LaunchResultMessage from '../../launch-result-message';
4
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
- export default function Demo() {
6
- return /*#__PURE__*/_jsxs(Grid, {
7
- container: true,
8
- spacing: 12,
9
- mt: 2,
10
- children: [/*#__PURE__*/_jsx(Grid, {
11
- item: true,
12
- xs: 12,
13
- sm: 6,
14
- md: 3,
15
- children: /*#__PURE__*/_jsx(LaunchResultMessage, {
16
- variant: "success",
17
- title: "Success Title",
18
- subTitle: "This is a success message.",
19
- footer: /*#__PURE__*/_jsx("div", {
20
- children: /*#__PURE__*/_jsx(Button, {
21
- color: "primary",
22
- variant: "contained",
23
- children: "Success Action"
24
- })
25
- })
26
- })
27
- }), /*#__PURE__*/_jsx(Grid, {
28
- item: true,
29
- xs: 12,
30
- sm: 6,
31
- md: 3,
32
- children: /*#__PURE__*/_jsx(LaunchResultMessage, {
33
- variant: "error",
34
- title: "Error Title",
35
- subTitle: "This is an error message.",
36
- footer: /*#__PURE__*/_jsx("div", {
37
- children: /*#__PURE__*/_jsx(Button, {
38
- color: "primary",
39
- variant: "contained",
40
- children: "Error Action"
41
- })
42
- })
43
- })
44
- }), /*#__PURE__*/_jsx(Grid, {
45
- item: true,
46
- xs: 12,
47
- sm: 6,
48
- md: 3,
49
- children: /*#__PURE__*/_jsx(LaunchResultMessage, {
50
- variant: "info",
51
- title: "Info Title",
52
- subTitle: "This is an info message.",
53
- footer: /*#__PURE__*/_jsx("div", {
54
- children: /*#__PURE__*/_jsx(Button, {
55
- color: "primary",
56
- variant: "contained",
57
- children: "Info Action"
58
- })
59
- })
60
- })
61
- }), /*#__PURE__*/_jsx(Grid, {
62
- item: true,
63
- xs: 12,
64
- sm: 6,
65
- md: 3,
66
- children: /*#__PURE__*/_jsx(LaunchResultMessage, {
67
- variant: "loading",
68
- title: "Loading Title",
69
- subTitle: "This is a loading message.",
70
- footer: /*#__PURE__*/_jsx("div", {
71
- children: /*#__PURE__*/_jsx(Button, {
72
- color: "primary",
73
- variant: "contained",
74
- disabled: true,
75
- children: "Loading Action"
76
- })
77
- })
78
- })
79
- })]
80
- });
81
- }
82
- Demo.propTypes = {};
@@ -1,27 +0,0 @@
1
- import { Container } from '@mui/material';
2
- import { ThemeProvider } from '@arcblock/ux/lib/Theme';
3
- import { ThemeModeToggle } from '@arcblock/ux/lib/Config';
4
- import Default from './demo/default';
5
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
- export default {
7
- title: 'Blocklet-Launcher/ResultMessage',
8
- parameters: {
9
- layout: 'fullscreen',
10
- readme: {
11
- sidebar: '<!-- PROPS -->'
12
- }
13
- },
14
- decorators: [Story => /*#__PURE__*/_jsxs(ThemeProvider, {
15
- prefer: "system",
16
- children: [/*#__PURE__*/_jsx(Container, {
17
- sx: {
18
- textAlign: 'right',
19
- py: 1
20
- },
21
- children: /*#__PURE__*/_jsx(ThemeModeToggle, {})
22
- }), /*#__PURE__*/_jsx(Story, {})]
23
- })]
24
- };
25
- Default.argTypes = {};
26
- Default.storyName = 'ResultMessage';
27
- export { Default };