@arcblock/ux 2.5.48 → 2.5.49

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.
@@ -52,6 +52,6 @@ function useCopy(_ref) {
52
52
  containerRef,
53
53
  copied,
54
54
  copy,
55
- texts: translations[locale]
55
+ texts: translations[locale] || translations.en
56
56
  };
57
57
  }
@@ -34,7 +34,7 @@ function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(
34
34
 
35
35
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
36
36
 
37
- async function submitContactForm(_ref, fields, context) {
37
+ function submitContactForm(_ref, fields, context) {
38
38
  let {
39
39
  formId,
40
40
  portalId
@@ -10,12 +10,16 @@ exports.useLocaleContext = useLocaleContext;
10
10
 
11
11
  var _react = require("react");
12
12
 
13
+ var _get = _interopRequireDefault(require("lodash/get"));
14
+
13
15
  var _propTypes = _interopRequireDefault(require("prop-types"));
14
16
 
15
17
  var _jsCookie = _interopRequireDefault(require("js-cookie"));
16
18
 
17
19
  var _browserLang = _interopRequireDefault(require("./browser-lang"));
18
20
 
21
+ var _util = require("./util");
22
+
19
23
  var _Util = require("../Util");
20
24
 
21
25
  var _jsxRuntime = require("react/jsx-runtime");
@@ -40,7 +44,7 @@ const getLocaleFromSearchParams = function getLocaleFromSearchParams(languages)
40
44
  let url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.location.href;
41
45
  const locale = new URL(url).searchParams.get('locale');
42
46
 
43
- if (languages.find(x => x.value === locale)) {
47
+ if (languages.find(x => x.code === locale)) {
44
48
  return locale;
45
49
  }
46
50
 
@@ -63,9 +67,9 @@ const getLocale = function getLocale() {
63
67
 
64
68
  let languages = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
65
69
  const langParams = {
66
- languages: languages.map(item => item.value),
67
- // 取 languages 首个元素的 value 值, 如果不存在则取 'en'
68
- fallback: (languages === null || languages === void 0 ? void 0 : (_languages$ = languages[0]) === null || _languages$ === void 0 ? void 0 : _languages$.value) || 'en'
70
+ languages: languages.map(item => item.code),
71
+ // 取 languages 首个元素的 code 值, 如果不存在则取 'en'
72
+ fallback: (languages === null || languages === void 0 ? void 0 : (_languages$ = languages[0]) === null || _languages$ === void 0 ? void 0 : _languages$.code) || 'en'
69
73
  };
70
74
  return getLocaleFromSearchParams(languages) || _jsCookie.default.get(cookieName) || (0, _browserLang.default)(langParams);
71
75
  };
@@ -80,7 +84,25 @@ const setLocale = locale => {
80
84
 
81
85
  exports.setLocale = setLocale;
82
86
 
83
- const replace = (template, data) => template.replace(/{(\w*)}/g, (m, key) => data.hasOwnProperty(key) ? data[key] : '');
87
+ const getLanguages = arg => {
88
+ const env = (0, _get.default)(window, 'blocklet.languages');
89
+
90
+ if (Array.isArray(env) && env.length) {
91
+ return env;
92
+ }
93
+
94
+ if (Array.isArray(arg) && arg.length) {
95
+ return arg;
96
+ }
97
+
98
+ return [{
99
+ code: 'en',
100
+ name: 'English'
101
+ }, {
102
+ code: 'zh',
103
+ name: '简体中文'
104
+ }];
105
+ };
84
106
 
85
107
  const LocaleContext = /*#__PURE__*/(0, _react.createContext)();
86
108
  exports.LocaleContext = LocaleContext;
@@ -100,7 +122,8 @@ function LocaleProvider(_ref) {
100
122
  } = _ref,
101
123
  rest = _objectWithoutProperties(_ref, _excluded);
102
124
 
103
- const [currentLocale, setCurrentLocale] = (0, _react.useState)(locale || getLocale(languages));
125
+ const langs = getLanguages(languages);
126
+ const [currentLocale, setCurrentLocale] = (0, _react.useState)(locale || getLocale(langs));
104
127
 
105
128
  const changeLocale = newLocale => {
106
129
  setCurrentLocale(newLocale);
@@ -108,7 +131,7 @@ function LocaleProvider(_ref) {
108
131
  };
109
132
 
110
133
  (0, _react.useEffect)(() => {
111
- const tmpLocale = locale || getLocale(languages);
134
+ const tmpLocale = locale || getLocale(langs);
112
135
 
113
136
  if (tmpLocale !== currentLocale) {
114
137
  changeLocale(locale);
@@ -116,30 +139,14 @@ function LocaleProvider(_ref) {
116
139
 
117
140
  }, [locale]);
118
141
 
119
- const translate = (key, data) => {
120
- if (!translations[currentLocale] || !translations[currentLocale][key]) {
121
- var _translations$fallbac;
122
-
123
- console.warn("Warning: no ".concat(key, " translation of ").concat(currentLocale));
124
-
125
- if (fallbackLocale && (_translations$fallbac = translations[fallbackLocale]) !== null && _translations$fallbac !== void 0 && _translations$fallbac[key]) {
126
- var _translations$fallbac2;
127
-
128
- return replace((_translations$fallbac2 = translations[fallbackLocale]) === null || _translations$fallbac2 === void 0 ? void 0 : _translations$fallbac2[key], data);
129
- }
130
-
131
- return key;
132
- }
133
-
134
- return replace(translations[currentLocale][key], data);
135
- };
142
+ const t = (key, data) => (0, _util.translate)(translations, key, currentLocale, fallbackLocale, data);
136
143
 
137
144
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(Provider, {
138
145
  value: _objectSpread({
139
146
  locale: currentLocale,
140
147
  changeLocale,
141
- t: translate,
142
- languages
148
+ t,
149
+ languages: langs
143
150
  }, rest),
144
151
  children: children
145
152
  });
@@ -157,18 +164,12 @@ LocaleProvider.propTypes = {
157
164
  // 会影响 translate(key) 的结果 - 当 key 无效时查找 fallbackLocale 对应的翻译结果
158
165
  fallbackLocale: _propTypes.default.string,
159
166
  languages: _propTypes.default.arrayOf(_propTypes.default.shape({
160
- value: _propTypes.default.string,
161
- text: _propTypes.default.string
167
+ code: _propTypes.default.string,
168
+ name: _propTypes.default.string
162
169
  }))
163
170
  };
164
171
  LocaleProvider.defaultProps = {
165
172
  locale: '',
166
173
  fallbackLocale: '',
167
- languages: [{
168
- value: 'en',
169
- text: 'English'
170
- }, {
171
- value: 'zh',
172
- text: '简体中文'
173
- }]
174
+ languages: []
174
175
  };
@@ -58,12 +58,12 @@ const languages = {
58
58
  nativeName: 'Русский'
59
59
  },
60
60
  zh: {
61
- name: 'Chinese',
61
+ name: 'Simplified Chinese',
62
62
  nativeName: '简体中文'
63
63
  },
64
64
  tw: {
65
- name: 'Chinese',
66
- nativeName: '繁体中文'
65
+ name: 'Traditional Chinese',
66
+ nativeName: '繁體中文'
67
67
  }
68
68
  };
69
69
  exports.map = languages;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = LocaleSelector;
7
7
 
8
8
  var _react = require("react");
9
9
 
@@ -86,12 +86,15 @@ function LocaleSelector(props) {
86
86
  }
87
87
  };
88
88
 
89
- function onClose(e) {
89
+ const onClose = e => {
90
90
  var _anchorEl$current;
91
91
 
92
- if ((_anchorEl$current = anchorEl.current) !== null && _anchorEl$current !== void 0 && _anchorEl$current.contains(e.target)) return;
92
+ if ((_anchorEl$current = anchorEl.current) !== null && _anchorEl$current !== void 0 && _anchorEl$current.contains(e.target)) {
93
+ return;
94
+ }
95
+
93
96
  setOpen(false);
94
- }
97
+ };
95
98
 
96
99
  const ButtonComponent = showText ? _Button.default : _IconButton.default;
97
100
  const handleEventProps = popperType === 'hover' ? {
@@ -133,7 +136,7 @@ function LocaleSelector(props) {
133
136
  children: [renderIcon, showText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
134
137
  component: "strong",
135
138
  className: "trigger-text",
136
- children: languages.find(x => x.value === locale).text
139
+ children: languages.find(x => x.code === locale).name
137
140
  }) : '']
138
141
  })
139
142
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Popper.default, _objectSpread(_objectSpread({
@@ -148,17 +151,17 @@ function LocaleSelector(props) {
148
151
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_MenuList.default, {
149
152
  children: languages.map(_ref => {
150
153
  let {
151
- value,
152
- text
154
+ code,
155
+ name
153
156
  } = _ref;
154
157
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_MenuItem.default, {
155
158
  className: "locale-item",
156
- onClick: () => onSelect(value, text),
159
+ onClick: () => onSelect(code, name),
157
160
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Check.default, {
158
- className: value === locale ? 'check-icon check-icon-visible' : 'check-icon',
161
+ className: code === locale ? 'check-icon check-icon-visible' : 'check-icon',
159
162
  fontSize: "small"
160
- }), text]
161
- }, value);
163
+ }), name]
164
+ }, code);
162
165
  })
163
166
  })
164
167
  })
@@ -183,8 +186,6 @@ LocaleSelector.defaultProps = {
183
186
  popperType: 'click',
184
187
  icon: null
185
188
  };
186
- var _default = LocaleSelector;
187
- exports.default = _default;
188
189
  const Div = (0, _Theme.styled)('div', {
189
190
  shouldForwardProp: prop => prop !== 'dark'
190
191
  })(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n display: inline-block;\n\n .trigger {\n display: flex;\n flex-direction: column;\n justify-content: center;\n font-size: 14px;\n white-space: nowrap;\n\n .trigger-text {\n margin-left: 5px;\n font-size: 14px;\n color: ", ";\n }\n }\n\n .locales {\n background: ", ";\n box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);\n }\n\n .locale-item {\n font-size: 16px;\n font-style: normal;\n font-stretch: normal;\n line-height: normal;\n letter-spacing: 2px;\n text-align: center;\n color: ", ";\n cursor: pointer;\n display: flex;\n padding: 16px;\n align-items: center;\n .check-icon {\n visibility: hidden;\n margin-right: 4px;\n }\n .check-icon-visible {\n visibility: visible;\n }\n }\n"])), props => (0, _Util.getColor)(props), props => (0, _Util.getBackground)(props), props => (0, _Util.getColor)(props));
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.translate = exports.t = exports.replace = void 0;
7
+
8
+ /* eslint-disable no-prototype-builtins */
9
+ const replace = (template, data) => template.replace(/{(\w*)}/g, (m, key) => data.hasOwnProperty(key) ? data[key] : '');
10
+
11
+ exports.replace = replace;
12
+
13
+ const translate = function translate(translations, key, locale) {
14
+ let fallbackLocale = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'en';
15
+ let data = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
16
+
17
+ if (!translations[locale] || !translations[locale][key]) {
18
+ var _translations$fallbac;
19
+
20
+ console.warn("Warning: no ".concat(key, " translation of ").concat(locale));
21
+
22
+ if (fallbackLocale && (_translations$fallbac = translations[fallbackLocale]) !== null && _translations$fallbac !== void 0 && _translations$fallbac[key]) {
23
+ var _translations$fallbac2;
24
+
25
+ return replace((_translations$fallbac2 = translations[fallbackLocale]) === null || _translations$fallbac2 === void 0 ? void 0 : _translations$fallbac2[key], data);
26
+ }
27
+
28
+ return key;
29
+ }
30
+
31
+ return replace(translations[locale][key], data);
32
+ };
33
+
34
+ exports.translate = translate;
35
+ const t = translate;
36
+ exports.t = t;
@@ -52,7 +52,8 @@ const useLocale = locale => {
52
52
  } = (0, _context.useLocaleContext)() || {
53
53
  locale: 'en'
54
54
  };
55
- return locale || localeFromContext;
55
+ const result = locale || localeFromContext;
56
+ return _translations.default[result] ? result : 'en';
56
57
  }; // 404
57
58
 
58
59
 
@@ -145,12 +146,12 @@ function ComingSoon(_ref6) {
145
146
  locale = useLocale(locale);
146
147
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_result.default, _objectSpread({
147
148
  icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledInfoIcon, {}),
148
- title: _translations.default[locale]['coming-soon'].title,
149
- description: _translations.default[locale]['coming-soon'].description
149
+ title: _translations.default[locale].comingSoon.title,
150
+ description: _translations.default[locale].comingSoon.description
150
151
  }, rest));
151
152
  }
152
153
 
153
- ComingSoon.status = 'coming-soon'; // info, 与其它 status 不同, title/description 需要使用方自己传入
154
+ ComingSoon.status = 'comingSoon'; // info, 与其它 status 不同, title/description 需要使用方自己传入
154
155
 
155
156
  function Info(props) {
156
157
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_result.default, _objectSpread({
@@ -16,7 +16,7 @@ var _default = {
16
16
  },
17
17
  500: {
18
18
  title: '500 - Internal Server Error',
19
- description: 'An internal server error has occured. Please try again later.'
19
+ description: 'An internal server error has occurred. Please try again later.'
20
20
  },
21
21
  error: {
22
22
  title: 'Application Error',
@@ -26,7 +26,7 @@ var _default = {
26
26
  title: 'Offline for maintenance',
27
27
  description: 'This app is undergoing maintenance right now. Please check back later.'
28
28
  },
29
- 'coming-soon': {
29
+ comingSoon: {
30
30
  title: 'Coming Soon',
31
31
  description: "Our website is under construction. We'll be here soon with our new website."
32
32
  }
@@ -52,7 +52,7 @@ var _default = {
52
52
  title: '维护中',
53
53
  description: '应用程序正在进行维护。请稍后再查看。'
54
54
  },
55
- 'coming-soon': {
55
+ comingSoon: {
56
56
  title: '即将上线',
57
57
  description: '我们的网站正在建设中。我们很快就会在这里推出我们的新网站。'
58
58
  }
@@ -60,31 +60,25 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
60
60
 
61
61
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
62
62
 
63
- const messages = {
64
- zh: {
65
- switchDid: '切换账户',
66
- switchProfile: '切换用户信息',
67
- switchPassport: '切换通行证',
68
- disconnect: '退出',
69
- connect: '登录',
70
- openInWallet: '打开 DID 钱包'
71
- },
63
+ const translations = {
72
64
  en: {
73
65
  switchDid: 'Switch DID',
74
66
  switchProfile: 'Switch Profile',
75
67
  switchPassport: 'Switch Passport',
76
68
  disconnect: 'Disconnect',
77
69
  connect: 'Connect',
78
- openInWallet: 'Open DID Wallet'
79
- }
80
- };
81
- const translations = {
82
- en: {
70
+ openInWallet: 'Open DID Wallet',
83
71
  alreadyBindOAuth: 'Already bind Auth0',
84
72
  bind: 'Bind ',
85
73
  thirdParty: 'Third Party Login'
86
74
  },
87
75
  zh: {
76
+ switchDid: '切换账户',
77
+ switchProfile: '切换用户信息',
78
+ switchPassport: '切换通行证',
79
+ disconnect: '退出',
80
+ connect: '登录',
81
+ openInWallet: '打开 DID 钱包',
88
82
  // NOTE: 目前只有 Auth0,展示出具体的第三方名字会更好
89
83
  alreadyBindOAuth: '已绑定 Auth0 账号',
90
84
  bind: '绑定',
@@ -129,6 +123,7 @@ function SessionManager(_ref) {
129
123
  } = _ref,
130
124
  rest = _objectWithoutProperties(_ref, _excluded);
131
125
 
126
+ const translation = translations[locale] || translations.en;
132
127
  const userAnchorRef = (0, _react.useRef)(null);
133
128
  const {
134
129
  logoutOAuth,
@@ -190,7 +185,7 @@ function SessionManager(_ref) {
190
185
  style: {
191
186
  lineHeight: '25px'
192
187
  },
193
- children: messages[locale].connect
188
+ children: translation.connect
194
189
  })]
195
190
  })) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.IconButton, _objectSpread(_objectSpread({}, rest), {}, {
196
191
  onClick: _onLogin,
@@ -283,7 +278,6 @@ function SessionManager(_ref) {
283
278
  }
284
279
  }
285
280
 
286
- const message = messages[locale] || messages.en;
287
281
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
288
282
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.IconButton, _objectSpread(_objectSpread({
289
283
  ref: userAnchorRef,
@@ -404,7 +398,7 @@ function SessionManager(_ref) {
404
398
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
405
399
  component: _OpenIn.default,
406
400
  className: "session-manager-menu-icon"
407
- }), message.openInWallet]
401
+ }), translation.openInWallet]
408
402
  }), !!switchDid && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
409
403
  className: "session-manager-menu-item",
410
404
  onClick: _onSwitchDid,
@@ -412,7 +406,7 @@ function SessionManager(_ref) {
412
406
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
413
407
  component: _Switch.default,
414
408
  className: "session-manager-menu-icon"
415
- }), message.switchDid]
409
+ }), translation.switchDid]
416
410
  }), !!switchProfile && hasBindWallet && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
417
411
  className: "session-manager-menu-item",
418
412
  onClick: _onSwitchProfile,
@@ -420,7 +414,7 @@ function SessionManager(_ref) {
420
414
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
421
415
  component: _PersonOutline.default,
422
416
  className: "session-manager-menu-icon"
423
- }), message.switchProfile]
417
+ }), translation.switchProfile]
424
418
  }), !!switchPassport && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
425
419
  className: "session-manager-menu-item",
426
420
  onClick: _onSwitchPassport,
@@ -428,7 +422,7 @@ function SessionManager(_ref) {
428
422
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
429
423
  component: _VpnKeyOutlined.default,
430
424
  className: "session-manager-menu-icon"
431
- }), message.switchPassport]
425
+ }), translation.switchPassport]
432
426
  }), oauthConfigList.length > 0 && !hasBindAccount && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
433
427
  className: "session-manager-menu-item",
434
428
  onClick: _onBindWallet,
@@ -436,7 +430,7 @@ function SessionManager(_ref) {
436
430
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
437
431
  component: _Link.default,
438
432
  className: "session-manager-menu-icon"
439
- }), isRawWalletAccount ? "".concat(translations[locale].bind).concat(translations[locale].thirdParty) : "".concat(translations[locale].bind, "DID Wallet")]
433
+ }), isRawWalletAccount ? "".concat(translation.bind).concat(translation.thirdParty) : "".concat(translation.bind, "DID Wallet")]
440
434
  }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.MenuItem, {
441
435
  className: "session-manager-menu-item",
442
436
  onClick: _onLogout,
@@ -445,7 +439,7 @@ function SessionManager(_ref) {
445
439
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.SvgIcon, {
446
440
  component: _Disconnect.default,
447
441
  className: "session-manager-menu-icon"
448
- }), message.disconnect]
442
+ }), translation.disconnect]
449
443
  })]
450
444
  })
451
445
  })
@@ -41,7 +41,8 @@ let _info = noop;
41
41
  * @returns {import('notistack').ProviderContext['enqueueSnackbar']}
42
42
  */
43
43
 
44
- const genFn = (enqueueSnackbar, variant) => (message, opts) => {
44
+ const genFn = (enqueueSnackbar, variant) => function (message) {
45
+ let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
45
46
  enqueueSnackbar(message, _objectSpread({
46
47
  autoHideDuration: 3000,
47
48
  variant
@@ -99,7 +100,9 @@ var _default = {
99
100
  * @param {import('notistack').OptionsObject} options
100
101
  * @returns {import('notistack').SnackbarKey}
101
102
  */
102
- success: function success(message, options) {
103
+ success: function success(message) {
104
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
105
+
103
106
  for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
104
107
  args[_key - 2] = arguments[_key];
105
108
  }
@@ -113,7 +116,9 @@ var _default = {
113
116
  * @param {import('notistack').OptionsObject} options
114
117
  * @returns {import('notistack').SnackbarKey}
115
118
  */
116
- error: function error(message, options) {
119
+ error: function error(message) {
120
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
121
+
117
122
  for (var _len2 = arguments.length, args = new Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
118
123
  args[_key2 - 2] = arguments[_key2];
119
124
  }
@@ -127,7 +132,9 @@ var _default = {
127
132
  * @param {import('notistack').OptionsObject} options
128
133
  * @returns {import('notistack').SnackbarKey}
129
134
  */
130
- warning: function warning(message, options) {
135
+ warning: function warning(message) {
136
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
137
+
131
138
  for (var _len3 = arguments.length, args = new Array(_len3 > 2 ? _len3 - 2 : 0), _key3 = 2; _key3 < _len3; _key3++) {
132
139
  args[_key3 - 2] = arguments[_key3];
133
140
  }
@@ -141,7 +148,9 @@ var _default = {
141
148
  * @param {import('notistack').OptionsObject} options
142
149
  * @returns {import('notistack').SnackbarKey}
143
150
  */
144
- info: function info(message, options) {
151
+ info: function info(message) {
152
+ let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
153
+
145
154
  for (var _len4 = arguments.length, args = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
146
155
  args[_key4 - 2] = arguments[_key4];
147
156
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ux",
3
- "version": "2.5.48",
3
+ "version": "2.5.49",
4
4
  "description": "Common used react components for arcblock products",
5
5
  "keywords": [
6
6
  "react",
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "scripts": {
19
19
  "lint": "eslint src tests",
20
+ "lint:fix": "npm run lint -- --fix",
20
21
  "build": "babel src --out-dir lib --copy-files --no-copy-ignored",
21
22
  "watch": "babel src --out-dir lib -w --copy-files --no-copy-ignored",
22
23
  "precommit": "CI=1 npm run lint",
@@ -40,16 +41,17 @@
40
41
  "babel-plugin-inline-react-svg": "^1.1.2",
41
42
  "eslint-plugin-react-hooks": "^4.6.0",
42
43
  "jest": "^28.1.3",
44
+ "jest-environment-jsdom": "^29.5.0",
43
45
  "moment-timezone": "^0.5.37"
44
46
  },
45
47
  "peerDependencies": {
46
48
  "react": ">=18.1.0"
47
49
  },
48
- "gitHead": "79c5d91c07cd0d7c76286b9865d902a27acc163f",
50
+ "gitHead": "984f01cb1503cac77e52885893a9f50269f3da91",
49
51
  "dependencies": {
50
52
  "@arcblock/did-motif": "^1.1.10",
51
- "@arcblock/icons": "^2.5.48",
52
- "@arcblock/react-hooks": "^2.5.48",
53
+ "@arcblock/icons": "^2.5.49",
54
+ "@arcblock/react-hooks": "^2.5.49",
53
55
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
54
56
  "@emotion/react": "^11.10.4",
55
57
  "@emotion/styled": "^11.10.4",
@@ -58,6 +60,7 @@
58
60
  "@mui/icons-material": "^5.10.6",
59
61
  "@mui/material": "^5.10.8",
60
62
  "@solana/qr-code-styling": "^1.6.0-beta.0",
63
+ "@testing-library/react": "^14.0.0",
61
64
  "axios": "^0.27.2",
62
65
  "base64-url": "^2.3.3",
63
66
  "copy-to-clipboard": "^3.3.2",
@@ -60,6 +60,7 @@ const DidAddress = forwardRef(
60
60
  // eslint-disable-next-line no-param-reassign
61
61
  locale = 'en';
62
62
  }
63
+
63
64
  // 避免 unmounted 后 setTimeout handler 依然改变 state
64
65
  const isMounted = useMountedState();
65
66
 
@@ -36,6 +36,6 @@ export default function useCopy({ content, locale = 'en' }) {
36
36
  containerRef,
37
37
  copied,
38
38
  copy,
39
- texts: translations[locale],
39
+ texts: translations[locale] || translations.en,
40
40
  };
41
41
  }
@@ -11,7 +11,7 @@ import { warn as deprecatedWarn } from '../Util/deprecate';
11
11
  import Button from '../Button';
12
12
  import { styled } from '../Theme';
13
13
 
14
- export async function submitContactForm({ formId, portalId }, fields, context) {
14
+ export function submitContactForm({ formId, portalId }, fields, context) {
15
15
  const url = `https://api.hsforms.com/submissions/v3/integration/submit/${portalId}/${formId}`;
16
16
  return axios
17
17
  .post(url, {
@@ -1,9 +1,12 @@
1
1
  /* eslint-disable no-prototype-builtins */
2
2
  import { createContext, useState, useEffect, useContext } from 'react';
3
+ import get from 'lodash/get';
3
4
  import PropTypes from 'prop-types';
4
5
  import Cookie from 'js-cookie';
5
6
 
6
7
  import browserLang from './browser-lang';
8
+ import { translate } from './util';
9
+
7
10
  import { getCookieOptions } from '../Util';
8
11
 
9
12
  const cookieName = 'nf_lang';
@@ -11,7 +14,7 @@ const cookieName = 'nf_lang';
11
14
  // 跨应用传递多语言选择的方式是在 query string 中添加 locale 参数,LocaleSelector 要高优先级遵守这个参数
12
15
  const getLocaleFromSearchParams = (languages, url = window.location.href) => {
13
16
  const locale = new URL(url).searchParams.get('locale');
14
- if (languages.find((x) => x.value === locale)) {
17
+ if (languages.find((x) => x.code === locale)) {
15
18
  return locale;
16
19
  }
17
20
  return null;
@@ -28,24 +31,39 @@ const setLocaleParam = (locale, url = window.location.href) => {
28
31
 
29
32
  const getLocale = (languages = []) => {
30
33
  const langParams = {
31
- languages: languages.map((item) => item.value),
32
- // 取 languages 首个元素的 value 值, 如果不存在则取 'en'
33
- fallback: languages?.[0]?.value || 'en',
34
+ languages: languages.map((item) => item.code),
35
+ // 取 languages 首个元素的 code 值, 如果不存在则取 'en'
36
+ fallback: languages?.[0]?.code || 'en',
34
37
  };
35
38
  return getLocaleFromSearchParams(languages) || Cookie.get(cookieName) || browserLang(langParams);
36
39
  };
40
+
37
41
  const setLocale = (locale) => {
38
42
  Cookie.set(cookieName, locale, getCookieOptions());
39
43
  setLocaleParam(locale);
40
44
  };
41
45
 
42
- const replace = (template, data) =>
43
- template.replace(/{(\w*)}/g, (m, key) => (data.hasOwnProperty(key) ? data[key] : ''));
46
+ const getLanguages = (arg) => {
47
+ const env = get(window, 'blocklet.languages');
48
+ if (Array.isArray(env) && env.length) {
49
+ return env;
50
+ }
51
+
52
+ if (Array.isArray(arg) && arg.length) {
53
+ return arg;
54
+ }
55
+
56
+ return [
57
+ { code: 'en', name: 'English' },
58
+ { code: 'zh', name: '简体中文' },
59
+ ];
60
+ };
44
61
 
45
62
  const LocaleContext = createContext();
46
63
  const { Provider, Consumer } = LocaleContext;
47
64
  function LocaleProvider({ children, locale, fallbackLocale, translations, languages, ...rest }) {
48
- const [currentLocale, setCurrentLocale] = useState(locale || getLocale(languages));
65
+ const langs = getLanguages(languages);
66
+ const [currentLocale, setCurrentLocale] = useState(locale || getLocale(langs));
49
67
 
50
68
  const changeLocale = (newLocale) => {
51
69
  setCurrentLocale(newLocale);
@@ -53,28 +71,16 @@ function LocaleProvider({ children, locale, fallbackLocale, translations, langua
53
71
  };
54
72
 
55
73
  useEffect(() => {
56
- const tmpLocale = locale || getLocale(languages);
74
+ const tmpLocale = locale || getLocale(langs);
57
75
  if (tmpLocale !== currentLocale) {
58
76
  changeLocale(locale);
59
77
  }
60
78
  // eslint-disable-next-line react-hooks/exhaustive-deps
61
79
  }, [locale]);
62
80
 
63
- const translate = (key, data) => {
64
- if (!translations[currentLocale] || !translations[currentLocale][key]) {
65
- console.warn(`Warning: no ${key} translation of ${currentLocale}`);
66
- if (fallbackLocale && translations[fallbackLocale]?.[key]) {
67
- return replace(translations[fallbackLocale]?.[key], data);
68
- }
69
- return key;
70
- }
71
-
72
- return replace(translations[currentLocale][key], data);
73
- };
81
+ const t = (key, data) => translate(translations, key, currentLocale, fallbackLocale, data);
74
82
 
75
- return (
76
- <Provider value={{ locale: currentLocale, changeLocale, t: translate, languages, ...rest }}>{children}</Provider>
77
- );
83
+ return <Provider value={{ locale: currentLocale, changeLocale, t, languages: langs, ...rest }}>{children}</Provider>;
78
84
  }
79
85
 
80
86
  function useLocaleContext() {
@@ -88,16 +94,13 @@ LocaleProvider.propTypes = {
88
94
  locale: PropTypes.string,
89
95
  // 会影响 translate(key) 的结果 - 当 key 无效时查找 fallbackLocale 对应的翻译结果
90
96
  fallbackLocale: PropTypes.string,
91
- languages: PropTypes.arrayOf(PropTypes.shape({ value: PropTypes.string, text: PropTypes.string })),
97
+ languages: PropTypes.arrayOf(PropTypes.shape({ code: PropTypes.string, name: PropTypes.string })),
92
98
  };
93
99
 
94
100
  LocaleProvider.defaultProps = {
95
101
  locale: '',
96
102
  fallbackLocale: '',
97
- languages: [
98
- { value: 'en', text: 'English' },
99
- { value: 'zh', text: '简体中文' },
100
- ],
103
+ languages: [],
101
104
  };
102
105
 
103
106
  export { LocaleProvider, Consumer as LocaleConsumer, LocaleContext, useLocaleContext, setLocale, getLocale };
@@ -45,12 +45,12 @@ const languages = {
45
45
  nativeName: 'Русский',
46
46
  },
47
47
  zh: {
48
- name: 'Chinese',
48
+ name: 'Simplified Chinese',
49
49
  nativeName: '简体中文',
50
50
  },
51
51
  tw: {
52
- name: 'Chinese',
53
- nativeName: '繁体中文',
52
+ name: 'Traditional Chinese',
53
+ nativeName: '繁體中文',
54
54
  },
55
55
  };
56
56
 
@@ -17,7 +17,7 @@ import { getColor, getBackground } from '../Util';
17
17
  import { LocaleContext } from './context';
18
18
  import { styled, useTheme } from '../Theme';
19
19
 
20
- function LocaleSelector(props) {
20
+ export default function LocaleSelector(props) {
21
21
  const { showText, popperProps, popperType, icon: Icon, size, ...rest } = props;
22
22
  const { locale, changeLocale, languages } = useContext(LocaleContext);
23
23
  const anchorEl = useRef(null);
@@ -33,10 +33,12 @@ function LocaleSelector(props) {
33
33
  }
34
34
  };
35
35
 
36
- function onClose(e) {
37
- if (anchorEl.current?.contains(e.target)) return;
36
+ const onClose = (e) => {
37
+ if (anchorEl.current?.contains(e.target)) {
38
+ return;
39
+ }
38
40
  setOpen(false);
39
- }
41
+ };
40
42
 
41
43
  const ButtonComponent = showText ? Button : IconButton;
42
44
 
@@ -72,7 +74,7 @@ function LocaleSelector(props) {
72
74
 
73
75
  {showText ? (
74
76
  <Typography component="strong" className="trigger-text">
75
- {languages.find((x) => x.value === locale).text}
77
+ {languages.find((x) => x.code === locale).name}
76
78
  </Typography>
77
79
  ) : (
78
80
  ''
@@ -84,13 +86,13 @@ function LocaleSelector(props) {
84
86
  <div className="locales">
85
87
  <ClickAwayListener onClickAway={onClose}>
86
88
  <MenuList>
87
- {languages.map(({ value, text }) => (
88
- <MenuItem key={value} className="locale-item" onClick={() => onSelect(value, text)}>
89
+ {languages.map(({ code, name }) => (
90
+ <MenuItem key={code} className="locale-item" onClick={() => onSelect(code, name)}>
89
91
  <CheckIcon
90
- className={value === locale ? 'check-icon check-icon-visible' : 'check-icon'}
92
+ className={code === locale ? 'check-icon check-icon-visible' : 'check-icon'}
91
93
  fontSize="small"
92
94
  />
93
- {text}
95
+ {name}
94
96
  </MenuItem>
95
97
  ))}
96
98
  </MenuList>
@@ -119,8 +121,6 @@ LocaleSelector.defaultProps = {
119
121
  icon: null,
120
122
  };
121
123
 
122
- export default LocaleSelector;
123
-
124
124
  const Div = styled('div', {
125
125
  shouldForwardProp: (prop) => prop !== 'dark',
126
126
  })`
@@ -0,0 +1,17 @@
1
+ /* eslint-disable no-prototype-builtins */
2
+ export const replace = (template, data) =>
3
+ template.replace(/{(\w*)}/g, (m, key) => (data.hasOwnProperty(key) ? data[key] : ''));
4
+
5
+ export const translate = (translations, key, locale, fallbackLocale = 'en', data = {}) => {
6
+ if (!translations[locale] || !translations[locale][key]) {
7
+ console.warn(`Warning: no ${key} translation of ${locale}`);
8
+ if (fallbackLocale && translations[fallbackLocale]?.[key]) {
9
+ return replace(translations[fallbackLocale]?.[key], data);
10
+ }
11
+ return key;
12
+ }
13
+
14
+ return replace(translations[locale][key], data);
15
+ };
16
+
17
+ export const t = translate;
@@ -11,7 +11,8 @@ import { useTheme } from '../Theme';
11
11
  const useLocale = (locale) => {
12
12
  locale = ['zh', 'en'].includes(locale) ? locale : '';
13
13
  const { locale: localeFromContext } = useLocaleContext() || { locale: 'en' };
14
- return locale || localeFromContext;
14
+ const result = locale || localeFromContext;
15
+ return translations[result] ? result : 'en';
15
16
  };
16
17
 
17
18
  // 404
@@ -90,13 +91,13 @@ export function ComingSoon({ locale, ...rest }) {
90
91
  return (
91
92
  <Result
92
93
  icon={<StyledInfoIcon />}
93
- title={translations[locale]['coming-soon'].title}
94
- description={translations[locale]['coming-soon'].description}
94
+ title={translations[locale].comingSoon.title}
95
+ description={translations[locale].comingSoon.description}
95
96
  {...rest}
96
97
  />
97
98
  );
98
99
  }
99
- ComingSoon.status = 'coming-soon';
100
+ ComingSoon.status = 'comingSoon';
100
101
 
101
102
  // info, 与其它 status 不同, title/description 需要使用方自己传入
102
103
  export function Info(props) {
@@ -10,7 +10,7 @@ export default {
10
10
  },
11
11
  500: {
12
12
  title: '500 - Internal Server Error',
13
- description: 'An internal server error has occured. Please try again later.',
13
+ description: 'An internal server error has occurred. Please try again later.',
14
14
  },
15
15
  error: {
16
16
  title: 'Application Error',
@@ -20,7 +20,7 @@ export default {
20
20
  title: 'Offline for maintenance',
21
21
  description: 'This app is undergoing maintenance right now. Please check back later.',
22
22
  },
23
- 'coming-soon': {
23
+ comingSoon: {
24
24
  title: 'Coming Soon',
25
25
  description: "Our website is under construction. We'll be here soon with our new website.",
26
26
  },
@@ -47,7 +47,7 @@ export default {
47
47
  title: '维护中',
48
48
  description: '应用程序正在进行维护。请稍后再查看。',
49
49
  },
50
- 'coming-soon': {
50
+ comingSoon: {
51
51
  title: '即将上线',
52
52
  description: '我们的网站正在建设中。我们很快就会在这里推出我们的新网站。',
53
53
  },
@@ -19,15 +19,7 @@ import { styled } from '../Theme';
19
19
  import DidAvatar from '../Avatar';
20
20
  import DidAddress from '../Address';
21
21
 
22
- const messages = {
23
- zh: {
24
- switchDid: '切换账户',
25
- switchProfile: '切换用户信息',
26
- switchPassport: '切换通行证',
27
- disconnect: '退出',
28
- connect: '登录',
29
- openInWallet: '打开 DID 钱包',
30
- },
22
+ const translations = {
31
23
  en: {
32
24
  switchDid: 'Switch DID',
33
25
  switchProfile: 'Switch Profile',
@@ -35,15 +27,17 @@ const messages = {
35
27
  disconnect: 'Disconnect',
36
28
  connect: 'Connect',
37
29
  openInWallet: 'Open DID Wallet',
38
- },
39
- };
40
- const translations = {
41
- en: {
42
30
  alreadyBindOAuth: 'Already bind Auth0',
43
31
  bind: 'Bind ',
44
32
  thirdParty: 'Third Party Login',
45
33
  },
46
34
  zh: {
35
+ switchDid: '切换账户',
36
+ switchProfile: '切换用户信息',
37
+ switchPassport: '切换通行证',
38
+ disconnect: '退出',
39
+ connect: '登录',
40
+ openInWallet: '打开 DID 钱包',
47
41
  // NOTE: 目前只有 Auth0,展示出具体的第三方名字会更好
48
42
  alreadyBindOAuth: '已绑定 Auth0 账号',
49
43
  bind: '绑定',
@@ -75,6 +69,7 @@ function SessionManager({
75
69
  size,
76
70
  ...rest
77
71
  }) {
72
+ const translation = translations[locale] || translations.en;
78
73
  const userAnchorRef = useRef(null);
79
74
  const { logoutOAuth, bindOAuth, configs: oauthConfigs, switchOAuthPassport } = useOAuth();
80
75
  const [userOpen, setUserOpen] = useState(false);
@@ -118,7 +113,7 @@ function SessionManager({
118
113
  {...rest}
119
114
  data-cy="sessionManager-login">
120
115
  <AccountIcon />
121
- <span style={{ lineHeight: '25px' }}>{messages[locale].connect}</span>
116
+ <span style={{ lineHeight: '25px' }}>{translation.connect}</span>
122
117
  </Button>
123
118
  ) : (
124
119
  <IconButton {...rest} onClick={_onLogin} data-cy="sessionManager-login" size="medium">
@@ -192,8 +187,6 @@ function SessionManager({
192
187
  }
193
188
  }
194
189
 
195
- const message = messages[locale] || messages.en;
196
-
197
190
  return (
198
191
  <>
199
192
  <IconButton
@@ -301,7 +294,7 @@ function SessionManager({
301
294
  href="https://www.abtwallet.io/"
302
295
  target="_blank">
303
296
  <SvgIcon component={OpenInIcon} className="session-manager-menu-icon" />
304
- {message.openInWallet}
297
+ {translation.openInWallet}
305
298
  </MenuItem>
306
299
  )}
307
300
  {!!switchDid && (
@@ -310,7 +303,7 @@ function SessionManager({
310
303
  onClick={_onSwitchDid}
311
304
  data-cy="sessionManager-switch-trigger">
312
305
  <SvgIcon component={SwitchDidIcon} className="session-manager-menu-icon" />
313
- {message.switchDid}
306
+ {translation.switchDid}
314
307
  </MenuItem>
315
308
  )}
316
309
  {!!switchProfile && hasBindWallet && (
@@ -319,7 +312,7 @@ function SessionManager({
319
312
  onClick={_onSwitchProfile}
320
313
  data-cy="sessionManager-switch-profile-trigger">
321
314
  <SvgIcon component={SwitchProfileIcon} className="session-manager-menu-icon" />
322
- {message.switchProfile}
315
+ {translation.switchProfile}
323
316
  </MenuItem>
324
317
  )}
325
318
  {!!switchPassport && (
@@ -328,7 +321,7 @@ function SessionManager({
328
321
  onClick={_onSwitchPassport}
329
322
  data-cy="sessionManager-switch-passport-trigger">
330
323
  <SvgIcon component={SwitchPassportIcon} className="session-manager-menu-icon" />
331
- {message.switchPassport}
324
+ {translation.switchPassport}
332
325
  </MenuItem>
333
326
  )}
334
327
  {oauthConfigList.length > 0 && !hasBindAccount && (
@@ -338,8 +331,8 @@ function SessionManager({
338
331
  data-cy="sessionManager-bind-trigger">
339
332
  <SvgIcon component={BindWalletIcon} className="session-manager-menu-icon" />
340
333
  {isRawWalletAccount
341
- ? `${translations[locale].bind}${translations[locale].thirdParty}`
342
- : `${translations[locale].bind}DID Wallet`}
334
+ ? `${translation.bind}${translation.thirdParty}`
335
+ : `${translation.bind}DID Wallet`}
343
336
  </MenuItem>
344
337
  )}
345
338
 
@@ -349,7 +342,7 @@ function SessionManager({
349
342
  disabled={disableLogout}
350
343
  data-cy="sessionManager-logout-trigger">
351
344
  <SvgIcon component={DisconnectIcon} className="session-manager-menu-icon" />
352
- {message.disconnect}
345
+ {translation.disconnect}
353
346
  </MenuItem>
354
347
  </MenuList>
355
348
  </ClickAwayListener>
@@ -19,13 +19,15 @@ let info = noop;
19
19
  * @param {import('notistack').VariantType} variant
20
20
  * @returns {import('notistack').ProviderContext['enqueueSnackbar']}
21
21
  */
22
- const genFn = (enqueueSnackbar, variant) => (message, opts) => {
23
- enqueueSnackbar(message, {
24
- autoHideDuration: 3000,
25
- variant,
26
- ...opts,
27
- });
28
- };
22
+ const genFn =
23
+ (enqueueSnackbar, variant) =>
24
+ (message, opts = {}) => {
25
+ enqueueSnackbar(message, {
26
+ autoHideDuration: 3000,
27
+ variant,
28
+ ...opts,
29
+ });
30
+ };
29
31
 
30
32
  // eslint-disable-next-line react/prop-types
31
33
  function ToastProvider({ children }) {
@@ -73,7 +75,7 @@ export default {
73
75
  * @param {import('notistack').OptionsObject} options
74
76
  * @returns {import('notistack').SnackbarKey}
75
77
  */
76
- success: (message, options, ...args) => success(message, options, ...args),
78
+ success: (message, options = {}, ...args) => success(message, options, ...args),
77
79
 
78
80
  /**
79
81
  *
@@ -81,7 +83,7 @@ export default {
81
83
  * @param {import('notistack').OptionsObject} options
82
84
  * @returns {import('notistack').SnackbarKey}
83
85
  */
84
- error: (message, options, ...args) => error(message, options, ...args),
86
+ error: (message, options = {}, ...args) => error(message, options, ...args),
85
87
 
86
88
  /**
87
89
  *
@@ -89,7 +91,7 @@ export default {
89
91
  * @param {import('notistack').OptionsObject} options
90
92
  * @returns {import('notistack').SnackbarKey}
91
93
  */
92
- warning: (message, options, ...args) => warning(message, options, ...args),
94
+ warning: (message, options = {}, ...args) => warning(message, options, ...args),
93
95
 
94
96
  /**
95
97
  *
@@ -97,5 +99,5 @@ export default {
97
99
  * @param {import('notistack').OptionsObject} options
98
100
  * @returns {import('notistack').SnackbarKey}
99
101
  */
100
- info: (message, options, ...args) => info(message, options, ...args),
102
+ info: (message, options = {}, ...args) => info(message, options, ...args),
101
103
  };