one-design-next 0.0.90 → 0.0.92

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.
@@ -127,5 +127,23 @@ export declare function shouldOpenSlashTriggerMenu(trigger: string | null | unde
127
127
  export declare const COMPOSER_SKILL_MENU_INSET_PX = 24;
128
128
  /** box 尚未量到宽度时的兜底(与旧默认对齐)。 */
129
129
  export declare const COMPOSER_SKILL_MENU_FALLBACK_WIDTH = 260;
130
- /** 未显式传 menuWidth 时,菜单比 composer box 略窄。 */
131
- export declare function resolveComposerSkillMenuWidth(explicit: number | undefined, boxWidth: number): number;
130
+ /** 高窗口下列表密度上限;矮窗会被视口截住。 */
131
+ export declare const COMPOSER_SKILL_MENU_DENSITY_CAP_PX = 280;
132
+ /** 列表高度地板,约两条 skill,避免搜索把列表挤成 0。 */
133
+ export declare const COMPOSER_SKILL_MENU_MIN_LIST_PX = 88;
134
+ /** 菜单与视口边缘的安全边距。 */
135
+ export declare const COMPOSER_SKILL_MENU_VIEWPORT_GUTTER_PX = 8;
136
+ /** 搜索栏 / 管理入口 / 菜单 padding,不进入列表滚动区。 */
137
+ export declare const COMPOSER_SKILL_MENU_CHROME_PX = 48;
138
+ /** Popover 贴在触发点上方的 mainAxis offset。 */
139
+ export declare const COMPOSER_SKILL_MENU_OFFSET_PX = 4;
140
+ /** 菜单宽跟随 composer box,比输入框略窄。 */
141
+ export declare function resolveComposerSkillMenuWidth(boxWidth: number): number;
142
+ /**
143
+ * 列表 maxHeight:密度上限与触发点上方可用空间取更矮,再夹到地板。
144
+ * placement=top 且不翻转,故只算上方剩余。
145
+ */
146
+ export declare function resolveComposerSkillMenuMaxHeight(input: {
147
+ triggerTop: number;
148
+ viewportHeight: number;
149
+ }): number;
@@ -505,12 +505,32 @@ export function shouldOpenSlashTriggerMenu(trigger, hitCount) {
505
505
  export var COMPOSER_SKILL_MENU_INSET_PX = 24;
506
506
  /** box 尚未量到宽度时的兜底(与旧默认对齐)。 */
507
507
  export var COMPOSER_SKILL_MENU_FALLBACK_WIDTH = 260;
508
-
509
- /** 未显式传 menuWidth 时,菜单比 composer box 略窄。 */
510
- export function resolveComposerSkillMenuWidth(explicit, boxWidth) {
511
- if (explicit !== undefined) return explicit;
508
+ /** 高窗口下列表密度上限;矮窗会被视口截住。 */
509
+ export var COMPOSER_SKILL_MENU_DENSITY_CAP_PX = 280;
510
+ /** 列表高度地板,约两条 skill,避免搜索把列表挤成 0。 */
511
+ export var COMPOSER_SKILL_MENU_MIN_LIST_PX = 88;
512
+ /** 菜单与视口边缘的安全边距。 */
513
+ export var COMPOSER_SKILL_MENU_VIEWPORT_GUTTER_PX = 8;
514
+ /** 搜索栏 / 管理入口 / 菜单 padding,不进入列表滚动区。 */
515
+ export var COMPOSER_SKILL_MENU_CHROME_PX = 48;
516
+ /** Popover 贴在触发点上方的 mainAxis offset。 */
517
+ export var COMPOSER_SKILL_MENU_OFFSET_PX = 4;
518
+
519
+ /** 菜单宽跟随 composer box,比输入框略窄。 */
520
+ export function resolveComposerSkillMenuWidth(boxWidth) {
512
521
  if (boxWidth > COMPOSER_SKILL_MENU_INSET_PX) {
513
522
  return Math.round(boxWidth - COMPOSER_SKILL_MENU_INSET_PX);
514
523
  }
515
524
  return COMPOSER_SKILL_MENU_FALLBACK_WIDTH;
525
+ }
526
+
527
+ /**
528
+ * 列表 maxHeight:密度上限与触发点上方可用空间取更矮,再夹到地板。
529
+ * placement=top 且不翻转,故只算上方剩余。
530
+ */
531
+ export function resolveComposerSkillMenuMaxHeight(input) {
532
+ var spaceAbove = input.triggerTop - COMPOSER_SKILL_MENU_VIEWPORT_GUTTER_PX - COMPOSER_SKILL_MENU_OFFSET_PX;
533
+ var available = spaceAbove - COMPOSER_SKILL_MENU_CHROME_PX;
534
+ var capped = Math.min(COMPOSER_SKILL_MENU_DENSITY_CAP_PX, available);
535
+ return Math.max(COMPOSER_SKILL_MENU_MIN_LIST_PX, Math.round(capped));
516
536
  }
@@ -6,6 +6,7 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
6
6
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
7
7
  var _excluded = ["bgClassName", "bgStyle", "children", "onMouseEnter", "onMouseLeave", "onMouseDown", "hoverColor", "activeColor", "disabled", "hoverCursor"];
8
8
  import React, { forwardRef, useCallback, useContext, useEffect, useRef } from 'react';
9
+ import { observeResize } from "../_util/sharedResizeObserver";
9
10
  import { ConfigContext } from "../config-provider";
10
11
  import "./style";
11
12
  var DEFAULT_HOVER_COLOR = 'rgba(33, 34, 38, 0.05)';
@@ -66,8 +67,6 @@ var HoverFill = /*#__PURE__*/forwardRef(function (_ref, outerRef) {
66
67
  y = _root$getBoundingClie.y;
67
68
  if (window.odnHoverFillState && window.odnHoverFillState.bgVisible && window.odnHoverFillState.bgNode && window.odnHoverFillState.baseNode && window.odnHoverFillState.baseNode !== root && ((_window$odnHoverFillS3 = window.odnHoverFillState.baseNode) === null || _window$odnHoverFillS3 === void 0 ? void 0 : _window$odnHoverFillS3.parentNode) === root.parentNode && hoverFillConfig.sharable) {
68
69
  var _window$odnHoverFillS4 = window.odnHoverFillState,
69
- bgX = _window$odnHoverFillS4.bgX,
70
- bgY = _window$odnHoverFillS4.bgY,
71
70
  bgScale = _window$odnHoverFillS4.bgScale,
72
71
  baseNode = _window$odnHoverFillS4.baseNode;
73
72
  var _baseNode$getBounding = baseNode.getBoundingClientRect(),
@@ -205,6 +204,12 @@ var HoverFill = /*#__PURE__*/forwardRef(function (_ref, outerRef) {
205
204
  }, 0);
206
205
  }, 100);
207
206
  };
207
+ var handleMouseUp = function handleMouseUp() {
208
+ window.removeEventListener('mouseup', handleMouseUp, false);
209
+ if (window.odnHoverFillState.bgNode) {
210
+ window.odnHoverFillState.bgNode.style.background = window.odnHoverFillState.bgVisible ? hoverColor : 'transparent';
211
+ }
212
+ };
208
213
  var handleMouseDown = function handleMouseDown(e) {
209
214
  e.persist();
210
215
  if (disabled) {
@@ -218,12 +223,6 @@ var HoverFill = /*#__PURE__*/forwardRef(function (_ref, outerRef) {
218
223
  }
219
224
  window.addEventListener('mouseup', handleMouseUp, false);
220
225
  };
221
- var handleMouseUp = function handleMouseUp() {
222
- window.removeEventListener('mouseup', handleMouseUp, false);
223
- if (window.odnHoverFillState.bgNode) {
224
- window.odnHoverFillState.bgNode.style.background = window.odnHoverFillState.bgVisible ? hoverColor : 'transparent';
225
- }
226
- };
227
226
  useEffect(function () {
228
227
  if (!window.odnHoverFillState) {
229
228
  window.odnHoverFillState = {
@@ -245,16 +244,10 @@ var HoverFill = /*#__PURE__*/forwardRef(function (_ref, outerRef) {
245
244
  }, []);
246
245
  useEffect(function () {
247
246
  var root = ref.current;
248
- if (!root || typeof ResizeObserver === 'undefined') {
247
+ if (!root) {
249
248
  return;
250
249
  }
251
- var observer = new ResizeObserver(function () {
252
- syncBgSize();
253
- });
254
- observer.observe(root);
255
- return function () {
256
- observer.disconnect();
257
- };
250
+ return observeResize(root, syncBgSize);
258
251
  }, [ref, syncBgSize]);
259
252
  return /*#__PURE__*/React.createElement("div", _extends({
260
253
  ref: ref,
package/dist/index.d.ts CHANGED
@@ -79,6 +79,6 @@ export { default as Suggestions, type SuggestionsProps } from './suggestions';
79
79
  export { default as UserBubble, type UserBubbleProps } from './user-bubble';
80
80
  export { default as Welcome, type WelcomeProps } from './welcome';
81
81
  export { ComposerSegmentType } from './_genui-types';
82
- export type { AgentEvent, Attachment, ChatMessage, ChipData, ComposerInvocationSegment, ComposerMentionSegment, ComposerSegment, ComposerTextSegment, Conversation, InlineRefState, InvocationData, MentionData, MessageSnapshot, PreviewTab, PreviewTarget, SendMeta, SkillGroup, SkillItem, Source, TextData, ToolCall, ToolStatus, } from './_genui-types';
82
+ export type { AgentEvent, Attachment, ChatMessage, ChipData, ComposerInvocationSegment, ComposerMentionSegment, ComposerSegment, ComposerTextSegment, Conversation, InlineRefState, InvocationData, MentionData, MessageSnapshot, PreviewTab, PreviewTarget, SendMeta, SkillItem, Source, TextData, ToolCall, ToolStatus, } from './_genui-types';
83
83
  export type { InterruptBase, InterruptIntent, InterruptStatus, } from './_interrupt-types';
84
84
  export { isInvocationSegment, isMentionSegment, isTextSegment, rawValueToSegments, segmentsHasContent, segmentsToReadableText, type SegmentsToReadableTextOptions, } from './composer/segments';
@@ -1,24 +1,9 @@
1
1
  /// <reference types="react" />
2
- import type { SkillGroup, SkillItem } from '../_genui-types';
2
+ import type { SkillItem } from '../_genui-types';
3
3
  import './style';
4
4
  export interface SkillSlotProps {
5
- /**
6
- * 技能列表(扁平结构)。
7
- * 当 `skillGroups` 未提供时生效;提供 `skillGroups` 则忽略此项。
8
- */
5
+ /** 技能列表(扁平结构)。 */
9
6
  skills?: SkillItem[];
10
- /**
11
- * 分组技能列表。`menu` / `bar` / `card` 均可使用;优先级高于 `skills`。
12
- * 组标题是否展示由 `showGroupTitles` 控制(默认:menu 展示,bar/card 不展示)。
13
- */
14
- skillGroups?: SkillGroup[];
15
- /**
16
- * 是否展示分组标题。
17
- * - 不传:`menu` 为 true,`bar` / `card` 为 false
18
- * - 显式传入则覆盖默认
19
- * 仅在提供 `skillGroups` 时生效;空 `groupName` 始终不渲染标题。
20
- */
21
- showGroupTitles?: boolean;
22
7
  variant?: 'menu' | 'bar' | 'card';
23
8
  /** 当前选中的 skill id(受控标识;不驱动选中视觉)。 */
24
9
  value?: string | null;
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
3
3
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
- import { Fragment, forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
4
+ import { forwardRef, useEffect, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState } from 'react';
5
5
  import HoverFill from "../hover-fill";
6
6
  import Icon from "../icon";
7
7
  import Input from "../input";
@@ -84,8 +84,6 @@ function SkillDescPopover(_ref) {
84
84
 
85
85
  export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
86
86
  var skillsProp = _ref2.skills,
87
- skillGroups = _ref2.skillGroups,
88
- showGroupTitlesProp = _ref2.showGroupTitles,
89
87
  _ref2$variant = _ref2.variant,
90
88
  variant = _ref2$variant === void 0 ? 'bar' : _ref2$variant,
91
89
  onSelect = _ref2.onSelect,
@@ -113,38 +111,14 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
113
111
 
114
112
  /* 目录全集:过滤前的列表。目录为空才整棵不渲染。 */
115
113
  var catalogSkills = useMemo(function () {
116
- if (skillGroups) return skillGroups.flatMap(function (g) {
117
- return g.skills;
118
- });
119
114
  return skillsProp !== null && skillsProp !== void 0 ? skillsProp : [];
120
- }, [skillGroups, skillsProp]);
121
- var visibleGroups = useMemo(function () {
122
- if (!skillGroups) return undefined;
123
- if (!searchableMenu) return skillGroups;
124
- return skillGroups.map(function (g) {
125
- return {
126
- groupName: g.groupName,
127
- skills: g.skills.filter(function (s) {
128
- return skillMatchesQuery(s, searchQuery);
129
- })
130
- };
131
- }).filter(function (g) {
132
- return g.skills.length > 0;
133
- });
134
- }, [skillGroups, searchableMenu, searchQuery]);
135
-
136
- /* 优先使用过滤后的 skillGroups,否则回退到 skills。 */
115
+ }, [skillsProp]);
137
116
  var skills = useMemo(function () {
138
- if (visibleGroups) return visibleGroups.flatMap(function (g) {
139
- return g.skills;
140
- });
141
117
  if (!searchableMenu) return catalogSkills;
142
118
  return catalogSkills.filter(function (s) {
143
119
  return skillMatchesQuery(s, searchQuery);
144
120
  });
145
- }, [visibleGroups, catalogSkills, searchableMenu, searchQuery]);
146
- var showGroupTitles = showGroupTitlesProp !== null && showGroupTitlesProp !== void 0 ? showGroupTitlesProp : variant === 'menu';
147
- var groupedWithTitles = !!(skillGroups && showGroupTitles);
121
+ }, [catalogSkills, searchableMenu, searchQuery]);
148
122
  /* menu 变体:HoverFill 只管鼠标。键盘高亮视觉暂时关闭(见 style),
149
123
  * 避免 mouseleave 后 ::before 接力造成闪一下。`activeIndex` / ↑↓ / Enter
150
124
  * 数据层仍工作,恢复视觉时解开 item-highlighted ::before 即可。
@@ -421,53 +395,11 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
421
395
  }
422
396
  return barButton;
423
397
  };
424
-
425
- /* 分组渲染:是否画标题由 showGroupTitles 决定。
426
- * menu 项必须与标题/分割线同级挂在 list 根下——HoverFill 跨项共享背景要求同一
427
- * parentNode;若再包一层 group / group-items,跨组必闪。bar/card 不用 HoverFill,
428
- * 仍用 group 壳承接 flex/grid。 */
429
- var renderGroups = function renderGroups() {
430
- var flatIndex = 0;
431
- if (variant === 'menu') {
432
- return /*#__PURE__*/React.createElement(React.Fragment, null, visibleGroups.map(function (group, groupIdx) {
433
- return /*#__PURE__*/React.createElement(Fragment, {
434
- key: group.groupName || "_group_".concat(groupIdx)
435
- }, showGroupTitles && group.groupName ? /*#__PURE__*/React.createElement("div", {
436
- "data-odn-skill-slot-group-header": true
437
- }, group.groupName) : null, group.skills.map(function (skill) {
438
- return renderMenuItem(skill, flatIndex++);
439
- }), groupIdx < visibleGroups.length - 1 ? /*#__PURE__*/React.createElement("div", {
440
- "data-odn-skill-slot-divider": true,
441
- "data-odn-skill-slot-group-divider": true
442
- }) : null);
443
- }));
444
- }
445
- return /*#__PURE__*/React.createElement(React.Fragment, null, visibleGroups.map(function (group, groupIdx) {
446
- return /*#__PURE__*/React.createElement("div", {
447
- key: group.groupName || "_group_".concat(groupIdx),
448
- "data-odn-skill-slot-group": true
449
- }, showGroupTitles && group.groupName ? /*#__PURE__*/React.createElement("div", {
450
- "data-odn-skill-slot-group-header": true
451
- }, group.groupName) : null, /*#__PURE__*/React.createElement("div", {
452
- "data-odn-skill-slot-group-items": true
453
- }, group.skills.map(function (skill) {
454
- return variant === 'card' ? renderCardItem(skill) : renderBarItem(skill);
455
- })));
456
- }));
457
- };
458
-
459
- /* 扁平模式下渲染所有项(menu / bar / card)。 */
460
- var renderFlatItems = function renderFlatItems() {
461
- return skills.map(function (skill, index) {
462
- if (variant === 'card') return renderCardItem(skill);
463
- if (variant === 'menu') return renderMenuItem(skill, index);
464
- return renderBarItem(skill);
465
- });
466
- };
467
-
468
- /* 有 skillGroups:始终按组遍历(保序);无标题时仍走分组 DOM,仅不渲染 header,
469
- * bar/card 用 group-items 承接原有 flex/grid,避免拍平后丢组边界。 */
470
- var listBody = visibleGroups ? renderGroups() : renderFlatItems();
398
+ var listBody = skills.map(function (skill, index) {
399
+ if (variant === 'card') return renderCardItem(skill);
400
+ if (variant === 'menu') return renderMenuItem(skill, index);
401
+ return renderBarItem(skill);
402
+ });
471
403
  var manageBtn = renderManageBtn();
472
404
  var searchBar = searchableMenu ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
473
405
  "data-odn-skill-slot-toolbar": true
@@ -533,7 +465,6 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
533
465
  return /*#__PURE__*/React.createElement("div", {
534
466
  "data-odn-skill-slot": true,
535
467
  "data-odn-skill-slot-variant": variant,
536
- "data-odn-skill-slot-grouped": groupedWithTitles || undefined,
537
468
  className: className,
538
469
  style: rootStyle
539
470
  }, listBody);
@@ -547,7 +478,6 @@ export var SkillSlot = /*#__PURE__*/forwardRef(function SkillSlot(_ref2, ref) {
547
478
  return /*#__PURE__*/React.createElement("div", {
548
479
  "data-odn-skill-slot": true,
549
480
  "data-odn-skill-slot-variant": variant,
550
- "data-odn-skill-slot-grouped": groupedWithTitles || undefined,
551
481
  className: className,
552
482
  style: rootStyle
553
483
  }, searchBar, hasScrollWrap ? /*#__PURE__*/React.createElement("div", {
@@ -151,7 +151,7 @@
151
151
  align-items: flex-start;
152
152
  gap: 8px;
153
153
  width: 100%;
154
- padding: 8px 12px;
154
+ padding: 4px 12px;
155
155
  font-size: 13px;
156
156
  color: var(--odn-color-black-12);
157
157
  text-align: left;
@@ -196,77 +196,14 @@
196
196
  word-break: break-word;
197
197
  }
198
198
 
199
- /* ---- menu 分组标题 ----
200
- * 分类名不做 uppercase。组间分割线画在组末、左右内缩,不跟标题叠尾线。 */
201
- [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-group-header] {
202
- padding: 0 16px 4px;
203
- font-size: 12px;
204
- font-weight: 500;
205
- color: var(--odn-color-black-8);
206
- line-height: 20px;
207
- user-select: none;
208
- pointer-events: none;
209
- }
210
-
211
- [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-list] > [data-odn-skill-slot-group-header]:first-child {
212
- padding-top: 4px;
213
- }
214
-
215
- /* 无组标题时:group 壳不参与布局,子项仍挂在根 flex/grid 上(与拍平一致) */
216
- [data-odn-skill-slot]:not([data-odn-skill-slot-grouped]) [data-odn-skill-slot-group],
217
- [data-odn-skill-slot]:not([data-odn-skill-slot-grouped]) [data-odn-skill-slot-group-items] {
218
- display: contents;
219
- }
220
-
221
- /* 有组标题:根改为纵向堆叠组;组内再承接原 bar flex / card grid */
222
- [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=bar],
223
- [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=card] {
224
- display: flex;
225
- flex-direction: column;
226
- flex-wrap: nowrap;
227
- gap: 12px;
228
- grid-template-columns: none;
229
- }
230
-
231
- [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=bar] [data-odn-skill-slot-group-items] {
232
- display: flex;
233
- flex-wrap: wrap;
234
- gap: 8px;
235
- }
236
-
237
- [data-odn-skill-slot][data-odn-skill-slot-grouped][data-odn-skill-slot-variant=card] [data-odn-skill-slot-group-items] {
238
- display: grid;
239
- grid-template-columns: repeat(2, 1fr);
240
- gap: 10px;
241
- }
242
-
243
- [data-odn-skill-slot][data-odn-skill-slot-variant=bar] [data-odn-skill-slot-group-header],
244
- [data-odn-skill-slot][data-odn-skill-slot-variant=card] [data-odn-skill-slot-group-header] {
245
- padding: 0 2px;
246
- font-size: 12px;
247
- font-weight: 600;
248
- color: var(--odn-color-black-8);
249
- line-height: 20px;
250
- user-select: none;
251
- pointer-events: none;
252
- }
253
-
254
199
  /* ---- menu 分隔线 ----
255
- * 通栏:搜索栏 / 技能管理,标「内容 ↔ 系统操作」。
256
- * 组间:仅无标题时出现,左右内缩对齐文案(macOS 菜单)。 */
200
+ * 通栏:搜索栏 / 技能管理,标「内容 ↔ 系统操作」。 */
257
201
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-divider] {
258
202
  margin: 4px 0;
259
203
  height: 1px;
260
204
  background: var(--odn-color-black-5);
261
205
  }
262
206
 
263
- [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-group-divider] {
264
- box-sizing: content-box;
265
- margin: 0 16px;
266
- padding: 8px 0;
267
- background-clip: content-box;
268
- }
269
-
270
207
  /* ---- menu 管理按钮:hug 内容宽;在顶栏靠右,无搜索时仍在列表底 ---- */
271
208
  [data-odn-skill-slot][data-odn-skill-slot-variant=menu] [data-odn-skill-slot-manage-btn] {
272
209
  display: inline-flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "one-design-next",
3
- "version": "0.0.90",
3
+ "version": "0.0.92",
4
4
  "description": "One Design Next from TAD@tencent.com",
5
5
  "license": "MIT",
6
6
  "type": "module",