one-design-next 0.0.88 → 0.0.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * 内联引用 chip 的品类 icon。
3
3
  *
4
- * chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 技能按钮同源,
5
- * 不使用 SkillItem.icon(那只服务技能菜单辨识)。
4
+ * chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 与 SkillTab 的
5
+ * 技能入口同源,不使用 SkillItem.icon(那只服务技能菜单辨识)。
6
6
  */
7
- export declare const SKILL_CATEGORY_ICON = "wand-sparkles";
7
+ export declare const SKILL_CATEGORY_ICON = "astroid";
8
8
  /** skill / 未标明的 invocation 通道 → 技能品类 icon;其它 kind 回退 data.icon */
9
9
  export declare function resolveInvocationCategoryIcon(kind?: string, fallback?: string): string | undefined;
10
10
  /** mention 按 kind 给品类 icon;未知 kind 回退 data.icon */
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * 内联引用 chip 的品类 icon。
3
3
  *
4
- * chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 技能按钮同源,
5
- * 不使用 SkillItem.icon(那只服务技能菜单辨识)。
4
+ * chip 视觉锚点按「类型」而非条目:skill 一律跟 Composer 与 SkillTab 的
5
+ * 技能入口同源,不使用 SkillItem.icon(那只服务技能菜单辨识)。
6
6
  */
7
- export var SKILL_CATEGORY_ICON = 'wand-sparkles';
7
+ export var SKILL_CATEGORY_ICON = 'astroid';
8
8
 
9
9
  /** skill / 未标明的 invocation 通道 → 技能品类 icon;其它 kind 回退 data.icon */
10
10
  export function resolveInvocationCategoryIcon(kind, fallback) {
package/dist/index.d.ts CHANGED
@@ -70,6 +70,7 @@ export { default as Mention, type MentionProps } from './mention';
70
70
  export { default as MessageImage, type MessageImageItem, type MessageImageProps, } from './message-image';
71
71
  export { default as PreviewPanel, type PreviewPanelActionTooltips, type PreviewPanelArtifact, type PreviewPanelProps, } from './preview-panel';
72
72
  export { default as Provenance, type ProvenanceProps, type ProvenanceType, } from './provenance';
73
+ export { default as SkillCard, SkillCardIcon, SkillCardMedia, skillCardSwitchStyle, type SkillCardButton, type SkillCardControl, type SkillCardIconProps, type SkillCardIconSize, type SkillCardIconTone, type SkillCardMediaProps, type SkillCardOperation, type SkillCardOperationType, type SkillCardProps, type SkillCardStatusLabel, type SkillCardStatusType, type SkillCardTag, type SkillCardTagType, } from './skill-card';
73
74
  export { default as SkillSlot, type SkillSlotHandle, type SkillSlotProps, } from './skill-slot';
74
75
  export { default as Sources, type SourcesProps } from './sources';
75
76
  export { default as StreamPulse, type StreamPulseProps } from './stream-pulse';
package/dist/index.js CHANGED
@@ -75,6 +75,7 @@ export { default as Mention } from "./mention";
75
75
  export { default as MessageImage } from "./message-image";
76
76
  export { default as PreviewPanel } from "./preview-panel";
77
77
  export { default as Provenance } from "./provenance";
78
+ export { default as SkillCard, SkillCardIcon, SkillCardMedia, skillCardSwitchStyle } from "./skill-card";
78
79
  export { default as SkillSlot } from "./skill-slot";
79
80
  export { default as Sources } from "./sources";
80
81
  export { default as StreamPulse } from "./stream-pulse";
@@ -0,0 +1,105 @@
1
+ import * as React from 'react';
2
+ import { type IconName } from '../icon';
3
+ import './style';
4
+ export type SkillCardTagType = 'normal' | 'brand' | 'hot';
5
+ export type SkillCardStatusType = 'info' | 'error';
6
+ export type SkillCardOperationType = 'normal' | 'error';
7
+ export type SkillCardIconSize = 'card' | 'detail';
8
+ export type SkillCardIconTone = 'tinted' | 'plain';
9
+ export interface SkillCardTag {
10
+ type: SkillCardTagType;
11
+ label: string;
12
+ }
13
+ export interface SkillCardStatusLabel {
14
+ type: SkillCardStatusType;
15
+ label: string;
16
+ }
17
+ export interface SkillCardOperation {
18
+ type: SkillCardOperationType;
19
+ label: string;
20
+ icon?: IconName;
21
+ disabled?: boolean;
22
+ onClick?: () => void;
23
+ }
24
+ export interface SkillCardButton {
25
+ icon?: IconName;
26
+ label?: string;
27
+ disabled?: boolean;
28
+ onClick?: () => void;
29
+ }
30
+ /** 官方市场的添加态与已拥有技能的启停态不能混用。 */
31
+ export type SkillCardControl = {
32
+ type: 'add';
33
+ added: boolean;
34
+ /** 添加/移除请求中的受控加载态。 */
35
+ loading?: boolean;
36
+ onChange?: (added: boolean) => void;
37
+ } | {
38
+ type: 'toggle';
39
+ checked: boolean;
40
+ onChange?: (checked: boolean) => void;
41
+ };
42
+ export interface SkillCardIconProps {
43
+ /** 图标内容由业务选择;推荐传入 Lucide 图标。 */
44
+ children: React.ReactNode;
45
+ /** `card` = 48px,`detail` = 80px。 */
46
+ size?: SkillCardIconSize;
47
+ /** `tinted` 用于卡片,`plain` 用于详情页等白底场景。 */
48
+ tone?: SkillCardIconTone;
49
+ className?: string;
50
+ style?: React.CSSProperties;
51
+ }
52
+ export interface SkillCardMediaProps {
53
+ /** 头像 URL;为空或加载失败时回退到 `icon`。 */
54
+ avatarUrl?: string;
55
+ /** 业务侧选择的 Lucide 图标,同时作为头像加载失败的回退。 */
56
+ icon: React.ReactNode;
57
+ alt?: string;
58
+ size?: SkillCardIconSize;
59
+ tone?: SkillCardIconTone;
60
+ className?: string;
61
+ style?: React.CSSProperties;
62
+ }
63
+ /** Skill 图标的统一视觉容器。 */
64
+ export declare function SkillCardIcon({ children, size, tone, className, style, }: SkillCardIconProps): React.JSX.Element;
65
+ /** 展示头像或 Lucide 图标,并在头像失效时回退到图标。 */
66
+ export declare function SkillCardMedia({ avatarUrl, icon, alt, size, tone, className, style, }: SkillCardMediaProps): React.JSX.Element;
67
+ /** SkillCard 内的 Switch 视觉 token,详情页可复用同一规格。 */
68
+ export declare const skillCardSwitchStyle: React.CSSProperties;
69
+ export interface SkillCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children' | 'onClick'> {
70
+ /** 技能中文展示名。 */
71
+ name: string;
72
+ /** 业务侧的英文技能标识;空间不足时优先省略。 */
73
+ nameEn?: string;
74
+ /** 一句话技能描述。 */
75
+ description: string;
76
+ /** 业务侧选择的 Lucide 图标。 */
77
+ icon: React.ReactNode;
78
+ /** 由业务决定是否传入;为空或失败时展示 icon。 */
79
+ avatarUrl?: string;
80
+ /** 已按展示顺序映射好的来源、热度、场景、版本等标签。 */
81
+ tags?: SkillCardTag[];
82
+ /** 审核等状态优先于所有操作;传入后隐藏控制、菜单与按钮。 */
83
+ statusLabel?: SkillCardStatusLabel;
84
+ /** 标准化的更多操作菜单;业务侧决定权限、顺序与回调。 */
85
+ operations?: SkillCardOperation[];
86
+ /** Hover 后的主操作,例如「去试试」。 */
87
+ button?: SkillCardButton;
88
+ /** 官方添加态或我的技能启停态,保持受控。 */
89
+ control?: SkillCardControl;
90
+ /** 点击卡片内容区。组件不负责打开详情。 */
91
+ onOpen?: () => void;
92
+ className?: string;
93
+ style?: React.CSSProperties;
94
+ }
95
+ /**
96
+ * 技能市场的展示卡片。
97
+ *
98
+ * 组件处理布局、状态优先级、Hover 动效和标准化 Action;数据筛选、
99
+ * 权限、详情路由及实际的添加、启停、试用行为均交由业务侧回调实现。
100
+ */
101
+ export declare function SkillCard({ name, nameEn, description, icon, avatarUrl, tags, statusLabel, operations, button, control, onOpen, className, style, ...rest }: SkillCardProps): React.JSX.Element;
102
+ export declare namespace SkillCard {
103
+ var displayName: string;
104
+ }
105
+ export default SkillCard;
@@ -0,0 +1,320 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
5
+ var _excluded = ["name", "nameEn", "description", "icon", "avatarUrl", "tags", "statusLabel", "operations", "button", "control", "onOpen", "className", "style"];
6
+ import clsx from 'clsx';
7
+ import * as React from 'react';
8
+ import Button from "../button";
9
+ import Card from "../card";
10
+ import Dropdown from "../dropdown";
11
+ import Icon from "../icon";
12
+ import Switch from "../switch";
13
+ import Tooltip from "../tooltip";
14
+ import "./style";
15
+
16
+ /** 官方市场的添加态与已拥有技能的启停态不能混用。 */
17
+
18
+ /** Skill 图标的统一视觉容器。 */
19
+ export function SkillCardIcon(_ref) {
20
+ var children = _ref.children,
21
+ _ref$size = _ref.size,
22
+ size = _ref$size === void 0 ? 'card' : _ref$size,
23
+ _ref$tone = _ref.tone,
24
+ tone = _ref$tone === void 0 ? 'tinted' : _ref$tone,
25
+ className = _ref.className,
26
+ style = _ref.style;
27
+ return /*#__PURE__*/React.createElement("span", {
28
+ "data-odn-skill-card-media": "icon",
29
+ "data-odn-skill-card-icon-box": true,
30
+ "data-odn-skill-card-icon-size": size,
31
+ "data-odn-skill-card-icon-tone": tone,
32
+ className: clsx(className),
33
+ style: style
34
+ }, children);
35
+ }
36
+
37
+ /** 展示头像或 Lucide 图标,并在头像失效时回退到图标。 */
38
+ export function SkillCardMedia(_ref2) {
39
+ var avatarUrl = _ref2.avatarUrl,
40
+ icon = _ref2.icon,
41
+ _ref2$alt = _ref2.alt,
42
+ alt = _ref2$alt === void 0 ? '' : _ref2$alt,
43
+ _ref2$size = _ref2.size,
44
+ size = _ref2$size === void 0 ? 'card' : _ref2$size,
45
+ _ref2$tone = _ref2.tone,
46
+ tone = _ref2$tone === void 0 ? 'tinted' : _ref2$tone,
47
+ className = _ref2.className,
48
+ style = _ref2.style;
49
+ var _React$useState = React.useState(false),
50
+ _React$useState2 = _slicedToArray(_React$useState, 2),
51
+ avatarFailed = _React$useState2[0],
52
+ setAvatarFailed = _React$useState2[1];
53
+ var shouldShowAvatar = !!avatarUrl && !avatarFailed;
54
+ React.useEffect(function () {
55
+ return setAvatarFailed(false);
56
+ }, [avatarUrl]);
57
+ if (!shouldShowAvatar) {
58
+ return /*#__PURE__*/React.createElement(SkillCardIcon, {
59
+ size: size,
60
+ tone: tone,
61
+ className: className,
62
+ style: style
63
+ }, icon);
64
+ }
65
+ return /*#__PURE__*/React.createElement("img", {
66
+ "data-odn-skill-card-media": "avatar",
67
+ "data-odn-skill-card-icon-box": true,
68
+ "data-odn-skill-card-icon-size": size,
69
+ "data-odn-skill-card-icon-tone": tone,
70
+ className: clsx(className),
71
+ style: style,
72
+ src: avatarUrl,
73
+ alt: alt,
74
+ onError: function onError() {
75
+ return setAvatarFailed(true);
76
+ }
77
+ });
78
+ }
79
+
80
+ /** SkillCard 内的 Switch 视觉 token,详情页可复用同一规格。 */
81
+ export var skillCardSwitchStyle = {
82
+ '--odn-switch-track-bg': 'rgba(74, 97, 143, 0.1)',
83
+ '--odn-switch-track-bg-hover': 'rgba(74, 97, 143, 0.14)',
84
+ '--odn-switch-track-bg-active': 'rgba(74, 97, 143, 0.18)',
85
+ '--odn-switch-track-bg-checked': '#2694FD',
86
+ '--odn-switch-track-bg-checked-hover': '#2694FD',
87
+ '--odn-switch-track-bg-checked-active': '#2694FD'
88
+ };
89
+ var TAG_GAP = 6;
90
+ var MIN_TRUNCATABLE_TAG_WIDTH = 36;
91
+
92
+ /** 来源优先;末项不足两字时收纳为 +N,避免难以辨识的单字截断。 */
93
+ function SkillCardTagList(_ref3) {
94
+ var tags = _ref3.tags;
95
+ var groupRef = React.useRef(null);
96
+ var measureRefs = React.useRef([]);
97
+ var _React$useState3 = React.useState(0),
98
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
99
+ collapsedCount = _React$useState4[0],
100
+ setCollapsedCount = _React$useState4[1];
101
+ var recalculate = React.useCallback(function () {
102
+ var _measureRefs$current$;
103
+ var group = groupRef.current;
104
+ if (!group || group.clientWidth <= 0 || tags.length < 2) return;
105
+ var sourceWidth = (_measureRefs$current$ = measureRefs.current[0]) === null || _measureRefs$current$ === void 0 ? void 0 : _measureRefs$current$.getBoundingClientRect().width;
106
+ if (!sourceWidth) return;
107
+ var remainingWidth = group.clientWidth - sourceWidth;
108
+ var nextCollapsedCount = 0;
109
+ for (var index = 1; index < tags.length; index += 1) {
110
+ var _measureRefs$current$2;
111
+ var tagWidth = (_measureRefs$current$2 = measureRefs.current[index]) === null || _measureRefs$current$2 === void 0 ? void 0 : _measureRefs$current$2.getBoundingClientRect().width;
112
+ if (!tagWidth) return;
113
+ remainingWidth -= TAG_GAP;
114
+ var isLastTag = index === tags.length - 1;
115
+ if (isLastTag) {
116
+ if (remainingWidth < MIN_TRUNCATABLE_TAG_WIDTH) {
117
+ nextCollapsedCount = tags.length - index;
118
+ }
119
+ break;
120
+ }
121
+ if (remainingWidth < tagWidth) {
122
+ nextCollapsedCount = tags.length - index;
123
+ break;
124
+ }
125
+ remainingWidth -= tagWidth;
126
+ }
127
+ setCollapsedCount(function (current) {
128
+ return current === nextCollapsedCount ? current : nextCollapsedCount;
129
+ });
130
+ }, [tags]);
131
+ React.useLayoutEffect(function () {
132
+ recalculate();
133
+ var group = groupRef.current;
134
+ if (!group || typeof ResizeObserver === 'undefined') return;
135
+ var observer = new ResizeObserver(recalculate);
136
+ observer.observe(group);
137
+ return function () {
138
+ return observer.disconnect();
139
+ };
140
+ }, [recalculate]);
141
+ var visibleCount = tags.length - collapsedCount;
142
+ return /*#__PURE__*/React.createElement("span", {
143
+ ref: groupRef,
144
+ "data-odn-skill-card-label-group": true
145
+ }, tags.slice(0, visibleCount).map(function (tag, index) {
146
+ return /*#__PURE__*/React.createElement("span", {
147
+ key: "".concat(tag.type, "-").concat(tag.label, "-").concat(index),
148
+ "data-odn-skill-card-tag": tag.type,
149
+ "data-odn-skill-card-tag-last": collapsedCount === 0 && index === tags.length - 1 || undefined
150
+ }, tag.type === 'hot' ? /*#__PURE__*/React.createElement(Icon, {
151
+ name: "hot-filled",
152
+ size: 14
153
+ }) : null, /*#__PURE__*/React.createElement("span", {
154
+ "data-odn-skill-card-tag-label": true
155
+ }, tag.label));
156
+ }), collapsedCount > 0 ? /*#__PURE__*/React.createElement("span", {
157
+ "data-odn-skill-card-tag": "normal",
158
+ "data-odn-skill-card-tag-summary": true
159
+ }, /*#__PURE__*/React.createElement("span", {
160
+ "data-odn-skill-card-tag-label": true
161
+ }, "+", collapsedCount)) : null, /*#__PURE__*/React.createElement("span", {
162
+ "aria-hidden": true,
163
+ "data-odn-skill-card-tag-measurer": true
164
+ }, tags.map(function (tag, index) {
165
+ return /*#__PURE__*/React.createElement("span", {
166
+ key: "".concat(tag.type, "-").concat(tag.label, "-").concat(index),
167
+ ref: function ref(element) {
168
+ measureRefs.current[index] = element;
169
+ },
170
+ "data-odn-skill-card-tag": tag.type
171
+ }, tag.type === 'hot' ? /*#__PURE__*/React.createElement(Icon, {
172
+ name: "hot-filled",
173
+ size: 14
174
+ }) : null, /*#__PURE__*/React.createElement("span", {
175
+ "data-odn-skill-card-tag-label": true
176
+ }, tag.label));
177
+ })));
178
+ }
179
+
180
+ /**
181
+ * 技能市场的展示卡片。
182
+ *
183
+ * 组件处理布局、状态优先级、Hover 动效和标准化 Action;数据筛选、
184
+ * 权限、详情路由及实际的添加、启停、试用行为均交由业务侧回调实现。
185
+ */
186
+ export function SkillCard(_ref4) {
187
+ var _control$type, _statusLabel$type;
188
+ var name = _ref4.name,
189
+ nameEn = _ref4.nameEn,
190
+ description = _ref4.description,
191
+ icon = _ref4.icon,
192
+ avatarUrl = _ref4.avatarUrl,
193
+ _ref4$tags = _ref4.tags,
194
+ tags = _ref4$tags === void 0 ? [] : _ref4$tags,
195
+ statusLabel = _ref4.statusLabel,
196
+ _ref4$operations = _ref4.operations,
197
+ operations = _ref4$operations === void 0 ? [] : _ref4$operations,
198
+ button = _ref4.button,
199
+ control = _ref4.control,
200
+ onOpen = _ref4.onOpen,
201
+ className = _ref4.className,
202
+ style = _ref4.style,
203
+ rest = _objectWithoutProperties(_ref4, _excluded);
204
+ var isAddControl = (control === null || control === void 0 ? void 0 : control.type) === 'add';
205
+ var isToggleControl = (control === null || control === void 0 ? void 0 : control.type) === 'toggle';
206
+ var hasButton = !!button && !!(button.label || button.icon);
207
+ var canShowHoverActions = !statusLabel && (operations.length > 0 || hasButton) && (!isAddControl || control.added);
208
+ var hasActionGroup = !statusLabel && (!!control || canShowHoverActions);
209
+ /** 审核态也需要 Hover 动效;仅状态标签保持占位,不展示 ActionGroup。 */
210
+ var isHoverable = !!statusLabel || !!onOpen || hasActionGroup;
211
+ var operationMenu = operations.flatMap(function (operation, index) {
212
+ var _operations;
213
+ return [].concat(_toConsumableArray(operation.type === 'error' && index > 0 && ((_operations = operations[index - 1]) === null || _operations === void 0 ? void 0 : _operations.type) !== 'error' ? [{
214
+ type: 'separator'
215
+ }] : []), [{
216
+ label: /*#__PURE__*/React.createElement("span", {
217
+ className: clsx('flex items-center gap-2', operation.type === 'error' && 'text-red-6')
218
+ }, operation.icon ? /*#__PURE__*/React.createElement(Icon, {
219
+ name: operation.icon,
220
+ size: 16
221
+ }) : null, operation.label),
222
+ value: String(index),
223
+ disabled: operation.disabled
224
+ }]);
225
+ });
226
+ return /*#__PURE__*/React.createElement(Card, _extends({
227
+ elevation: 0,
228
+ "data-odn-skill-card": true,
229
+ "data-odn-skill-card-control": (_control$type = control === null || control === void 0 ? void 0 : control.type) !== null && _control$type !== void 0 ? _control$type : 'none',
230
+ "data-odn-skill-card-added": isAddControl ? String(control.added) : undefined,
231
+ "data-odn-skill-card-status": (_statusLabel$type = statusLabel === null || statusLabel === void 0 ? void 0 : statusLabel.type) !== null && _statusLabel$type !== void 0 ? _statusLabel$type : 'default',
232
+ "data-odn-skill-card-hoverable": isHoverable || undefined,
233
+ className: clsx(className),
234
+ style: style
235
+ }, rest), onOpen ? /*#__PURE__*/React.createElement("button", {
236
+ type: "button",
237
+ "data-odn-skill-card-open": true,
238
+ "aria-label": "\u6253\u5F00".concat(name, "\u8BE6\u60C5"),
239
+ onClick: onOpen
240
+ }) : null, /*#__PURE__*/React.createElement("span", {
241
+ "data-odn-skill-card-glow": true,
242
+ "aria-hidden": true
243
+ }), /*#__PURE__*/React.createElement("span", {
244
+ "data-odn-skill-card-icon": true,
245
+ "aria-hidden": true
246
+ }, /*#__PURE__*/React.createElement(SkillCardMedia, {
247
+ avatarUrl: avatarUrl,
248
+ icon: icon,
249
+ alt: "".concat(name, "\u5934\u50CF")
250
+ })), /*#__PURE__*/React.createElement("span", {
251
+ "data-odn-skill-card-copy": true
252
+ }, /*#__PURE__*/React.createElement("span", {
253
+ "data-odn-skill-card-name-group": true
254
+ }, /*#__PURE__*/React.createElement("span", {
255
+ "data-odn-skill-card-name": true
256
+ }, name), nameEn ? /*#__PURE__*/React.createElement("span", {
257
+ "data-odn-skill-card-alias": true
258
+ }, nameEn) : null), tags.length > 0 ? /*#__PURE__*/React.createElement(SkillCardTagList, {
259
+ tags: tags
260
+ }) : null), /*#__PURE__*/React.createElement("p", {
261
+ "data-odn-skill-card-description": true
262
+ }, description), statusLabel ? /*#__PURE__*/React.createElement("span", {
263
+ "data-odn-skill-card-status-badge": statusLabel.type
264
+ }, statusLabel.label) : hasActionGroup ? /*#__PURE__*/React.createElement("span", {
265
+ "data-odn-skill-card-action-group": true
266
+ }, isAddControl ? /*#__PURE__*/React.createElement("span", {
267
+ "data-odn-skill-card-default-action": true
268
+ }, /*#__PURE__*/React.createElement(Tooltip, {
269
+ popup: control.added ? '移除已添加技能' : '添加技能',
270
+ placement: "top"
271
+ }, /*#__PURE__*/React.createElement(Button, {
272
+ type: "button",
273
+ size: "small",
274
+ intent: "normal",
275
+ icon: control.added ? 'check' : 'plus',
276
+ loading: control.loading,
277
+ "data-odn-skill-card-added-action": control.added || undefined,
278
+ "aria-label": control.added ? '移除已添加技能' : '添加技能',
279
+ disabled: !control.onChange || control.loading,
280
+ onClick: function onClick() {
281
+ var _control$onChange;
282
+ return (_control$onChange = control.onChange) === null || _control$onChange === void 0 ? void 0 : _control$onChange.call(control, !control.added);
283
+ }
284
+ }))) : null, canShowHoverActions ? /*#__PURE__*/React.createElement("span", {
285
+ "data-odn-skill-card-hover-actions": true
286
+ }, operations.length > 0 ? /*#__PURE__*/React.createElement(Dropdown, {
287
+ popupClassName: "odn-skill-card-menu",
288
+ menu: operationMenu,
289
+ onSelect: function onSelect(value) {
290
+ var _operations$Number, _operations$Number$on;
291
+ return (_operations$Number = operations[Number(value)]) === null || _operations$Number === void 0 || (_operations$Number$on = _operations$Number.onClick) === null || _operations$Number$on === void 0 ? void 0 : _operations$Number$on.call(_operations$Number);
292
+ }
293
+ }, /*#__PURE__*/React.createElement("span", {
294
+ "data-odn-skill-card-operation-trigger": true
295
+ }, /*#__PURE__*/React.createElement(Button, {
296
+ light: true,
297
+ size: "small",
298
+ icon: "ellipsis",
299
+ "aria-label": "\u66F4\u591A\u64CD\u4F5C"
300
+ }))) : null, hasButton && button ? /*#__PURE__*/React.createElement(Button, {
301
+ type: "button",
302
+ size: "small",
303
+ intent: "normal",
304
+ icon: button.icon,
305
+ disabled: button.disabled || !button.onClick,
306
+ "data-odn-skill-card-try": true,
307
+ onClick: button.onClick
308
+ }, button.label) : null) : null, isToggleControl ? /*#__PURE__*/React.createElement("span", {
309
+ "data-odn-skill-card-switch": true
310
+ }, /*#__PURE__*/React.createElement(Switch, {
311
+ size: "medium",
312
+ style: skillCardSwitchStyle,
313
+ checked: control.checked,
314
+ disabled: !control.onChange,
315
+ "aria-label": control.checked ? "\u505C\u7528".concat(name) : "\u542F\u7528".concat(name),
316
+ onChange: control.onChange
317
+ })) : null) : null);
318
+ }
319
+ SkillCard.displayName = 'SkillCard';
320
+ export default SkillCard;
@@ -0,0 +1,430 @@
1
+ @charset "UTF-8";
2
+ html {
3
+ --odn-skill-card-height: 144px;
4
+ --odn-skill-card-padding: 20px;
5
+ --odn-skill-card-action-gap: 8px;
6
+ --odn-skill-card-hover-duration: 0.3s;
7
+ --odn-skill-card-hover-ease: cubic-bezier(0.4, 0, 0.2, 1);
8
+ --odn-skill-card-text: rgba(0, 0, 0, 0.95);
9
+ --odn-skill-card-secondary: rgba(51, 55, 61, 0.58);
10
+ --odn-skill-card-source: #296bef;
11
+ --odn-skill-card-source-bg: rgba(41, 107, 239, 0.1);
12
+ --odn-skill-card-soft-bg: rgba(74, 97, 143, 0.08);
13
+ --odn-skill-card-border: rgba(74, 97, 143, 0.08);
14
+ }
15
+
16
+ [data-odn-skill-card] {
17
+ --odn-card-radius: 16px;
18
+ box-sizing: border-box;
19
+ position: relative;
20
+ isolation: isolate;
21
+ width: 100%;
22
+ min-width: 0;
23
+ height: var(--odn-skill-card-height);
24
+ overflow: hidden;
25
+ border: 1px solid var(--odn-skill-card-border);
26
+ border-radius: 16px;
27
+ background: var(--odn-color-bg-elevated);
28
+ color: var(--odn-skill-card-text);
29
+ text-align: left;
30
+ transition: border-color 0.15s ease-out, box-shadow 0.15s ease-out;
31
+ }
32
+
33
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true]:hover {
34
+ border-color: var(--odn-color-black-6);
35
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
36
+ }
37
+
38
+ [data-odn-skill-card-open] {
39
+ position: absolute;
40
+ inset: 0;
41
+ z-index: 1;
42
+ padding: 0;
43
+ border: 0;
44
+ background: transparent;
45
+ cursor: pointer;
46
+ }
47
+
48
+ [data-odn-skill-card-open]:focus {
49
+ outline: none;
50
+ }
51
+
52
+ [data-odn-skill-card-open]:focus-visible {
53
+ outline: 2px solid color-mix(in srgb, var(--odn-color-primary) 55%, transparent);
54
+ outline-offset: -2px;
55
+ }
56
+
57
+ [data-odn-skill-card-glow] {
58
+ position: absolute;
59
+ inset: 0;
60
+ z-index: 0;
61
+ overflow: hidden;
62
+ border-radius: inherit;
63
+ pointer-events: none;
64
+ opacity: 0;
65
+ transition: opacity var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease);
66
+ }
67
+
68
+ [data-odn-skill-card-glow]::after {
69
+ content: "";
70
+ position: absolute;
71
+ left: -65px;
72
+ top: -30px;
73
+ width: 230px;
74
+ height: 130px;
75
+ transform: rotate(-8.4deg);
76
+ background-image: radial-gradient(ellipse at center, rgb(38, 148, 253), transparent 60%);
77
+ }
78
+
79
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true]:hover [data-odn-skill-card-glow] {
80
+ opacity: 0.12;
81
+ }
82
+
83
+ [data-odn-skill-card-icon] {
84
+ position: absolute;
85
+ left: var(--odn-skill-card-padding);
86
+ top: var(--odn-skill-card-padding);
87
+ z-index: 10;
88
+ display: inline-flex;
89
+ pointer-events: none;
90
+ transform: scale(1);
91
+ transform-origin: center;
92
+ opacity: 1;
93
+ will-change: transform;
94
+ transition: transform var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease), opacity var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease);
95
+ }
96
+
97
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true]:hover [data-odn-skill-card-icon] {
98
+ transform: scale(0.73);
99
+ opacity: 0;
100
+ }
101
+
102
+ [data-odn-skill-card-icon-box] {
103
+ display: inline-flex;
104
+ flex-shrink: 0;
105
+ align-items: center;
106
+ justify-content: center;
107
+ overflow: hidden;
108
+ border: 1px solid var(--odn-color-black-1);
109
+ border-radius: 8px;
110
+ color: rgb(38, 148, 253);
111
+ object-fit: cover;
112
+ }
113
+
114
+ [data-odn-skill-card-icon-box][data-odn-skill-card-icon-size=card] {
115
+ width: 48px;
116
+ height: 48px;
117
+ }
118
+
119
+ [data-odn-skill-card-icon-box][data-odn-skill-card-icon-size=detail] {
120
+ width: 80px;
121
+ height: 80px;
122
+ }
123
+
124
+ [data-odn-skill-card-icon-box][data-odn-skill-card-icon-tone=tinted] {
125
+ background: var(--odn-color-blue-1, #f2f7ff);
126
+ }
127
+
128
+ [data-odn-skill-card-icon-box][data-odn-skill-card-icon-tone=plain] {
129
+ background: var(--odn-color-bg-elevated);
130
+ }
131
+
132
+ [data-odn-skill-card-copy] {
133
+ position: absolute;
134
+ top: var(--odn-skill-card-padding);
135
+ right: 70px;
136
+ left: 80px;
137
+ z-index: 20;
138
+ display: flex;
139
+ min-width: 0;
140
+ flex-direction: column;
141
+ pointer-events: none;
142
+ transform: translateX(0);
143
+ will-change: left, right, transform;
144
+ transition: left var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease), right var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease), transform var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease);
145
+ }
146
+
147
+ [data-odn-skill-card][data-odn-skill-card-control=add] [data-odn-skill-card-copy] {
148
+ right: 62px;
149
+ }
150
+
151
+ [data-odn-skill-card][data-odn-skill-card-status=info] [data-odn-skill-card-copy],
152
+ [data-odn-skill-card][data-odn-skill-card-status=error] [data-odn-skill-card-copy] {
153
+ right: 92px;
154
+ }
155
+
156
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true]:hover [data-odn-skill-card-copy] {
157
+ transform: translateX(-60px);
158
+ }
159
+
160
+ /* 审核态右上不切换操作,但左侧图标让位后 nameEn 需要获得真实可用宽度。 */
161
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true][data-odn-skill-card-status=info]:hover [data-odn-skill-card-copy],
162
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true][data-odn-skill-card-status=error]:hover [data-odn-skill-card-copy] {
163
+ left: var(--odn-skill-card-padding);
164
+ transform: translateX(0);
165
+ }
166
+
167
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true][data-odn-skill-card-status=default][data-odn-skill-card-control=toggle]:hover [data-odn-skill-card-copy] {
168
+ right: 116px;
169
+ }
170
+
171
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true][data-odn-skill-card-status=default][data-odn-skill-card-control=add][data-odn-skill-card-added=true]:hover [data-odn-skill-card-copy] {
172
+ right: 70px;
173
+ }
174
+
175
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true][data-odn-skill-card-status=default][data-odn-skill-card-control=add][data-odn-skill-card-added=false]:hover [data-odn-skill-card-copy] {
176
+ right: 2px;
177
+ }
178
+
179
+ [data-odn-skill-card-name-group] {
180
+ display: flex;
181
+ min-width: 0;
182
+ align-items: baseline;
183
+ gap: 8px;
184
+ }
185
+
186
+ [data-odn-skill-card-name] {
187
+ min-width: 0;
188
+ max-width: calc(100% - 8px);
189
+ flex: 0 1 auto;
190
+ overflow: hidden;
191
+ color: var(--odn-skill-card-text);
192
+ font-size: 14px;
193
+ font-weight: 500;
194
+ line-height: 22px;
195
+ text-overflow: ellipsis;
196
+ white-space: nowrap;
197
+ }
198
+
199
+ [data-odn-skill-card-alias] {
200
+ min-width: 0;
201
+ flex: 1 1 0;
202
+ overflow: hidden;
203
+ color: var(--odn-skill-card-secondary);
204
+ font-size: 14px;
205
+ line-height: 22px;
206
+ text-overflow: ellipsis;
207
+ white-space: nowrap;
208
+ }
209
+
210
+ [data-odn-skill-card-label-group] {
211
+ display: flex;
212
+ min-width: 0;
213
+ align-items: center;
214
+ gap: 6px;
215
+ margin-top: 4px;
216
+ overflow: hidden;
217
+ white-space: nowrap;
218
+ }
219
+
220
+ [data-odn-skill-card-tag] {
221
+ display: inline-flex;
222
+ box-sizing: border-box;
223
+ height: 22px;
224
+ flex-shrink: 0;
225
+ align-items: center;
226
+ border-radius: 4px;
227
+ padding: 0 6px;
228
+ font-size: 12px;
229
+ line-height: 22px;
230
+ }
231
+
232
+ [data-odn-skill-card-tag-label] {
233
+ min-width: 0;
234
+ white-space: nowrap;
235
+ }
236
+
237
+ [data-odn-skill-card-tag-last=true] {
238
+ min-width: 24px;
239
+ flex: 0 1 auto;
240
+ overflow: hidden;
241
+ }
242
+
243
+ [data-odn-skill-card-tag-last=true] [data-odn-skill-card-tag-label] {
244
+ display: block;
245
+ overflow: hidden;
246
+ text-overflow: ellipsis;
247
+ }
248
+
249
+ [data-odn-skill-card-tag-measurer] {
250
+ position: absolute;
251
+ top: 0;
252
+ left: -9999px;
253
+ display: flex;
254
+ visibility: hidden;
255
+ white-space: nowrap;
256
+ }
257
+
258
+ [data-odn-skill-card-tag-measurer] [data-odn-skill-card-tag] {
259
+ flex: none;
260
+ }
261
+
262
+ [data-odn-skill-card-tag=brand] {
263
+ max-width: 84px;
264
+ overflow: hidden;
265
+ color: var(--odn-skill-card-source);
266
+ background: var(--odn-skill-card-source-bg);
267
+ font-weight: 500;
268
+ }
269
+
270
+ [data-odn-skill-card-tag=brand] [data-odn-skill-card-tag-label] {
271
+ display: block;
272
+ overflow: hidden;
273
+ text-overflow: ellipsis;
274
+ }
275
+
276
+ [data-odn-skill-card-tag=hot] {
277
+ gap: 4px;
278
+ color: var(--odn-color-orange-6);
279
+ background: var(--odn-color-orange-1);
280
+ font-weight: 500;
281
+ }
282
+
283
+ [data-odn-skill-card-tag=normal] {
284
+ color: var(--odn-skill-card-secondary);
285
+ background: var(--odn-skill-card-soft-bg);
286
+ }
287
+
288
+ [data-odn-skill-card-description] {
289
+ position: absolute;
290
+ top: 80px;
291
+ right: var(--odn-skill-card-padding);
292
+ left: var(--odn-skill-card-padding);
293
+ z-index: 20;
294
+ display: -webkit-box;
295
+ margin: 0;
296
+ overflow: hidden;
297
+ color: var(--odn-skill-card-secondary);
298
+ font-size: 14px;
299
+ line-height: 22px;
300
+ pointer-events: none;
301
+ -webkit-box-orient: vertical;
302
+ -webkit-line-clamp: 2;
303
+ }
304
+
305
+ [data-odn-skill-card-status-badge] {
306
+ position: absolute;
307
+ top: var(--odn-skill-card-padding);
308
+ right: var(--odn-skill-card-padding);
309
+ z-index: 30;
310
+ display: inline-flex;
311
+ box-sizing: border-box;
312
+ height: 22px;
313
+ align-items: center;
314
+ border-radius: 4px;
315
+ padding: 0 8px;
316
+ font-size: 12px;
317
+ font-weight: 500;
318
+ line-height: 22px;
319
+ }
320
+
321
+ [data-odn-skill-card-status-badge=info] {
322
+ color: var(--odn-color-blue-6);
323
+ background: var(--odn-color-blue-1);
324
+ }
325
+
326
+ [data-odn-skill-card-status-badge=error] {
327
+ color: var(--odn-color-red-6);
328
+ background: var(--odn-color-red-1);
329
+ }
330
+
331
+ [data-odn-skill-card-action-group] {
332
+ position: absolute;
333
+ top: var(--odn-skill-card-padding);
334
+ right: var(--odn-skill-card-padding);
335
+ z-index: 30;
336
+ width: 144px;
337
+ height: 30px;
338
+ }
339
+
340
+ [data-odn-skill-card][data-odn-skill-card-control=add] [data-odn-skill-card-action-group],
341
+ [data-odn-skill-card][data-odn-skill-card-control=none] [data-odn-skill-card-action-group] {
342
+ width: 98px;
343
+ }
344
+
345
+ [data-odn-skill-card-default-action] {
346
+ position: absolute;
347
+ inset: 0;
348
+ display: flex;
349
+ align-items: center;
350
+ justify-content: flex-end;
351
+ transition: opacity var(--odn-skill-card-hover-duration) ease-out, transform var(--odn-skill-card-hover-duration) ease-out;
352
+ }
353
+
354
+ [data-odn-skill-card-default-action] [data-odn-button] {
355
+ width: 30px;
356
+ min-width: 30px;
357
+ height: 30px;
358
+ padding: 0;
359
+ }
360
+
361
+ /* 已添加仅保留绿色对勾;未添加仍使用带描边的“+”按钮。 */
362
+ [data-odn-skill-card-default-action] [data-odn-button][data-odn-skill-card-added-action=true],
363
+ [data-odn-skill-card-default-action] [data-odn-button][data-odn-skill-card-added-action=true]:hover {
364
+ color: var(--odn-color-green-6);
365
+ background: var(--odn-color-green-1);
366
+ border-color: transparent;
367
+ }
368
+
369
+ [data-odn-skill-card-hover-actions] {
370
+ position: absolute;
371
+ top: 0;
372
+ right: 0;
373
+ display: flex;
374
+ height: 30px;
375
+ align-items: center;
376
+ gap: var(--odn-skill-card-action-gap);
377
+ pointer-events: none;
378
+ opacity: 0;
379
+ transform: translateX(4px);
380
+ transition: opacity var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease), transform var(--odn-skill-card-hover-duration) var(--odn-skill-card-hover-ease);
381
+ }
382
+
383
+ [data-odn-skill-card][data-odn-skill-card-control=toggle] [data-odn-skill-card-hover-actions] {
384
+ right: 46px;
385
+ }
386
+
387
+ /* 已添加 check 保持同一元素:默认居右,Hover 时位移到「去试试」左侧。 */
388
+ [data-odn-skill-card][data-odn-skill-card-control=add][data-odn-skill-card-added=true] [data-odn-skill-card-default-action] {
389
+ right: 0;
390
+ left: auto;
391
+ width: 30px;
392
+ justify-content: center;
393
+ }
394
+
395
+ [data-odn-skill-card][data-odn-skill-card-control=add][data-odn-skill-card-added=true]:hover [data-odn-skill-card-default-action] {
396
+ transform: translateX(-68px);
397
+ }
398
+
399
+ [data-odn-skill-card][data-odn-skill-card-hoverable=true]:hover [data-odn-skill-card-hover-actions] {
400
+ pointer-events: auto;
401
+ opacity: 1;
402
+ transform: translateX(0);
403
+ }
404
+
405
+ [data-odn-skill-card][data-odn-skill-card-control=add][data-odn-skill-card-added=true]:hover [data-odn-skill-card-hover-actions] {
406
+ right: 0;
407
+ }
408
+
409
+ [data-odn-skill-card-try] {
410
+ width: 60px;
411
+ min-width: 60px;
412
+ }
413
+
414
+ [data-odn-skill-card-hover-actions] [data-odn-button][aria-label=更多操作] {
415
+ width: 30px;
416
+ min-width: 30px;
417
+ height: 30px;
418
+ padding: 0;
419
+ }
420
+
421
+ [data-odn-dropdown-content].odn-skill-card-menu {
422
+ min-width: 120px;
423
+ padding: 4px 0;
424
+ }
425
+
426
+ [data-odn-skill-card-switch] {
427
+ position: absolute;
428
+ top: 5px;
429
+ right: 0;
430
+ }
@@ -0,0 +1,2 @@
1
+ import '../../style';
2
+ import './index.scss';
@@ -0,0 +1,2 @@
1
+ import "../../style";
2
+ import "./index.css";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.88",
3
+ "version": "0.0.89",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "license": "MIT",
6
6
  "type": "module",