one-design-next 0.0.69 → 0.0.71

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 (52) hide show
  1. package/dist/artifact/actions.d.ts +17 -0
  2. package/dist/artifact/actions.js +29 -0
  3. package/dist/artifact/glow.d.ts +7 -0
  4. package/dist/artifact/glow.js +17 -0
  5. package/dist/artifact/icons/ArtifactFileIcon.d.ts +17 -0
  6. package/dist/artifact/icons/ArtifactFileIcon.js +72 -0
  7. package/dist/artifact/icons/file-icons.d.ts +80 -0
  8. package/dist/artifact/icons/file-icons.js +86 -0
  9. package/dist/artifact/icons/index.d.ts +2 -0
  10. package/dist/artifact/icons/index.js +2 -0
  11. package/dist/artifact/icons/medium/csv.svg +25 -0
  12. package/dist/artifact/icons/medium/docx.svg +25 -0
  13. package/dist/artifact/icons/medium/file.svg +25 -0
  14. package/dist/artifact/icons/medium/html.svg +25 -0
  15. package/dist/artifact/icons/medium/md.svg +25 -0
  16. package/dist/artifact/icons/medium/pdf.svg +25 -0
  17. package/dist/artifact/icons/medium/pptx.svg +25 -0
  18. package/dist/artifact/icons/medium/xlsx.svg +25 -0
  19. package/dist/artifact/icons/small/csv.svg +19 -0
  20. package/dist/artifact/icons/small/docx.svg +19 -0
  21. package/dist/artifact/icons/small/file.svg +19 -0
  22. package/dist/artifact/icons/small/html.svg +19 -0
  23. package/dist/artifact/icons/small/md.svg +19 -0
  24. package/dist/artifact/icons/small/pdf.svg +19 -0
  25. package/dist/artifact/icons/small/pptx.svg +19 -0
  26. package/dist/artifact/icons/small/xlsx.svg +19 -0
  27. package/dist/artifact/index.d.ts +35 -16
  28. package/dist/artifact/index.js +187 -180
  29. package/dist/artifact/style/index.css +194 -162
  30. package/dist/composer/index.d.ts +24 -35
  31. package/dist/composer/index.js +212 -106
  32. package/dist/composer/style/index.css +57 -5
  33. package/dist/drawer/index.d.ts +5 -0
  34. package/dist/drawer/index.js +3 -0
  35. package/dist/icon/svg-data.d.ts +20 -0
  36. package/dist/icon/svg-data.js +1 -1
  37. package/dist/icon/types.d.ts +1 -1
  38. package/dist/index.d.ts +2 -2
  39. package/dist/index.js +1 -1
  40. package/dist/modal-base/index.d.ts +7 -0
  41. package/dist/modal-base/index.js +12 -2
  42. package/dist/pop-base/index.d.ts +8 -0
  43. package/dist/pop-base/index.js +8 -1
  44. package/dist/pop-base/style/index.css +8 -0
  45. package/dist/preview-panel/index.d.ts +11 -5
  46. package/dist/preview-panel/index.js +15 -9
  47. package/dist/preview-panel/style/index.css +3 -1
  48. package/dist/skill-slot/index.d.ts +20 -7
  49. package/dist/skill-slot/index.js +191 -105
  50. package/dist/skill-slot/style/index.css +71 -20
  51. package/dist/tooltip/index.js +30 -13
  52. package/package.json +1 -1
@@ -1,33 +1,89 @@
1
- import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
3
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
- import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
4
+ import { Fragment, forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
5
5
  import HoverFill from "../hover-fill";
6
6
  import Icon from "../icon";
7
- import Tooltip from "../tooltip";
7
+ import Popover from "../popover";
8
8
  import "./style";
9
9
 
10
10
  /* 给 listbox / option 生成稳定且唯一的 id 前缀(aria-activedescendant 需要)。
11
11
  * 模块级自增 + useState 初始化,保证每个实例 mount 期间 id 稳定。 */
12
12
  var skillSlotIdSeq = 0;
13
13
 
14
+ /**
15
+ * menu/card 行内描述:仅在被 line-clamp 截断时,hover 0.5s 右侧 Popover 出全文。
16
+ * 始终挂载 Popover(用 visible 关掉未截断态),避免条件挂载导致 ref/测量丢帧。
17
+ */
18
+ function SkillDescPopover(_ref) {
19
+ var description = _ref.description;
20
+ var ref = useRef(null);
21
+ var _useState = useState(false),
22
+ _useState2 = _slicedToArray(_useState, 2),
23
+ truncated = _useState2[0],
24
+ setTruncated = _useState2[1];
25
+ useLayoutEffect(function () {
26
+ var _document$fonts, _document$fonts$then;
27
+ var el = ref.current;
28
+ if (!el) return;
29
+ var measure = function measure() {
30
+ /* line-clamp 截断时 scrollHeight 会大于可见 clientHeight */
31
+ var next = el.scrollHeight > el.clientHeight + 1;
32
+ setTruncated(function (prev) {
33
+ return prev === next ? prev : next;
34
+ });
35
+ };
36
+ measure();
37
+ /* 弹层/字体未稳时首帧易漏判:双 rAF + ResizeObserver + fonts.ready */
38
+ var raf2 = 0;
39
+ var raf1 = requestAnimationFrame(function () {
40
+ measure();
41
+ raf2 = requestAnimationFrame(measure);
42
+ });
43
+ var ro = typeof ResizeObserver !== 'undefined' ? new ResizeObserver(measure) : null;
44
+ ro === null || ro === void 0 || ro.observe(el);
45
+ if (el.parentElement) ro === null || ro === void 0 || ro.observe(el.parentElement);
46
+ var fontsReady = (_document$fonts = document.fonts) === null || _document$fonts === void 0 || (_document$fonts = _document$fonts.ready) === null || _document$fonts === void 0 || (_document$fonts$then = _document$fonts.then) === null || _document$fonts$then === void 0 ? void 0 : _document$fonts$then.call(_document$fonts, measure);
47
+ return function () {
48
+ cancelAnimationFrame(raf1);
49
+ cancelAnimationFrame(raf2);
50
+ ro === null || ro === void 0 || ro.disconnect();
51
+ /* fonts.ready 无法取消,measure 内 setState 在 unmount 后由 React 忽略 */
52
+ void fontsReady;
53
+ };
54
+ }, [description]);
55
+ return /*#__PURE__*/React.createElement(Popover, {
56
+ placement: "right",
57
+ mouseEnterDelay: 0.5
58
+ /* 未截断强制关闭;截断后交还给 hover 非受控 */,
59
+ visible: truncated ? undefined : false,
60
+ popup: /*#__PURE__*/React.createElement("span", {
61
+ "data-odn-skill-slot-desc-full": true
62
+ }, description)
63
+ }, /*#__PURE__*/React.createElement("span", {
64
+ ref: ref,
65
+ "data-odn-skill-slot-item-desc": true
66
+ }, description));
67
+ }
68
+
14
69
  /** 命令式句柄:供"焦点不在 menu 上"的宿主(如 composer 的 contenteditable)转发键盘。 */
15
70
 
16
- export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
17
- var skillsProp = _ref.skills,
18
- skillGroups = _ref.skillGroups,
19
- _ref$variant = _ref.variant,
20
- variant = _ref$variant === void 0 ? 'bar' : _ref$variant,
21
- value = _ref.value,
22
- onSelect = _ref.onSelect,
23
- onManageSkills = _ref.onManageSkills,
24
- skillManageFooter = _ref.skillManageFooter,
25
- activeIndex = _ref.activeIndex,
26
- onActiveIndexChange = _ref.onActiveIndexChange,
27
- menuMaxHeight = _ref.menuMaxHeight,
28
- itemWidth = _ref.itemWidth,
29
- className = _ref.className,
30
- style = _ref.style;
71
+ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
72
+ var skillsProp = _ref2.skills,
73
+ skillGroups = _ref2.skillGroups,
74
+ showGroupTitlesProp = _ref2.showGroupTitles,
75
+ _ref2$variant = _ref2.variant,
76
+ variant = _ref2$variant === void 0 ? 'bar' : _ref2$variant,
77
+ onSelect = _ref2.onSelect,
78
+ onManageSkills = _ref2.onManageSkills,
79
+ skillManageFooter = _ref2.skillManageFooter,
80
+ activeIndex = _ref2.activeIndex,
81
+ onActiveIndexChange = _ref2.onActiveIndexChange,
82
+ menuMaxHeight = _ref2.menuMaxHeight,
83
+ menuWidth = _ref2.menuWidth,
84
+ itemWidth = _ref2.itemWidth,
85
+ className = _ref2.className,
86
+ style = _ref2.style;
31
87
  /* 优先使用 skillGroups,否则回退到 skills;两者都未提供则为空数组。 */
32
88
  var skills = useMemo(function () {
33
89
  if (skillGroups) return skillGroups.flatMap(function (g) {
@@ -35,6 +91,8 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
35
91
  });
36
92
  return skillsProp !== null && skillsProp !== void 0 ? skillsProp : [];
37
93
  }, [skillGroups, skillsProp]);
94
+ var showGroupTitles = showGroupTitlesProp !== null && showGroupTitlesProp !== void 0 ? showGroupTitlesProp : variant === 'menu';
95
+ var groupedWithTitles = !!(skillGroups && showGroupTitles);
38
96
  /* menu 变体:HoverFill 完全只管鼠标交互(命令式状态机,不变);键盘 ↑↓
39
97
  * 走独立的 CSS [data-odn-skill-slot-item-highlighted] 视觉层。
40
98
  *
@@ -52,22 +110,22 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
52
110
  * 维护高亮 index,监听 ↑↓ / Home / End 移动、Enter / Space 选中,
53
111
  * 并自动跳过 disabled 项、把高亮项滚动进视口。 */
54
112
 
55
- var _useState = useState(function () {
113
+ var _useState3 = useState(function () {
56
114
  return "odn-skill-slot-".concat(++skillSlotIdSeq);
57
115
  }),
58
- _useState2 = _slicedToArray(_useState, 1),
59
- listboxId = _useState2[0];
60
- var _useState3 = useState(-1),
61
- _useState4 = _slicedToArray(_useState3, 2),
62
- internalActiveIndex = _useState4[0],
63
- setInternalActiveIndex = _useState4[1];
64
- var isControlled = activeIndex != null;
116
+ _useState4 = _slicedToArray(_useState3, 1),
117
+ listboxId = _useState4[0];
118
+ var _useState5 = useState(-1),
119
+ _useState6 = _slicedToArray(_useState5, 2),
120
+ internalActiveIndex = _useState6[0],
121
+ setInternalActiveIndex = _useState6[1];
122
+ var isControlled = activeIndex !== undefined && activeIndex !== null;
65
123
  var currentIndex = isControlled ? activeIndex : internalActiveIndex;
66
124
  var itemRefs = useRef([]);
67
125
 
68
- /* disabled 与 active 互斥:已选中项不算 disabled(与渲染逻辑保持一致)。 */
126
+ /* SkillItem.disabled 为唯一禁用来源(不再与选中态互斥)。 */
69
127
  var isItemDisabled = function isItemDisabled(skill) {
70
- return !!skill.disabled && value !== skill.id;
128
+ return !!skill.disabled;
71
129
  };
72
130
 
73
131
  /* 高亮项变化时滚动进视口(menu 列表可能超出浮层高度)。 */
@@ -175,18 +233,17 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
175
233
  if (skills.length === 0) return null;
176
234
 
177
235
  /* menu variant 有 scroll-wrap 时,滚动仅包裹技能列表,footer 固定在底部不参与滚动。 */
178
- var hasScrollWrap = variant === 'menu' && menuMaxHeight != null;
236
+ var hasScrollWrap = variant === 'menu' && menuMaxHeight !== undefined && menuMaxHeight !== null;
179
237
 
180
238
  /* 渲染单个菜单项(menu variant)——提取为独立函数以便扁平/分组共用。 */
181
239
  var renderMenuItem = function renderMenuItem(skill, index) {
182
- var active = value === skill.id;
183
240
  var highlighted = currentIndex === index;
184
- var disabled = !!skill.disabled && !active;
241
+ var disabled = !!skill.disabled;
185
242
  return /*#__PURE__*/React.createElement(HoverFill, {
186
243
  key: skill.id,
187
244
  "data-odn-skill-slot-item-wrap": true,
188
245
  bgClassName: "odn-skill-slot-item-bg",
189
- disabled: active || disabled,
246
+ disabled: disabled,
190
247
  onMouseEnter: function onMouseEnter() {
191
248
  if (disabled) return;
192
249
  if (isControlled) {
@@ -205,7 +262,6 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
205
262
  itemRefs.current[index] = el;
206
263
  },
207
264
  "data-odn-skill-slot-item": true,
208
- "data-odn-skill-slot-item-active": active || undefined,
209
265
  "data-odn-skill-slot-item-highlighted": highlighted || undefined,
210
266
  "data-odn-skill-slot-item-disabled": disabled || undefined,
211
267
  role: "option",
@@ -223,9 +279,9 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
223
279
  "data-odn-skill-slot-item-content": true
224
280
  }, /*#__PURE__*/React.createElement("span", {
225
281
  "data-odn-skill-slot-item-label": true
226
- }, skill.label), skill.description && /*#__PURE__*/React.createElement("span", {
227
- "data-odn-skill-slot-item-desc": true
228
- }, skill.description))));
282
+ }, skill.label), skill.description ? /*#__PURE__*/React.createElement(SkillDescPopover, {
283
+ description: skill.description
284
+ }) : null)));
229
285
  };
230
286
 
231
287
  /* 渲染底部"技能管理"按钮(仅 menu 变体 + 提供 onManageSkills 时。不参与键盘导航)。 */
@@ -246,83 +302,108 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
246
302
  onClick: onManageSkills
247
303
  }, skillManageFooter !== null && skillManageFooter !== void 0 ? skillManageFooter : defaultFooter));
248
304
  };
305
+ var renderCardItem = function renderCardItem(skill) {
306
+ var disabled = !!skill.disabled;
307
+ return /*#__PURE__*/React.createElement("button", {
308
+ key: skill.id,
309
+ type: "button",
310
+ "data-odn-skill-slot-item": true,
311
+ "data-odn-skill-slot-item-disabled": disabled || undefined,
312
+ disabled: disabled,
313
+ "aria-disabled": disabled || undefined,
314
+ onClick: function onClick() {
315
+ return onSelect === null || onSelect === void 0 ? void 0 : onSelect(skill);
316
+ }
317
+ }, /*#__PURE__*/React.createElement("span", {
318
+ "data-odn-skill-slot-card-header": true
319
+ }, /*#__PURE__*/React.createElement("span", {
320
+ "data-odn-skill-slot-item-icon": true
321
+ }, /*#__PURE__*/React.createElement(Icon, {
322
+ name: skill.icon,
323
+ size: 16
324
+ })), /*#__PURE__*/React.createElement("span", {
325
+ "data-odn-skill-slot-item-label": true
326
+ }, skill.label)), skill.description ? /*#__PURE__*/React.createElement(SkillDescPopover, {
327
+ description: skill.description
328
+ }) : null);
329
+ };
330
+ var renderBarItem = function renderBarItem(skill) {
331
+ var disabled = !!skill.disabled;
332
+ var barButton = /*#__PURE__*/React.createElement("button", {
333
+ key: skill.id,
334
+ type: "button",
335
+ "data-odn-skill-slot-item": true,
336
+ "data-odn-skill-slot-item-disabled": disabled || undefined,
337
+ disabled: disabled,
338
+ "aria-disabled": disabled || undefined,
339
+ onClick: function onClick() {
340
+ return onSelect === null || onSelect === void 0 ? void 0 : onSelect(skill);
341
+ }
342
+ }, /*#__PURE__*/React.createElement(Icon, {
343
+ name: skill.icon,
344
+ size: 14
345
+ }), skill.label);
346
+
347
+ /* bar 无行内描述:整颗 chip hover 0.5s 后向上 Popover 出全文 */
348
+ if (skill.description) {
349
+ return /*#__PURE__*/React.createElement(Popover, {
350
+ key: skill.id,
351
+ placement: "top",
352
+ mouseEnterDelay: 0.5,
353
+ popup: /*#__PURE__*/React.createElement("span", {
354
+ "data-odn-skill-slot-desc-full": true
355
+ }, skill.description)
356
+ }, barButton);
357
+ }
358
+ return barButton;
359
+ };
249
360
 
250
- /* 分组模式下渲染 menu 列表(带分组标题)。 */
251
- var renderMenuGroups = function renderMenuGroups() {
361
+ /* 分组渲染:是否画标题由 showGroupTitles 决定。
362
+ * menu 项必须与标题/分割线同级挂在 list 根下——HoverFill 跨项共享背景要求同一
363
+ * parentNode;若再包一层 group / group-items,跨组必闪。bar/card 不用 HoverFill,
364
+ * 仍用 group 壳承接 flex/grid。 */
365
+ var renderGroups = function renderGroups() {
252
366
  var flatIndex = 0;
253
- return /*#__PURE__*/React.createElement(React.Fragment, null, skillGroups.map(function (group) {
367
+ if (variant === 'menu') {
368
+ return /*#__PURE__*/React.createElement(React.Fragment, null, skillGroups.map(function (group, groupIdx) {
369
+ return /*#__PURE__*/React.createElement(Fragment, {
370
+ key: group.groupName || "_group_".concat(groupIdx)
371
+ }, groupIdx > 0 ? /*#__PURE__*/React.createElement("div", {
372
+ "data-odn-skill-slot-divider": true,
373
+ "data-odn-skill-slot-group-divider": true
374
+ }) : null, showGroupTitles && group.groupName ? /*#__PURE__*/React.createElement("div", {
375
+ "data-odn-skill-slot-group-header": true
376
+ }, group.groupName) : null, group.skills.map(function (skill) {
377
+ return renderMenuItem(skill, flatIndex++);
378
+ }));
379
+ }));
380
+ }
381
+ return /*#__PURE__*/React.createElement(React.Fragment, null, skillGroups.map(function (group, groupIdx) {
254
382
  return /*#__PURE__*/React.createElement("div", {
255
- key: group.groupName || "_group_".concat(flatIndex)
256
- }, group.groupName && /*#__PURE__*/React.createElement("div", {
383
+ key: group.groupName || "_group_".concat(groupIdx),
384
+ "data-odn-skill-slot-group": true
385
+ }, showGroupTitles && group.groupName ? /*#__PURE__*/React.createElement("div", {
257
386
  "data-odn-skill-slot-group-header": true
258
- }, group.groupName), group.skills.map(function (skill) {
259
- var idx = flatIndex++;
260
- return renderMenuItem(skill, idx);
261
- }));
387
+ }, group.groupName) : null, /*#__PURE__*/React.createElement("div", {
388
+ "data-odn-skill-slot-group-items": true
389
+ }, group.skills.map(function (skill) {
390
+ return variant === 'card' ? renderCardItem(skill) : renderBarItem(skill);
391
+ })));
262
392
  }));
263
393
  };
264
394
 
265
395
  /* 扁平模式下渲染所有项(menu / bar / card)。 */
266
396
  var renderFlatItems = function renderFlatItems() {
267
397
  return skills.map(function (skill, index) {
268
- var active = value === skill.id;
269
- var highlighted = currentIndex === index;
270
- var disabled = !!skill.disabled && !active;
271
- if (variant === 'card') {
272
- return /*#__PURE__*/React.createElement("button", {
273
- key: skill.id,
274
- type: "button",
275
- "data-odn-skill-slot-item": true,
276
- "data-odn-skill-slot-item-active": active || undefined,
277
- "data-odn-skill-slot-item-disabled": disabled || undefined,
278
- disabled: disabled,
279
- "aria-disabled": disabled || undefined,
280
- onClick: function onClick() {
281
- return onSelect === null || onSelect === void 0 ? void 0 : onSelect(skill);
282
- }
283
- }, /*#__PURE__*/React.createElement("span", {
284
- "data-odn-skill-slot-card-header": true
285
- }, /*#__PURE__*/React.createElement("span", {
286
- "data-odn-skill-slot-item-icon": true
287
- }, /*#__PURE__*/React.createElement(Icon, {
288
- name: skill.icon,
289
- size: 16
290
- })), /*#__PURE__*/React.createElement("span", {
291
- "data-odn-skill-slot-item-label": true
292
- }, skill.label)), skill.description && /*#__PURE__*/React.createElement("span", {
293
- "data-odn-skill-slot-item-desc": true
294
- }, skill.description));
295
- }
296
- if (variant === 'menu') {
297
- return renderMenuItem(skill, index);
298
- }
299
- var barButton = /*#__PURE__*/React.createElement("button", {
300
- key: skill.id,
301
- type: "button",
302
- "data-odn-skill-slot-item": true,
303
- "data-odn-skill-slot-item-active": active || undefined,
304
- "data-odn-skill-slot-item-disabled": disabled || undefined,
305
- disabled: disabled,
306
- "aria-disabled": disabled || undefined,
307
- onClick: function onClick() {
308
- return onSelect === null || onSelect === void 0 ? void 0 : onSelect(skill);
309
- }
310
- }, /*#__PURE__*/React.createElement(Icon, {
311
- name: skill.icon,
312
- size: 14
313
- }), skill.label);
314
- if (skill.description) {
315
- return /*#__PURE__*/React.createElement(Tooltip, {
316
- key: skill.id,
317
- popup: skill.description,
318
- placement: "top",
319
- offset: 6
320
- }, barButton);
321
- }
322
- return barButton;
398
+ if (variant === 'card') return renderCardItem(skill);
399
+ if (variant === 'menu') return renderMenuItem(skill, index);
400
+ return renderBarItem(skill);
323
401
  });
324
402
  };
325
- var listBody = variant === 'menu' && skillGroups ? renderMenuGroups() : renderFlatItems();
403
+
404
+ /* 有 skillGroups:始终按组遍历(保序);无标题时仍走分组 DOM,仅不渲染 header,
405
+ * bar/card 用 group-items 承接原有 flex/grid,避免拍平后丢组边界。 */
406
+ var listBody = skillGroups ? renderGroups() : renderFlatItems();
326
407
  var manageFooter = renderManageFooter();
327
408
 
328
409
  /* 共享的属性容器:menu variant 的 aria / keyboard / 交互属性 */
@@ -335,13 +416,19 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
335
416
  onFocus: handleMenuFocus,
336
417
  onBlur: handleMenuBlur
337
418
  } : {};
419
+ var rootStyle = _objectSpread(_objectSpread(_objectSpread({}, variant === 'menu' && menuWidth !== undefined && menuWidth !== null ? {
420
+ width: menuWidth
421
+ } : {}), variant !== 'menu' && itemWidth !== undefined && itemWidth !== null ? {
422
+ '--odn-skill-slot-item-width': "".concat(itemWidth, "px")
423
+ } : {}), style);
338
424
  if (hasScrollWrap) {
339
425
  /* 滚动仅包裹技能列表,footer 固定在底部不参与滚动 */
340
426
  return /*#__PURE__*/React.createElement("div", _extends({
341
427
  "data-odn-skill-slot": true,
342
428
  "data-odn-skill-slot-variant": variant,
429
+ "data-odn-skill-slot-grouped": groupedWithTitles || undefined,
343
430
  className: className,
344
- style: style
431
+ style: rootStyle
345
432
  }, listAttrs), /*#__PURE__*/React.createElement("div", {
346
433
  "data-odn-skill-slot-scroll-wrap": true,
347
434
  style: {
@@ -353,10 +440,9 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref, ref) {
353
440
  return /*#__PURE__*/React.createElement("div", _extends({
354
441
  "data-odn-skill-slot": true,
355
442
  "data-odn-skill-slot-variant": variant,
443
+ "data-odn-skill-slot-grouped": groupedWithTitles || undefined,
356
444
  className: className,
357
- style: _objectSpread(_objectSpread({}, variant !== 'menu' && itemWidth != null ? {
358
- '--odn-skill-slot-item-width': "".concat(itemWidth, "px")
359
- } : {}), style)
445
+ style: rootStyle
360
446
  }, listAttrs), listBody, manageFooter);
361
447
  });
362
448
  SkillSlot.displayName = 'SkillSlot';
@@ -74,7 +74,7 @@
74
74
  * 之外的,但布局上 button 和 HoverFill 占同位置;button 给个 background 不会
75
75
  * 跟 HoverFill 视觉打架,但 ::before 写法以后想加扩散动画更灵活。 */
76
76
  }
77
- [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-item][data-odn-skill-slot-item-highlighted]:not(:hover):not([data-odn-skill-slot-item-active])::before {
77
+ [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-item][data-odn-skill-slot-item-highlighted]:not(:hover)::before {
78
78
  content: "";
79
79
  position: absolute;
80
80
  inset: 0;
@@ -84,10 +84,6 @@
84
84
  pointer-events: none;
85
85
  z-index: -1;
86
86
  }
87
- [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-item][data-odn-skill-slot-item-active] {
88
- color: var(--odn-color-brand-6);
89
- background: color-mix(in srgb, var(--odn-color-brand-6) 10%, transparent);
90
- }
91
87
 
92
88
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-item-label] {
93
89
  font-size: 13px;
@@ -96,6 +92,14 @@
96
92
 
97
93
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-item-desc] {
98
94
  font-size: 12px;
95
+ line-height: 20px;
96
+ color: var(--odn-color-black-9);
97
+ /* 描述固定最多 2 行,不可配置 */
98
+ display: -webkit-box;
99
+ -webkit-box-orient: vertical;
100
+ -webkit-line-clamp: 2;
101
+ overflow: hidden;
102
+ word-break: break-word;
99
103
  }
100
104
 
101
105
  /* ---- menu 分组标题 ---- */
@@ -111,6 +115,45 @@
111
115
  pointer-events: none;
112
116
  }
113
117
 
118
+ /* 无组标题时:group 壳不参与布局,子项仍挂在根 flex/grid 上(与拍平一致) */
119
+ [data-odn-skill-slot]:not([data-odn-skill-slot-grouped]) [data-odn-skill-slot-group],
120
+ [data-odn-skill-slot]:not([data-odn-skill-slot-grouped]) [data-odn-skill-slot-group-items] {
121
+ display: contents;
122
+ }
123
+
124
+ /* 有组标题:根改为纵向堆叠组;组内再承接原 bar flex / card grid */
125
+ [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=bar],
126
+ [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=card] {
127
+ display: flex;
128
+ flex-direction: column;
129
+ flex-wrap: nowrap;
130
+ gap: 12px;
131
+ grid-template-columns: none;
132
+ }
133
+
134
+ [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=bar] [data-odn-skill-slot-group-items] {
135
+ display: flex;
136
+ flex-wrap: wrap;
137
+ gap: 8px;
138
+ }
139
+
140
+ [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=card] [data-odn-skill-slot-group-items] {
141
+ display: grid;
142
+ grid-template-columns: repeat(2, 1fr);
143
+ gap: 10px;
144
+ }
145
+
146
+ [data-odn-skill-slot][data-odn-skill-slot-variant=bar] [data-odn-skill-slot-group-header],
147
+ [data-odn-skill-slot][data-odn-skill-slot-variant=card] [data-odn-skill-slot-group-header] {
148
+ padding: 0 2px;
149
+ font-size: 12px;
150
+ font-weight: 600;
151
+ color: var(--odn-color-black-8);
152
+ line-height: 20px;
153
+ user-select: none;
154
+ pointer-events: none;
155
+ }
156
+
114
157
  /* ---- menu 底部分隔线 ---- */
115
158
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-divider] {
116
159
  margin: 4px 0;
@@ -118,6 +161,11 @@
118
161
  background: var(--odn-color-black-5);
119
162
  }
120
163
 
164
+ /* 组间分割线:略收紧上下留白,避免与组标题叠出过大空隙 */
165
+ [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-group-divider] {
166
+ margin: 4px 0 2px;
167
+ }
168
+
121
169
  /* ---- menu 底部管理按钮 ---- */
122
170
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-manage-btn] {
123
171
  display: flex;
@@ -174,11 +222,6 @@
174
222
  background: var(--odn-color-black-3);
175
223
  color: var(--odn-color-black-12);
176
224
  }
177
- [data-odn-skill-slot][data-odn-skill-slot-variant=bar] [data-odn-skill-slot-item][data-odn-skill-slot-item-active] {
178
- border-color: var(--odn-color-brand-6);
179
- background: color-mix(in srgb, var(--odn-color-brand-6) 8%, transparent);
180
- color: var(--odn-color-brand-6);
181
- }
182
225
 
183
226
  /* ---- variant: card ---- */
184
227
  [data-odn-skill-slot][data-odn-skill-slot-variant=card] {
@@ -206,13 +249,6 @@
206
249
  background: var(--odn-color-white);
207
250
  box-shadow: var(--odn-shadow-1);
208
251
  }
209
- [data-odn-skill-slot][data-odn-skill-slot-variant=card] [data-odn-skill-slot-item][data-odn-skill-slot-item-active] {
210
- background: color-mix(in srgb, var(--odn-color-cyan-5) 8%, var(--odn-color-white));
211
- box-shadow: 0 0 0 1px color-mix(in srgb, var(--odn-color-cyan-5) 16%, transparent);
212
- }
213
- [data-odn-skill-slot][data-odn-skill-slot-variant=card] [data-odn-skill-slot-item][data-odn-skill-slot-item-active] [data-odn-skill-slot-item-label] {
214
- color: var(--odn-color-brand-6);
215
- }
216
252
 
217
253
  [data-odn-skill-slot][data-odn-skill-slot-variant=card] [data-odn-skill-slot-card-header] {
218
254
  display: inline-flex;
@@ -242,9 +278,13 @@
242
278
  font-weight: 400;
243
279
  color: var(--odn-color-black-9);
244
280
  line-height: 20px;
245
- white-space: nowrap;
281
+ /* 描述固定最多 2 行,不可配置(原单行 ellipsis 改为 2 行 clamp) */
282
+ display: -webkit-box;
283
+ -webkit-box-orient: vertical;
284
+ -webkit-line-clamp: 2;
246
285
  overflow: hidden;
247
- text-overflow: ellipsis;
286
+ word-break: break-word;
287
+ white-space: normal;
248
288
  }
249
289
 
250
290
  [data-odn-skill-slot-item-content] {
@@ -264,6 +304,17 @@
264
304
 
265
305
  [data-odn-skill-slot-item-desc] {
266
306
  font-size: 12px;
267
- color: var(--odn-color-black-8);
307
+ color: var(--odn-color-black-9);
268
308
  line-height: 20px;
309
+ }
310
+
311
+ /* 描述全文 Popover 内容 */
312
+ [data-odn-skill-slot-desc-full] {
313
+ display: inline-block;
314
+ max-width: 280px;
315
+ font-size: 12px;
316
+ line-height: 20px;
317
+ color: var(--odn-color-black-9);
318
+ word-break: break-word;
319
+ white-space: pre-wrap;
269
320
  }
@@ -2,7 +2,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
3
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
4
  import _extends from "@babel/runtime/helpers/esm/extends";
5
- var _excluded = ["as", "arrowed", "autoPlacements", "offset", "popupStyle", "popupClassName", "mouseEnterDelay", "mouseLeaveDelay", "flip", "matchWidth", "portal", "shift", "children", "placement"],
5
+ var _excluded = ["as", "arrowed", "autoPlacements", "offset", "popupStyle", "popupClassName", "mouseEnterDelay", "mouseLeaveDelay", "flip", "matchWidth", "portal", "shift", "children", "placement", "visible", "transitionDuration"],
6
6
  _excluded2 = ["onMouseEnter", "onMouseLeave"];
7
7
  import React, { useEffect, useRef, useState } from 'react';
8
8
  import PopBase from "../pop-base";
@@ -31,6 +31,8 @@ var TooltipGroup = function TooltipGroup(props) {
31
31
  children = props.children,
32
32
  _props$placement = props.placement,
33
33
  placement = _props$placement === void 0 ? 'top' : _props$placement,
34
+ visibleProp = props.visible,
35
+ transitionDuration = props.transitionDuration,
34
36
  otherProps = _objectWithoutProperties(props, _excluded);
35
37
  var Tag = as;
36
38
  var tooltipInfos = React.Children.toArray(children).map(function (child) {
@@ -61,7 +63,20 @@ var TooltipGroup = function TooltipGroup(props) {
61
63
  _useState8 = _slicedToArray(_useState7, 2),
62
64
  offsetY = _useState8[0],
63
65
  setOffsetY = _useState8[1];
66
+
67
+ /* 受控 visible=false:强制收起(如 Composer 技能菜单展开时禁用入口 tooltip) */
68
+ useEffect(function () {
69
+ if (visibleProp === false) {
70
+ clearTimeout(hoverTimer.current);
71
+ setVisible(false);
72
+ }
73
+ }, [visibleProp]);
74
+ var effectiveVisible = visibleProp === false ? false : visible;
64
75
  var handleMouseEnter = function handleMouseEnter(e, index) {
76
+ var _tooltipInfos$index;
77
+ if (visibleProp === false) return;
78
+ var popup = (_tooltipInfos$index = tooltipInfos[index]) === null || _tooltipInfos$index === void 0 ? void 0 : _tooltipInfos$index.popup;
79
+ if (popup === false || popup === null || popup === undefined) return;
65
80
  clearTimeout(hoverTimer.current);
66
81
  var currentTarget = e.currentTarget;
67
82
  hoverTimer.current = window.setTimeout(function () {
@@ -83,25 +98,25 @@ var TooltipGroup = function TooltipGroup(props) {
83
98
  targetTop = _currentTarget$getBou.top,
84
99
  targetWidth = _currentTarget$getBou.width,
85
100
  targetHeight = _currentTarget$getBou.height;
86
- var offsetX = 0;
87
- var offsetY = 0;
101
+ var nextOffsetX = 0;
102
+ var nextOffsetY = 0;
88
103
  if (placement.startsWith('top') || placement.startsWith('bottom')) {
89
- offsetX = targetLeft - left - width / 2 + targetWidth / 2;
104
+ nextOffsetX = targetLeft - left - width / 2 + targetWidth / 2;
90
105
  if (placement.startsWith('top')) {
91
- offsetY = targetTop - top;
106
+ nextOffsetY = targetTop - top;
92
107
  } else {
93
- offsetY = targetTop - top - height + targetHeight;
108
+ nextOffsetY = targetTop - top - height + targetHeight;
94
109
  }
95
110
  } else if (placement.startsWith('left') || placement.startsWith('right')) {
96
- offsetY = targetTop - top - height / 2 + targetHeight / 2;
111
+ nextOffsetY = targetTop - top - height / 2 + targetHeight / 2;
97
112
  if (placement.startsWith('left')) {
98
- offsetX = targetLeft - left;
113
+ nextOffsetX = targetLeft - left;
99
114
  } else {
100
- offsetX = targetLeft - left - width + targetWidth;
115
+ nextOffsetX = targetLeft - left - width + targetWidth;
101
116
  }
102
117
  }
103
- setOffsetX(offsetX);
104
- setOffsetY(offsetY);
118
+ setOffsetX(nextOffsetX);
119
+ setOffsetY(nextOffsetY);
105
120
  }, visible ? 0 : mouseEnterDelay * 1000);
106
121
  };
107
122
  var handleMouseLeave = function handleMouseLeave() {
@@ -135,9 +150,11 @@ var TooltipGroup = function TooltipGroup(props) {
135
150
  portal: portal,
136
151
  shift: shift,
137
152
  placement: placement,
138
- visible: visible,
153
+ visible: effectiveVisible
154
+ /* 受控强制收起时硬切,避免与技能面板等叠层时残留淡出 */,
155
+ transitionDuration: visibleProp === false ? 0 : transitionDuration,
139
156
  popupStyle: _objectSpread(_objectSpread({}, popupStyle), {}, {
140
- transform: "translate(".concat(offsetX, "px, ").concat(offsetY, "px) scale(").concat(visible ? 1 : 0.8, ")")
157
+ transform: "translate(".concat(offsetX, "px, ").concat(offsetY, "px) scale(").concat(effectiveVisible ? 1 : 0.8, ")")
141
158
  })
142
159
  }, /*#__PURE__*/React.createElement(Tag, _objectSpread({
143
160
  ref: tagRef
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.69",
3
+ "version": "0.0.71",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "license": "MIT",
6
6
  "type": "module",