@gadmin2n/schematics 0.0.110 → 0.0.112

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.
Files changed (19) hide show
  1. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +0 -12
  2. package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +1 -1
  3. package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/taihu.ts +8 -2
  4. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/authProvider.ts +26 -27
  5. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/DevShell.tsx +19 -0
  6. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/OnboardingModal.tsx +101 -0
  7. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/dev-shell/style.css +129 -0
  8. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +0 -24
  9. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +17 -28
  10. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +15 -2
  11. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/en/common.json +10 -9
  12. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/locales/zh_CN/common.json +12 -11
  13. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasCell.tsx +103 -0
  14. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasComponentLibrary.tsx +449 -0
  15. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasPage.tsx +794 -713
  16. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/CanvasToolbar.tsx +3 -239
  17. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/canvasContextMenuRegistry.tsx +3 -2
  18. package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/canvas/hooks/useCanvasContextMenu.tsx +79 -8
  19. package/package.json +1 -1
@@ -161,7 +161,7 @@
161
161
  "emptyHint": "从组件库拖拽组件到此处",
162
162
  "exitPreview": "退出预览",
163
163
  "config": "配置",
164
- "configCharts": "配置显示图表与顺序",
164
+ "configCharts": "配置可切换的图表类型",
165
165
  "editCode": "编辑代码",
166
166
  "duplicate": "复制",
167
167
  "delete": "删除",
@@ -247,14 +247,14 @@
247
247
  "changePageSize": "修改分页数量",
248
248
  "removePagination": "移除分页",
249
249
  "addPagination": "添加分页",
250
- "direction": "方向",
250
+ "direction": "图表方向",
251
251
  "vertical": "纵向",
252
252
  "horizontal": "横向",
253
253
  "hideGrid": "隐藏网格",
254
254
  "showGrid": "显示网格",
255
255
  "hideLabel": "隐藏数据标签",
256
256
  "showLabel": "显示数据标签",
257
- "switchVariant": "切换样式",
257
+ "switchVariant": "切换显示样式",
258
258
  "pie": "饼图",
259
259
  "ring": "环形图",
260
260
  "topN": "显示项数",
@@ -264,22 +264,23 @@
264
264
  "showDots": "显示坐标点",
265
265
  "hideDotsLabel": "隐藏坐标点数据",
266
266
  "showDotsLabel": "显示坐标点数据",
267
- "disableStacked": "关闭堆叠",
268
- "enableStacked": "开启堆叠",
269
- "disablePercent": "关闭百分比",
270
- "enablePercent": "开启百分比",
271
- "disableArea": "关闭面积",
272
- "enableArea": "开启面积",
267
+ "disableStacked": "关闭数据堆叠",
268
+ "enableStacked": "开启数据堆叠",
269
+ "disablePercent": "关闭百分比堆叠",
270
+ "enablePercent": "开启百分比堆叠",
271
+ "disableArea": "关闭面积填充",
272
+ "enableArea": "开启面积填充",
273
273
  "disableSmooth": "关闭拟合曲线",
274
274
  "enableSmooth": "开启拟合曲线",
275
- "switchTo": "切换到",
275
+ "switchTo": "切换图表类型",
276
276
  "showDownload": "显示下载按钮",
277
277
  "hideDownload": "隐藏下载按钮",
278
278
  "enableSorting": "启用排序",
279
279
  "disableSorting": "禁用排序",
280
280
  "enableFiltering": "启用过滤",
281
281
  "disableFiltering": "禁用过滤",
282
- "configColumns": "配置列"
282
+ "configColumns": "配置列",
283
+ "visibilityGroup": "显示元素"
283
284
  },
284
285
  "modal": {
285
286
  "columnConfigTitle": "列配置",
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
+ import { Tooltip } from 'antd';
3
+ import { CopyOutlined, DeleteOutlined, MoreOutlined } from '@ant-design/icons';
2
4
  import IsolatedLivePreview from './IsolatedLivePreview';
3
5
  import { useIsAgentAllowed } from 'config/agentAllowed';
4
6
 
@@ -10,6 +12,9 @@ interface CanvasCellProps extends React.HTMLAttributes<HTMLDivElement> {
10
12
  onClick: (e: React.MouseEvent) => void;
11
13
  onDoubleClick: (e: React.MouseEvent) => void;
12
14
  onContextMenu: (e: React.MouseEvent) => void;
15
+ onDuplicate?: () => void;
16
+ onDelete?: () => void;
17
+ onMore?: (e: React.MouseEvent) => void;
13
18
  className?: string;
14
19
  style?: React.CSSProperties;
15
20
  children?: React.ReactNode; // react-grid-layout injects resize handles here
@@ -26,6 +31,9 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
26
31
  onClick,
27
32
  onDoubleClick,
28
33
  onContextMenu,
34
+ onDuplicate,
35
+ onDelete,
36
+ onMore,
29
37
  className,
30
38
  style,
31
39
  children,
@@ -35,6 +43,7 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
35
43
  ) => {
36
44
  const isSection = componentType === 'Section';
37
45
  const isAgentAllowed = useIsAgentAllowed();
46
+ const showToolbar = !isPreview && isAgentAllowed && selected;
38
47
 
39
48
  return (
40
49
  <div
@@ -77,6 +86,84 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
77
86
  >
78
87
  <IsolatedLivePreview code={code} />
79
88
  </div>
89
+
90
+ {/* 选中态悬浮工具栏 */}
91
+ {showToolbar && (
92
+ <div
93
+ onMouseDown={(e) => e.stopPropagation()}
94
+ onClick={(e) => e.stopPropagation()}
95
+ style={{
96
+ position: 'absolute',
97
+ top: 6,
98
+ right: 6,
99
+ zIndex: 10,
100
+ display: 'flex',
101
+ alignItems: 'center',
102
+ gap: 2,
103
+ padding: 2,
104
+ background: '#fff',
105
+ border: '1px solid #d6e4ff',
106
+ borderRadius: 6,
107
+ boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
108
+ }}
109
+ >
110
+ <Tooltip title="复制">
111
+ <button
112
+ type="button"
113
+ onClick={(e) => {
114
+ e.stopPropagation();
115
+ onDuplicate?.();
116
+ }}
117
+ style={toolbarBtnStyle}
118
+ onMouseEnter={(e) =>
119
+ (e.currentTarget.style.background = '#f0f5ff')
120
+ }
121
+ onMouseLeave={(e) =>
122
+ (e.currentTarget.style.background = 'transparent')
123
+ }
124
+ >
125
+ <CopyOutlined />
126
+ </button>
127
+ </Tooltip>
128
+ <Tooltip title="更多">
129
+ <button
130
+ type="button"
131
+ onClick={(e) => {
132
+ e.stopPropagation();
133
+ onMore?.(e);
134
+ }}
135
+ style={toolbarBtnStyle}
136
+ onMouseEnter={(e) =>
137
+ (e.currentTarget.style.background = '#f0f5ff')
138
+ }
139
+ onMouseLeave={(e) =>
140
+ (e.currentTarget.style.background = 'transparent')
141
+ }
142
+ >
143
+ <MoreOutlined />
144
+ </button>
145
+ </Tooltip>
146
+ <Tooltip title="删除">
147
+ <button
148
+ type="button"
149
+ onClick={(e) => {
150
+ e.stopPropagation();
151
+ onDelete?.();
152
+ }}
153
+ style={{ ...toolbarBtnStyle, color: '#ff4d4f' }}
154
+ onMouseEnter={(e) =>
155
+ (e.currentTarget.style.background = '#fff1f0')
156
+ }
157
+ onMouseLeave={(e) =>
158
+ (e.currentTarget.style.background = 'transparent')
159
+ }
160
+ >
161
+ <DeleteOutlined />
162
+ </button>
163
+ </Tooltip>
164
+ </div>
165
+ )}
166
+
80
167
  {/* Resize handles injected by react-grid-layout */}
81
168
  {children}
82
169
  </div>
@@ -84,6 +171,22 @@ const CanvasCell = React.forwardRef<HTMLDivElement, CanvasCellProps>(
84
171
  },
85
172
  );
86
173
 
174
+ const toolbarBtnStyle: React.CSSProperties = {
175
+ border: 'none',
176
+ background: 'transparent',
177
+ width: 24,
178
+ height: 24,
179
+ borderRadius: 4,
180
+ cursor: 'pointer',
181
+ display: 'flex',
182
+ alignItems: 'center',
183
+ justifyContent: 'center',
184
+ fontSize: 14,
185
+ color: '#555',
186
+ padding: 0,
187
+ transition: 'background 120ms ease',
188
+ };
189
+
87
190
  CanvasCell.displayName = 'CanvasCell';
88
191
 
89
192
  export default CanvasCell;
@@ -0,0 +1,449 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
+ import { Input, Popover, Tooltip, Button } from 'antd';
3
+ import {
4
+ SearchOutlined,
5
+ CaretDownOutlined,
6
+ CaretRightOutlined,
7
+ AppstoreOutlined,
8
+ MenuFoldOutlined,
9
+ MenuUnfoldOutlined,
10
+ } from '@ant-design/icons';
11
+ import ComponentThumbnail from './ComponentThumbnail';
12
+ import { CANVAS_COMPONENTS, CANVAS_DEFAULTS } from './canvasDefaults';
13
+ import { useTranslation } from 'react-i18next';
14
+ import { getComponentLabel, getVariantLabel } from './canvasI18n';
15
+
16
+ // ─── 组件分类 ─────────────────────────────────────────────────────────────────
17
+
18
+ interface CategoryDef {
19
+ key: string;
20
+ /** i18n key under canvas.libraryCategories.* */
21
+ labelKey: string;
22
+ defaultLabel: string;
23
+ /** 包含的组件 type,按显示顺序 */
24
+ types: string[];
25
+ }
26
+
27
+ const CATEGORIES: CategoryDef[] = [
28
+ {
29
+ key: 'data',
30
+ labelKey: 'data',
31
+ defaultLabel: '数据展示',
32
+ types: ['NumCard', 'Table'],
33
+ },
34
+ {
35
+ key: 'chart',
36
+ labelKey: 'chart',
37
+ defaultLabel: '图表',
38
+ types: ['BarChart', 'LineChart', 'PieChart', 'RadarChart', 'TreemapChart'],
39
+ },
40
+ {
41
+ key: 'map',
42
+ labelKey: 'map',
43
+ defaultLabel: '地图',
44
+ types: ['WorldMap'],
45
+ },
46
+ ];
47
+
48
+ // ─── Props ───────────────────────────────────────────────────────────────────
49
+
50
+ interface CanvasComponentLibraryProps {
51
+ /** 是否折叠成窄条(仅显示展开按钮) */
52
+ collapsed: boolean;
53
+ onToggleCollapsed: () => void;
54
+ /** 点击 item 时直接添加到画布。code 为指定 variant 代码,留空走默认 */
55
+ onAdd: (componentType: string, code?: string) => void;
56
+ }
57
+
58
+ // ─── Component ───────────────────────────────────────────────────────────────
59
+
60
+ const CanvasComponentLibrary: React.FC<CanvasComponentLibraryProps> = ({
61
+ collapsed,
62
+ onToggleCollapsed,
63
+ onAdd,
64
+ }) => {
65
+ const { t } = useTranslation();
66
+ const [keyword, setKeyword] = useState('');
67
+ const [openCats, setOpenCats] = useState<Record<string, boolean>>({
68
+ data: true,
69
+ chart: true,
70
+ map: true,
71
+ });
72
+
73
+ const handleVariantDragStart = useCallback(
74
+ (e: React.DragEvent, componentType: string, variantCode: string) => {
75
+ e.dataTransfer.setData('componentType', componentType);
76
+ e.dataTransfer.setData('variantCode', variantCode);
77
+ e.dataTransfer.setData(
78
+ `x-component-type/${componentType.toLowerCase()}`,
79
+ '',
80
+ );
81
+ e.dataTransfer.effectAllowed = 'copy';
82
+ },
83
+ [],
84
+ );
85
+
86
+ // ── 关键字过滤 ──
87
+ const filteredCats = useMemo(() => {
88
+ const kw = keyword.trim().toLowerCase();
89
+ return CATEGORIES.map((cat) => ({
90
+ ...cat,
91
+ types: cat.types.filter((type) => {
92
+ if (!CANVAS_COMPONENTS.includes(type)) return false;
93
+ if (!kw) return true;
94
+ const label = getComponentLabel(type, t).toLowerCase();
95
+ return label.includes(kw) || type.toLowerCase().includes(kw);
96
+ }),
97
+ })).filter((cat) => cat.types.length > 0);
98
+ }, [keyword, t]);
99
+
100
+ // ── 折叠态:窄条只展示展开按钮 ──
101
+ if (collapsed) {
102
+ return (
103
+ <div
104
+ style={{
105
+ width: 40,
106
+ flexShrink: 0,
107
+ background: '#fff',
108
+ borderRight: '1px solid #eaeaea',
109
+ display: 'flex',
110
+ flexDirection: 'column',
111
+ alignItems: 'center',
112
+ paddingTop: 12,
113
+ }}
114
+ >
115
+ <Tooltip
116
+ title={t('canvas.library.expand', { defaultValue: '展开组件库' })}
117
+ placement="right"
118
+ >
119
+ <Button
120
+ type="text"
121
+ size="small"
122
+ icon={<MenuUnfoldOutlined />}
123
+ onClick={onToggleCollapsed}
124
+ />
125
+ </Tooltip>
126
+ <div
127
+ style={{
128
+ marginTop: 8,
129
+ color: '#bbb',
130
+ fontSize: 11,
131
+ writingMode: 'vertical-rl',
132
+ letterSpacing: 2,
133
+ }}
134
+ >
135
+ <AppstoreOutlined style={{ marginRight: 4 }} />
136
+ {t('canvas.componentLib')}
137
+ </div>
138
+ </div>
139
+ );
140
+ }
141
+
142
+ return (
143
+ <div
144
+ style={{
145
+ width: 240,
146
+ flexShrink: 0,
147
+ background: '#fff',
148
+ borderRight: '1px solid #eaeaea',
149
+ display: 'flex',
150
+ flexDirection: 'column',
151
+ overflow: 'hidden',
152
+ }}
153
+ >
154
+ {/* ── Header ── */}
155
+ <div
156
+ style={{
157
+ display: 'flex',
158
+ alignItems: 'center',
159
+ justifyContent: 'space-between',
160
+ padding: '10px 12px',
161
+ borderBottom: '1px solid #f0f0f0',
162
+ }}
163
+ >
164
+ <span
165
+ style={{
166
+ fontSize: 13,
167
+ fontWeight: 600,
168
+ color: '#1a1a1a',
169
+ display: 'inline-flex',
170
+ alignItems: 'center',
171
+ gap: 6,
172
+ }}
173
+ >
174
+ <AppstoreOutlined style={{ color: '#4361ee' }} />
175
+ {t('canvas.componentLib')}
176
+ </span>
177
+ <Tooltip title={t('canvas.library.collapse', { defaultValue: '收起' })}>
178
+ <Button
179
+ type="text"
180
+ size="small"
181
+ icon={<MenuFoldOutlined />}
182
+ onClick={onToggleCollapsed}
183
+ />
184
+ </Tooltip>
185
+ </div>
186
+
187
+ {/* ── Search ── */}
188
+ <div style={{ padding: '8px 12px' }}>
189
+ <Input
190
+ allowClear
191
+ size="small"
192
+ placeholder={t('canvas.library.searchPlaceholder', {
193
+ defaultValue: '搜索组件',
194
+ })}
195
+ prefix={<SearchOutlined style={{ color: '#bfbfbf' }} />}
196
+ value={keyword}
197
+ onChange={(e) => setKeyword(e.target.value)}
198
+ />
199
+ </div>
200
+
201
+ {/* ── Categories ── */}
202
+ <div style={{ flex: 1, overflowY: 'auto', padding: '4px 8px 12px' }}>
203
+ {filteredCats.length === 0 && (
204
+ <div
205
+ style={{
206
+ textAlign: 'center',
207
+ color: '#bfbfbf',
208
+ fontSize: 12,
209
+ padding: '24px 0',
210
+ }}
211
+ >
212
+ {t('canvas.library.empty', { defaultValue: '没有匹配的组件' })}
213
+ </div>
214
+ )}
215
+ {filteredCats.map((cat) => {
216
+ const open = openCats[cat.key] ?? true;
217
+ return (
218
+ <div key={cat.key} style={{ marginBottom: 4 }}>
219
+ {/* Category header */}
220
+ <div
221
+ onClick={() =>
222
+ setOpenCats((prev) => ({ ...prev, [cat.key]: !open }))
223
+ }
224
+ style={{
225
+ display: 'flex',
226
+ alignItems: 'center',
227
+ gap: 4,
228
+ padding: '6px 4px',
229
+ cursor: 'pointer',
230
+ userSelect: 'none',
231
+ fontSize: 12,
232
+ fontWeight: 600,
233
+ color: '#666',
234
+ }}
235
+ >
236
+ {open ? <CaretDownOutlined /> : <CaretRightOutlined />}
237
+ {t(`canvas.library.categories.${cat.labelKey}`, {
238
+ defaultValue: cat.defaultLabel,
239
+ })}
240
+ <span
241
+ style={{ color: '#bfbfbf', fontWeight: 400, marginLeft: 2 }}
242
+ >
243
+ ({cat.types.length})
244
+ </span>
245
+ </div>
246
+ {/* Items */}
247
+ {open && (
248
+ <div
249
+ style={{
250
+ display: 'grid',
251
+ gridTemplateColumns: '1fr 1fr',
252
+ gap: 6,
253
+ padding: '4px 0',
254
+ }}
255
+ >
256
+ {cat.types.map((type) => (
257
+ <LibraryItem
258
+ key={type}
259
+ type={type}
260
+ onDragStart={handleVariantDragStart}
261
+ onAdd={onAdd}
262
+ />
263
+ ))}
264
+ </div>
265
+ )}
266
+ </div>
267
+ );
268
+ })}
269
+ </div>
270
+ </div>
271
+ );
272
+ };
273
+
274
+ export default CanvasComponentLibrary;
275
+
276
+ // ─── LibraryItem ─────────────────────────────────────────────────────────────
277
+
278
+ interface LibraryItemProps {
279
+ type: string;
280
+ onDragStart: (
281
+ e: React.DragEvent,
282
+ componentType: string,
283
+ variantCode: string,
284
+ ) => void;
285
+ onAdd: (componentType: string, code?: string) => void;
286
+ }
287
+
288
+ const LibraryItem: React.FC<LibraryItemProps> = ({
289
+ type,
290
+ onDragStart,
291
+ onAdd,
292
+ }) => {
293
+ const { t } = useTranslation();
294
+ const def = CANVAS_DEFAULTS[type];
295
+ const variants = def?.variants ?? [];
296
+ const hasMultiVariant = variants.length > 1;
297
+ const primaryCode = variants[0]?.code ?? def?.code ?? '';
298
+
299
+ const card = (
300
+ <Tooltip
301
+ title={t('canvas.library.itemTooltip', {
302
+ defaultValue: '点击添加,或拖到画布',
303
+ })}
304
+ placement="right"
305
+ mouseEnterDelay={0.4}
306
+ >
307
+ <div
308
+ draggable
309
+ onDragStart={(e) => onDragStart(e, type, primaryCode)}
310
+ onClick={() => onAdd(type, primaryCode)}
311
+ style={{
312
+ display: 'flex',
313
+ flexDirection: 'column',
314
+ alignItems: 'center',
315
+ gap: 4,
316
+ padding: 6,
317
+ cursor: 'pointer',
318
+ userSelect: 'none',
319
+ border: '1px solid #ececec',
320
+ borderRadius: 8,
321
+ background: '#fff',
322
+ transition: 'all 160ms ease',
323
+ }}
324
+ onMouseEnter={(e) => {
325
+ e.currentTarget.style.borderColor = '#4361ee';
326
+ e.currentTarget.style.boxShadow = '0 3px 10px rgba(67,97,238,0.10)';
327
+ e.currentTarget.style.transform = 'translateY(-1px)';
328
+ }}
329
+ onMouseLeave={(e) => {
330
+ e.currentTarget.style.borderColor = '#ececec';
331
+ e.currentTarget.style.boxShadow = 'none';
332
+ e.currentTarget.style.transform = 'translateY(0)';
333
+ }}
334
+ >
335
+ <div
336
+ style={{
337
+ border: '1px solid #f0f0f0',
338
+ borderRadius: 6,
339
+ overflow: 'hidden',
340
+ background: '#fafafa',
341
+ width: 96,
342
+ }}
343
+ >
344
+ <ComponentThumbnail componentType={type} width={96} />
345
+ </div>
346
+ <span
347
+ style={{
348
+ fontSize: 11,
349
+ color: '#555',
350
+ fontWeight: 500,
351
+ textAlign: 'center',
352
+ pointerEvents: 'none',
353
+ maxWidth: '100%',
354
+ overflow: 'hidden',
355
+ textOverflow: 'ellipsis',
356
+ whiteSpace: 'nowrap',
357
+ }}
358
+ >
359
+ {getComponentLabel(type, t)}
360
+ </span>
361
+ </div>
362
+ </Tooltip>
363
+ );
364
+
365
+ if (!hasMultiVariant) return card;
366
+
367
+ // 多 variant:hover popover 展示子样式
368
+ const popoverContent = (
369
+ <div
370
+ style={{
371
+ display: 'flex',
372
+ alignItems: 'center',
373
+ gap: 12,
374
+ padding: 4,
375
+ maxWidth: 460,
376
+ flexWrap: 'wrap',
377
+ }}
378
+ >
379
+ {variants.map((v) => (
380
+ <div
381
+ key={v.name}
382
+ draggable
383
+ onDragStart={(e) => onDragStart(e, type, v.code)}
384
+ onClick={() => onAdd(type, v.code)}
385
+ style={{
386
+ display: 'flex',
387
+ flexDirection: 'column',
388
+ alignItems: 'center',
389
+ gap: 4,
390
+ cursor: 'pointer',
391
+ userSelect: 'none',
392
+ }}
393
+ >
394
+ <div
395
+ style={{
396
+ border: '1px solid #e8e8e8',
397
+ borderRadius: 6,
398
+ overflow: 'hidden',
399
+ background: '#fff',
400
+ transition: 'all 160ms ease',
401
+ }}
402
+ onMouseEnter={(e) => {
403
+ e.currentTarget.style.borderColor = '#4361ee';
404
+ e.currentTarget.style.transform = 'translateY(-2px)';
405
+ }}
406
+ onMouseLeave={(e) => {
407
+ e.currentTarget.style.borderColor = '#e8e8e8';
408
+ e.currentTarget.style.transform = 'translateY(0)';
409
+ }}
410
+ >
411
+ <ComponentThumbnail
412
+ componentType={type}
413
+ code={v.code}
414
+ width={120}
415
+ />
416
+ </div>
417
+ <span
418
+ style={{
419
+ fontSize: 10,
420
+ color: '#666',
421
+ fontWeight: 500,
422
+ textAlign: 'center',
423
+ pointerEvents: 'none',
424
+ }}
425
+ >
426
+ {getVariantLabel(v.label, t)}
427
+ </span>
428
+ </div>
429
+ ))}
430
+ </div>
431
+ );
432
+
433
+ return (
434
+ <Popover
435
+ content={popoverContent}
436
+ title={
437
+ <span style={{ fontSize: 12, fontWeight: 600, color: '#333' }}>
438
+ {getComponentLabel(type, t)}
439
+ </span>
440
+ }
441
+ trigger="hover"
442
+ placement="rightTop"
443
+ mouseEnterDelay={0.2}
444
+ mouseLeaveDelay={0.3}
445
+ >
446
+ {card}
447
+ </Popover>
448
+ );
449
+ };