@abtnode/ux 1.17.8-beta-20260106-113136-b3c09e14 → 1.17.8-beta-20260108-120904-21cb5fb6

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.
@@ -2,12 +2,14 @@
2
2
  import { useContext, useMemo } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Skeleton, Box, Typography, Tooltip, keyframes } from '@mui/material';
5
+ import { useCreation } from 'ahooks';
5
6
  import { Icon } from '@iconify/react';
6
7
  import { LocaleContext } from '@arcblock/ux/lib/Locale/context';
8
+ // eslint-disable-next-line import/no-unresolved
9
+ import { formatNumber } from '@blocklet/aigne-hub/utils/util';
7
10
  import CachedIcon from '@mui/icons-material/Cached';
8
11
  import { withQuery } from 'ufo';
9
12
  import { CardWrapper, ButtonWrapper } from './basic';
10
- import { formatAmount } from '../utils';
11
13
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
14
  export default function CreditCard({
13
15
  loading = false,
@@ -35,14 +37,20 @@ export default function CreditCard({
35
37
  const isDeficit = useMemo(() => {
36
38
  return Number(credit?.creditBalance?.balance) <= 0 && Number(credit?.creditBalance?.pendingCredit) > 0;
37
39
  }, [credit]);
38
- if (!credit && !loading) {
39
- return null;
40
- }
41
40
  const {
42
41
  creditBalance,
43
42
  profileLink = '',
44
- paymentLink = ''
43
+ paymentLink = '',
44
+ creditPrefix = ''
45
45
  } = credit || {};
46
+ const creditValue = useCreation(() => {
47
+ const formattedBalance = formatNumber(creditBalance?.balance ?? 0);
48
+ const displayValue = creditPrefix ? `${creditPrefix} ${formattedBalance}` : formattedBalance;
49
+ return isDeficit ? `- ${displayValue}` : displayValue;
50
+ }, [isDeficit, creditPrefix, creditBalance?.balance]);
51
+ if (!credit && !loading) {
52
+ return null;
53
+ }
46
54
  return /*#__PURE__*/_jsx(CardWrapper, {
47
55
  children: loading ? /*#__PURE__*/_jsxs(Box, {
48
56
  sx: {
@@ -117,9 +125,7 @@ export default function CreditCard({
117
125
  sx: {
118
126
  color: !isSelfHost && isDeficit ? 'error.main' : 'text.primary'
119
127
  },
120
- children: [/*#__PURE__*/_jsx("span", {
121
- children: isSelfHost ? t('setting.aigne.infinite') : isDeficit ? `- ${formatAmount(creditBalance?.pendingCredit)}` : formatAmount(creditBalance.balance)
122
- }), !isSelfHost ? /*#__PURE__*/_jsx(Tooltip, {
128
+ children: [isSelfHost ? t('setting.aigne.infinite') : creditValue, !isSelfHost ? /*#__PURE__*/_jsx(Tooltip, {
123
129
  title: t('common.refresh'),
124
130
  children: /*#__PURE__*/_jsx(CachedIcon, {
125
131
  sx: {
@@ -0,0 +1,272 @@
1
+ import { Accordion, AccordionDetails, AccordionSummary, Box, Chip, IconButton, Stack, TextField, Typography } from '@mui/material';
2
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
3
+ import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
4
+ import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
5
+ import AddIcon from '@mui/icons-material/Add';
6
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
7
+ import PropTypes from 'prop-types';
8
+ import { defaultActions, requiredLanguages, isValidActionName, getSortedLanguages, getLanguageLabel } from './constants';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ function ActionNameEditor({
11
+ value = '',
12
+ onChange = () => {},
13
+ onBlur = () => {},
14
+ onKeyDown = () => {},
15
+ isDuplicate = false
16
+ }) {
17
+ const {
18
+ t
19
+ } = useLocaleContext();
20
+ const isInvalid = value && !isValidActionName(value);
21
+ let helperText = '';
22
+ if (isInvalid) {
23
+ helperText = t('authentication.didConnect.actionNameError');
24
+ } else if (isDuplicate) {
25
+ helperText = t('authentication.didConnect.actionNameDuplicate');
26
+ }
27
+ return /*#__PURE__*/_jsx(TextField, {
28
+ value: value,
29
+ onChange: onChange,
30
+ onBlur: onBlur,
31
+ onKeyDown: onKeyDown,
32
+ onClick: e => e.stopPropagation(),
33
+ size: "small",
34
+ variant: "standard",
35
+ autoFocus: true,
36
+ placeholder: "action-name",
37
+ helperText: helperText,
38
+ error: isInvalid || isDuplicate,
39
+ sx: {
40
+ '& .MuiInputBase-input': {
41
+ py: 0,
42
+ fontSize: 14,
43
+ fontWeight: 500
44
+ }
45
+ }
46
+ });
47
+ }
48
+ ActionNameEditor.propTypes = {
49
+ value: PropTypes.string,
50
+ onChange: PropTypes.func,
51
+ onBlur: PropTypes.func,
52
+ onKeyDown: PropTypes.func,
53
+ isDuplicate: PropTypes.bool
54
+ };
55
+ function LanguageChip({
56
+ langCode,
57
+ isSelected = false,
58
+ canDelete = false,
59
+ onSelect = () => {},
60
+ onDelete = () => {}
61
+ }) {
62
+ return /*#__PURE__*/_jsx(Chip, {
63
+ label: getLanguageLabel(langCode),
64
+ onClick: onSelect,
65
+ onDelete: canDelete ? onDelete : undefined,
66
+ size: "small",
67
+ sx: {
68
+ bgcolor: isSelected ? 'primary.main' : 'grey.100',
69
+ color: isSelected ? 'primary.contrastText' : 'text.primary',
70
+ '&:hover': {
71
+ bgcolor: isSelected ? 'primary.dark' : 'grey.200'
72
+ },
73
+ '& .MuiChip-deleteIcon': {
74
+ color: isSelected ? 'primary.contrastText' : 'text.secondary',
75
+ '&:hover': {
76
+ color: isSelected ? 'primary.contrastText' : 'error.main'
77
+ }
78
+ }
79
+ }
80
+ });
81
+ }
82
+ LanguageChip.propTypes = {
83
+ langCode: PropTypes.string.isRequired,
84
+ isSelected: PropTypes.bool,
85
+ canDelete: PropTypes.bool,
86
+ onSelect: PropTypes.func,
87
+ onDelete: PropTypes.func
88
+ };
89
+ export default function ActionItem({
90
+ actionKey,
91
+ actionData = {},
92
+ expanded = false,
93
+ selectedLang = '',
94
+ editing = {},
95
+ onChange = {}
96
+ }) {
97
+ const {
98
+ t
99
+ } = useLocaleContext();
100
+ const canEdit = !defaultActions.includes(actionKey);
101
+ const langs = getSortedLanguages(Object.keys(actionData));
102
+ const langData = actionData[selectedLang] || {};
103
+ const isEditing = editing?.actionKey === actionKey;
104
+ const isDuplicate = editing?.name && editing.name !== actionKey && editing.allActions?.[editing.name];
105
+ return /*#__PURE__*/_jsxs(Accordion, {
106
+ expanded: expanded,
107
+ onChange: (_, isExpanded) => onChange.accordion(isExpanded),
108
+ elevation: 0,
109
+ sx: {
110
+ border: '1px solid',
111
+ borderColor: 'grey.200',
112
+ borderRadius: '8px !important',
113
+ '&:before': {
114
+ display: 'none'
115
+ },
116
+ '&.Mui-expanded': {
117
+ margin: 0
118
+ }
119
+ },
120
+ children: [/*#__PURE__*/_jsxs(AccordionSummary, {
121
+ expandIcon: /*#__PURE__*/_jsx(ExpandMoreIcon, {}),
122
+ sx: {
123
+ minHeight: 48,
124
+ '& .MuiAccordionSummary-content': {
125
+ alignItems: 'center',
126
+ gap: 1
127
+ }
128
+ },
129
+ children: [isEditing ? /*#__PURE__*/_jsx(ActionNameEditor, {
130
+ value: editing.name,
131
+ onChange: onChange.editingName,
132
+ onBlur: onChange.finishEditing,
133
+ onKeyDown: onChange.editingKeyDown,
134
+ isDuplicate: isDuplicate
135
+ }) : /*#__PURE__*/_jsxs(Box, {
136
+ sx: {
137
+ display: 'flex',
138
+ alignItems: 'center',
139
+ gap: 0.5,
140
+ '&:hover .edit-icon': {
141
+ opacity: 1
142
+ }
143
+ },
144
+ children: [/*#__PURE__*/_jsx(Typography, {
145
+ sx: {
146
+ fontWeight: 500
147
+ },
148
+ children: actionKey
149
+ }), canEdit && /*#__PURE__*/_jsx(IconButton, {
150
+ className: "edit-icon",
151
+ size: "small",
152
+ onClick: onChange.startEditing,
153
+ sx: {
154
+ p: 0.25,
155
+ opacity: 0,
156
+ transition: 'opacity 0.2s',
157
+ color: 'text.secondary',
158
+ '&:hover': {
159
+ color: 'primary.main',
160
+ bgcolor: 'transparent'
161
+ }
162
+ },
163
+ children: /*#__PURE__*/_jsx(EditOutlinedIcon, {
164
+ sx: {
165
+ fontSize: 16
166
+ }
167
+ })
168
+ })]
169
+ }), canEdit && /*#__PURE__*/_jsx(IconButton, {
170
+ size: "small",
171
+ onClick: onChange.delete,
172
+ sx: {
173
+ ml: 'auto',
174
+ mr: 1,
175
+ p: 0.5,
176
+ color: 'error.main',
177
+ '&:hover': {
178
+ bgcolor: 'error.lighter'
179
+ }
180
+ },
181
+ children: /*#__PURE__*/_jsx(DeleteOutlineIcon, {
182
+ sx: {
183
+ fontSize: 20
184
+ }
185
+ })
186
+ })]
187
+ }), /*#__PURE__*/_jsxs(AccordionDetails, {
188
+ sx: {
189
+ pt: 0
190
+ },
191
+ children: [/*#__PURE__*/_jsxs(Box, {
192
+ sx: {
193
+ display: 'flex',
194
+ flexWrap: 'wrap',
195
+ alignItems: 'center',
196
+ gap: 1,
197
+ mb: 2
198
+ },
199
+ children: [/*#__PURE__*/_jsx(Typography, {
200
+ variant: "body2",
201
+ color: "text.secondary",
202
+ sx: {
203
+ flexShrink: 0
204
+ },
205
+ children: "Languages:"
206
+ }), langs.map(langCode => /*#__PURE__*/_jsx(LanguageChip, {
207
+ langCode: langCode,
208
+ isSelected: selectedLang === langCode,
209
+ canDelete: !requiredLanguages.includes(langCode),
210
+ onSelect: () => onChange.language(langCode),
211
+ onDelete: e => onChange.deleteLanguage(langCode, e)
212
+ }, langCode)), /*#__PURE__*/_jsx(Chip, {
213
+ label: `${t('common.add')}`,
214
+ onClick: onChange.addLanguage,
215
+ size: "small",
216
+ variant: "outlined",
217
+ icon: /*#__PURE__*/_jsx(AddIcon, {
218
+ sx: {
219
+ fontSize: 16
220
+ }
221
+ }),
222
+ sx: {
223
+ borderStyle: 'dashed',
224
+ '&:hover': {
225
+ bgcolor: 'action.hover'
226
+ }
227
+ }
228
+ })]
229
+ }), /*#__PURE__*/_jsxs(Stack, {
230
+ spacing: 2,
231
+ children: [/*#__PURE__*/_jsx(TextField, {
232
+ label: "Title",
233
+ value: langData.title || '',
234
+ onChange: e => onChange.field('title', e.target.value),
235
+ fullWidth: true,
236
+ size: "small"
237
+ }), /*#__PURE__*/_jsx(TextField, {
238
+ label: "Scan",
239
+ value: langData.scan || '',
240
+ onChange: e => onChange.field('scan', e.target.value),
241
+ fullWidth: true,
242
+ size: "small",
243
+ multiline: true,
244
+ minRows: 2
245
+ })]
246
+ })]
247
+ })]
248
+ });
249
+ }
250
+ ActionItem.propTypes = {
251
+ actionKey: PropTypes.string.isRequired,
252
+ actionData: PropTypes.object,
253
+ expanded: PropTypes.bool,
254
+ selectedLang: PropTypes.string,
255
+ editing: PropTypes.shape({
256
+ actionKey: PropTypes.string,
257
+ name: PropTypes.string,
258
+ allActions: PropTypes.object
259
+ }),
260
+ onChange: PropTypes.shape({
261
+ accordion: PropTypes.func,
262
+ language: PropTypes.func,
263
+ field: PropTypes.func,
264
+ startEditing: PropTypes.func,
265
+ editingName: PropTypes.func,
266
+ finishEditing: PropTypes.func,
267
+ editingKeyDown: PropTypes.func,
268
+ delete: PropTypes.func,
269
+ addLanguage: PropTypes.func,
270
+ deleteLanguage: PropTypes.func
271
+ })
272
+ };
@@ -0,0 +1,67 @@
1
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, FormControl, MenuItem, Select, Typography } from '@mui/material';
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import PropTypes from 'prop-types';
4
+ import { baseLanguages } from '@blocklet/constant';
5
+ import { getLanguageLabel } from './constants';
6
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
+ export default function AddLanguageDialog({
8
+ open,
9
+ onClose,
10
+ existingLanguages,
11
+ selectedLanguage,
12
+ onLanguageChange,
13
+ onAdd
14
+ }) {
15
+ const {
16
+ t
17
+ } = useLocaleContext();
18
+ const availableLanguages = baseLanguages.filter(lang => !existingLanguages.includes(lang.code));
19
+ return /*#__PURE__*/_jsxs(Dialog, {
20
+ open: open,
21
+ onClose: onClose,
22
+ maxWidth: "xs",
23
+ fullWidth: true,
24
+ children: [/*#__PURE__*/_jsx(DialogTitle, {
25
+ children: t('authentication.didConnect.addLanguage')
26
+ }), /*#__PURE__*/_jsx(DialogContent, {
27
+ children: /*#__PURE__*/_jsx(FormControl, {
28
+ fullWidth: true,
29
+ sx: {
30
+ mt: 1
31
+ },
32
+ children: /*#__PURE__*/_jsx(Select, {
33
+ value: selectedLanguage,
34
+ onChange: e => onLanguageChange(e.target.value),
35
+ displayEmpty: true,
36
+ size: "small",
37
+ renderValue: value => value ? getLanguageLabel(value) : /*#__PURE__*/_jsx(Typography, {
38
+ color: "text.secondary",
39
+ children: t('authentication.didConnect.selectLanguage')
40
+ }),
41
+ children: availableLanguages.map(lang => /*#__PURE__*/_jsx(MenuItem, {
42
+ value: lang.code,
43
+ children: lang.name
44
+ }, lang.code))
45
+ })
46
+ })
47
+ }), /*#__PURE__*/_jsxs(DialogActions, {
48
+ children: [/*#__PURE__*/_jsx(Button, {
49
+ onClick: onClose,
50
+ children: t('common.cancel')
51
+ }), /*#__PURE__*/_jsx(Button, {
52
+ onClick: onAdd,
53
+ variant: "contained",
54
+ disabled: !selectedLanguage,
55
+ children: t('common.add')
56
+ })]
57
+ })]
58
+ });
59
+ }
60
+ AddLanguageDialog.propTypes = {
61
+ open: PropTypes.bool.isRequired,
62
+ onClose: PropTypes.func.isRequired,
63
+ existingLanguages: PropTypes.array.isRequired,
64
+ selectedLanguage: PropTypes.string.isRequired,
65
+ onLanguageChange: PropTypes.func.isRequired,
66
+ onAdd: PropTypes.func.isRequired
67
+ };
@@ -0,0 +1,74 @@
1
+ import { baseLanguages } from '@blocklet/constant';
2
+ export const defaultConfig = {
3
+ login: {
4
+ en: {
5
+ title: 'Login',
6
+ scan: 'Login with one of the following methods',
7
+ confirm: 'Confirm connection in your DID Wallet',
8
+ success: 'Successfully logged in'
9
+ },
10
+ zh: {
11
+ title: '登录',
12
+ scan: '请使用下面的方式完成登录',
13
+ confirm: '在 DID Wallet 中确认连接',
14
+ success: '登录成功'
15
+ }
16
+ },
17
+ 'switch-profile': {
18
+ en: {
19
+ title: 'Switch Profile',
20
+ scan: 'Use DID Wallet to switch profile',
21
+ confirm: 'Select profile in your DID Wallet',
22
+ success: 'Profile updated'
23
+ },
24
+ zh: {
25
+ title: '切换个人信息',
26
+ scan: '请使用 DID Wallet 来切换个人信息',
27
+ confirm: '在 DID Wallet 中选择个人信息',
28
+ success: '个人信息已经更新'
29
+ }
30
+ },
31
+ 'switch-passport': {
32
+ en: {
33
+ title: 'Switch Passport',
34
+ scan: 'Use DID Wallet to switch passport',
35
+ confirm: 'Select passport in your DID Wallet',
36
+ success: 'Passport and session updated'
37
+ },
38
+ zh: {
39
+ title: '切换通行证',
40
+ scan: '请使用 DID Wallet 来切换通行证',
41
+ confirm: '在 DID Wallet 中选择通行证',
42
+ success: '通行证和会话已经更新'
43
+ }
44
+ }
45
+ };
46
+ export const configTemplate = {
47
+ en: {
48
+ title: '',
49
+ scan: '',
50
+ confirm: '',
51
+ success: ''
52
+ },
53
+ zh: {
54
+ title: '',
55
+ scan: '',
56
+ confirm: '',
57
+ success: ''
58
+ }
59
+ };
60
+ export const defaultAction = 'new-action';
61
+ export const defaultActions = Object.keys(defaultConfig);
62
+ export const requiredLanguages = ['zh', 'en'];
63
+ export const isValidActionName = name => /^[a-z][a-z-]*$/.test(name);
64
+ export const getSortedLanguages = langs => {
65
+ const sorted = [];
66
+ if (langs.includes('zh')) sorted.push('zh');
67
+ if (langs.includes('en')) sorted.push('en');
68
+ langs.filter(lang => !requiredLanguages.includes(lang)).forEach(lang => sorted.push(lang));
69
+ return sorted;
70
+ };
71
+ export const getLanguageLabel = code => {
72
+ const lang = baseLanguages.find(l => l.code === code);
73
+ return lang ? lang.name : code;
74
+ };