@abtnode/ux 1.17.8-beta-20260104-120132-cb5b1914 → 1.17.8-beta-20260108-021819-e099f0ca

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.
@@ -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
+ };
@@ -0,0 +1,277 @@
1
+ import { Box, Button, Stack, Typography } from '@mui/material';
2
+ import AddIcon from '@mui/icons-material/Add';
3
+ import SaveIcon from '@mui/icons-material/Save';
4
+ import Dialog from '@arcblock/ux/lib/Dialog';
5
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
6
+ import { useMemoizedFn } from 'ahooks';
7
+ import { useEffect, useState } from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { defaultConfig, configTemplate, defaultAction, defaultActions, isValidActionName } from './constants';
10
+ import ActionItem from './action-item';
11
+ import AddLanguageDialog from './add-language-dialog';
12
+
13
+ // TODO: 先禁用添加新的 action
14
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
15
+ const disabledAddAction = true;
16
+ export default function AuthTextVisualMode({
17
+ open = false,
18
+ onClose = () => {},
19
+ onSave = () => {},
20
+ initialConfig = null
21
+ }) {
22
+ const {
23
+ t,
24
+ locale
25
+ } = useLocaleContext();
26
+ const [actions, setActions] = useState({});
27
+ const [expandedAction, setExpandedAction] = useState('login');
28
+ const [selectedLanguages, setSelectedLanguages] = useState({});
29
+ const [addLanguageOpen, setAddLanguageOpen] = useState(false);
30
+ const [addLanguageAction, setAddLanguageAction] = useState('');
31
+ const [newLanguage, setNewLanguage] = useState('');
32
+ const [editingAction, setEditingAction] = useState(null);
33
+ const [editingName, setEditingName] = useState('');
34
+ const currentLocale = locale || 'en';
35
+ useEffect(() => {
36
+ if (!open) return;
37
+ const parsedDialogs = initialConfig || defaultConfig;
38
+ setActions(parsedDialogs);
39
+ const dialogKeys = Object.keys(parsedDialogs);
40
+ setExpandedAction(dialogKeys[0] || 'login');
41
+ const initialSelected = {};
42
+ dialogKeys.forEach(key => {
43
+ const langs = Object.keys(parsedDialogs[key] || {});
44
+ initialSelected[key] = langs.includes(currentLocale) ? currentLocale : langs[0] || 'en';
45
+ });
46
+ setSelectedLanguages(initialSelected);
47
+ setEditingAction(null);
48
+ }, [open, initialConfig, currentLocale]);
49
+ const isActionEmpty = useMemoizedFn(actionData => {
50
+ if (!actionData) return true;
51
+ return Object.values(actionData).every(langData => !langData?.title?.trim() && !langData?.scan?.trim());
52
+ });
53
+ const canAddNewAction = useMemoizedFn(() => {
54
+ const hasEmpty = Object.keys(actions).some(key => !defaultActions.includes(key) && isActionEmpty(actions[key]));
55
+ return !hasEmpty && !actions[defaultAction];
56
+ });
57
+ const handleAddAction = useMemoizedFn(() => {
58
+ if (!canAddNewAction()) return;
59
+ setActions(prev => ({
60
+ ...prev,
61
+ [defaultAction]: configTemplate
62
+ }));
63
+ setExpandedAction(defaultAction);
64
+ setSelectedLanguages(prev => ({
65
+ ...prev,
66
+ [defaultAction]: currentLocale
67
+ }));
68
+ setEditingAction(defaultAction);
69
+ setEditingName(defaultAction);
70
+ });
71
+ const handleEditingNameChange = useMemoizedFn(e => {
72
+ const {
73
+ value
74
+ } = e.target;
75
+ if (value === '' || /^[a-z-]*$/.test(value)) {
76
+ setEditingName(value);
77
+ }
78
+ });
79
+ const handleFinishEditing = useMemoizedFn(() => {
80
+ const newName = editingName.trim();
81
+ if (!newName || !isValidActionName(newName) || newName !== editingAction && actions[newName]) {
82
+ setEditingAction(null);
83
+ return;
84
+ }
85
+ if (newName !== editingAction) {
86
+ const newActions = {};
87
+ Object.keys(actions).forEach(key => {
88
+ newActions[key === editingAction ? newName : key] = actions[key];
89
+ });
90
+ setActions(newActions);
91
+ if (expandedAction === editingAction) setExpandedAction(newName);
92
+ if (selectedLanguages[editingAction]) {
93
+ setSelectedLanguages(prev => {
94
+ const updated = {
95
+ ...prev,
96
+ [newName]: prev[editingAction]
97
+ };
98
+ delete updated[editingAction];
99
+ return updated;
100
+ });
101
+ }
102
+ }
103
+ setEditingAction(null);
104
+ });
105
+ const handleEditingKeyDown = useMemoizedFn(e => {
106
+ if (e.key === 'Enter') handleFinishEditing();else if (e.key === 'Escape') setEditingAction(null);
107
+ });
108
+ const handleDeleteAction = useMemoizedFn((actionKey, e) => {
109
+ e.stopPropagation();
110
+ const newActions = {
111
+ ...actions
112
+ };
113
+ delete newActions[actionKey];
114
+ setActions(newActions);
115
+ if (expandedAction === actionKey) {
116
+ setExpandedAction(Object.keys(newActions)[0] || false);
117
+ }
118
+ });
119
+ const handleAddLanguage = useMemoizedFn(() => {
120
+ if (!newLanguage || !addLanguageAction) return;
121
+ setActions(prev => ({
122
+ ...prev,
123
+ [addLanguageAction]: {
124
+ ...prev[addLanguageAction],
125
+ [newLanguage]: {
126
+ title: '',
127
+ scan: '',
128
+ confirm: '',
129
+ success: ''
130
+ }
131
+ }
132
+ }));
133
+ setSelectedLanguages(prev => ({
134
+ ...prev,
135
+ [addLanguageAction]: newLanguage
136
+ }));
137
+ setAddLanguageOpen(false);
138
+ });
139
+ const handleDeleteLanguage = useMemoizedFn((actionKey, langCode, e) => {
140
+ e.stopPropagation();
141
+ const actionData = actions[actionKey];
142
+ const langs = Object.keys(actionData || {});
143
+ if (langs.length <= 1) return;
144
+ const newActionData = {
145
+ ...actionData
146
+ };
147
+ delete newActionData[langCode];
148
+ setActions(prev => ({
149
+ ...prev,
150
+ [actionKey]: newActionData
151
+ }));
152
+ if (selectedLanguages[actionKey] === langCode) {
153
+ setSelectedLanguages(prev => ({
154
+ ...prev,
155
+ [actionKey]: Object.keys(newActionData)[0] || 'en'
156
+ }));
157
+ }
158
+ });
159
+ const handleSave = useMemoizedFn(() => {
160
+ onSave(JSON.stringify(actions));
161
+ onClose();
162
+ });
163
+ const addEnabled = canAddNewAction();
164
+ const dialogActions = /*#__PURE__*/_jsxs(_Fragment, {
165
+ children: [/*#__PURE__*/_jsx(Button, {
166
+ onClick: onClose,
167
+ variant: "outlined",
168
+ children: t('common.cancel')
169
+ }), /*#__PURE__*/_jsx(Button, {
170
+ onClick: handleSave,
171
+ variant: "contained",
172
+ startIcon: /*#__PURE__*/_jsx(SaveIcon, {}),
173
+ children: t('common.confirm')
174
+ })]
175
+ });
176
+ return /*#__PURE__*/_jsxs(Dialog, {
177
+ open: open,
178
+ onClose: onClose,
179
+ maxWidth: "md",
180
+ fullWidth: true,
181
+ title: t('authentication.didConnect.configDialogTitle'),
182
+ actions: dialogActions,
183
+ children: [/*#__PURE__*/_jsxs(Stack, {
184
+ spacing: 1.5,
185
+ children: [Object.keys(actions).map(actionKey => {
186
+ const actionData = actions[actionKey] || {};
187
+ const langs = Object.keys(actionData);
188
+ const selectedLang = selectedLanguages[actionKey] || langs[0] || 'en';
189
+ return /*#__PURE__*/_jsx(ActionItem, {
190
+ actionKey: actionKey,
191
+ actionData: actionData,
192
+ expanded: expandedAction === actionKey,
193
+ selectedLang: selectedLang,
194
+ editing: {
195
+ actionKey: editingAction,
196
+ name: editingName,
197
+ allActions: actions
198
+ },
199
+ onChange: {
200
+ accordion: isExpanded => setExpandedAction(isExpanded ? actionKey : false),
201
+ language: langCode => setSelectedLanguages(prev => ({
202
+ ...prev,
203
+ [actionKey]: langCode
204
+ })),
205
+ field: (field, value) => setActions(prev => ({
206
+ ...prev,
207
+ [actionKey]: {
208
+ ...prev[actionKey],
209
+ [selectedLang]: {
210
+ ...prev[actionKey]?.[selectedLang],
211
+ [field]: value
212
+ }
213
+ }
214
+ })),
215
+ startEditing: e => {
216
+ e.stopPropagation();
217
+ setEditingAction(actionKey);
218
+ setEditingName(actionKey);
219
+ },
220
+ editingName: handleEditingNameChange,
221
+ finishEditing: handleFinishEditing,
222
+ editingKeyDown: handleEditingKeyDown,
223
+ delete: e => handleDeleteAction(actionKey, e),
224
+ addLanguage: e => {
225
+ e.stopPropagation();
226
+ setAddLanguageAction(actionKey);
227
+ setNewLanguage('');
228
+ setAddLanguageOpen(true);
229
+ },
230
+ deleteLanguage: (langCode, e) => handleDeleteLanguage(actionKey, langCode, e)
231
+ }
232
+ }, actionKey);
233
+ }), !disabledAddAction && /*#__PURE__*/_jsxs(Box, {
234
+ onClick: addEnabled ? handleAddAction : undefined,
235
+ sx: {
236
+ border: '2px dashed',
237
+ borderColor: addEnabled ? 'grey.300' : 'grey.200',
238
+ borderRadius: 2,
239
+ py: 1.5,
240
+ display: 'flex',
241
+ alignItems: 'center',
242
+ justifyContent: 'center',
243
+ cursor: addEnabled ? 'pointer' : 'not-allowed',
244
+ color: addEnabled ? 'text.secondary' : 'text.disabled',
245
+ transition: 'all 0.2s',
246
+ ...(addEnabled && {
247
+ '&:hover': {
248
+ borderColor: 'primary.main',
249
+ color: 'primary.main',
250
+ bgcolor: 'primary.lighter'
251
+ }
252
+ })
253
+ },
254
+ children: [/*#__PURE__*/_jsx(AddIcon, {
255
+ sx: {
256
+ mr: 0.5
257
+ }
258
+ }), /*#__PURE__*/_jsx(Typography, {
259
+ children: t('authentication.didConnect.addNewAction')
260
+ })]
261
+ })]
262
+ }), /*#__PURE__*/_jsx(AddLanguageDialog, {
263
+ open: addLanguageOpen,
264
+ onClose: () => setAddLanguageOpen(false),
265
+ existingLanguages: Object.keys(actions[addLanguageAction] || {}),
266
+ selectedLanguage: newLanguage,
267
+ onLanguageChange: setNewLanguage,
268
+ onAdd: handleAddLanguage
269
+ })]
270
+ });
271
+ }
272
+ AuthTextVisualMode.propTypes = {
273
+ open: PropTypes.bool,
274
+ onClose: PropTypes.func,
275
+ onSave: PropTypes.func,
276
+ initialConfig: PropTypes.object
277
+ };