one-design-next 0.0.85 → 0.0.87
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.
- package/dist/chat-list/index.d.ts +15 -4
- package/dist/chat-list/index.js +55 -40
- package/dist/chat-list/style/index.css +31 -2
- package/dist/composer/editor.d.ts +4 -1
- package/dist/composer/editor.js +28 -9
- package/dist/composer/index.js +135 -119
- package/dist/composer/style/index.css +15 -8
- package/dist/composer/utils.d.ts +13 -1
- package/dist/composer/utils.js +33 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/skill-slot/index.d.ts +4 -3
- package/dist/skill-slot/index.js +56 -28
- package/dist/skill-slot/style/index.css +83 -43
- package/package.json +1 -1
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
import { type ChatItemProps } from '../chat-item';
|
|
3
3
|
import './style';
|
|
4
|
-
/**
|
|
4
|
+
/** 按会话时间筛选(面板不含时间组;`filterTime` 仅受控 API)。 */
|
|
5
5
|
export type ChatListFilterTime = 'all' | 'today' | '7d' | '30d';
|
|
6
|
-
/** 按会话类型筛选:全部 / AI / 人工客服。 */
|
|
6
|
+
/** 按会话类型筛选:全部 / AI 任务 / 人工客服。 */
|
|
7
7
|
export type ChatListFilterType = 'all' | 'ai' | 'human';
|
|
8
|
+
/** 按会话状态筛选:全部 / 生成中 / 待回复 / 未读 / 任务报错。 */
|
|
9
|
+
export type ChatListFilterStatus = 'all' | 'generating' | 'waiting' | 'unread' | 'error';
|
|
8
10
|
export type ChatListItem = Pick<ChatItemProps, 'id' | 'title' | 'active' | 'type' | 'status' | 'pinned' | 'time'>;
|
|
9
11
|
export interface ChatListProps {
|
|
10
12
|
items: ChatListItem[];
|
|
@@ -20,7 +22,7 @@ export interface ChatListProps {
|
|
|
20
22
|
*/
|
|
21
23
|
recentSectionTitle?: ReactNode | null;
|
|
22
24
|
/**
|
|
23
|
-
*
|
|
25
|
+
* 受控:时间筛选。筛选面板不含时间组,仅 API 可用。
|
|
24
26
|
*/
|
|
25
27
|
filterTime?: ChatListFilterTime;
|
|
26
28
|
/** 非受控:初始时间筛选。默认 `'all'`。 */
|
|
@@ -33,6 +35,13 @@ export interface ChatListProps {
|
|
|
33
35
|
/** 非受控:初始类型筛选。默认 `'all'`。 */
|
|
34
36
|
defaultFilterType?: ChatListFilterType;
|
|
35
37
|
onFilterTypeChange?: (value: ChatListFilterType) => void;
|
|
38
|
+
/**
|
|
39
|
+
* 受控:状态筛选。`'all'` | `'generating'` | `'waiting'` | `'unread'` | `'error'`。
|
|
40
|
+
*/
|
|
41
|
+
filterStatus?: ChatListFilterStatus;
|
|
42
|
+
/** 非受控:初始状态筛选。默认 `'all'`。 */
|
|
43
|
+
defaultFilterStatus?: ChatListFilterStatus;
|
|
44
|
+
onFilterStatusChange?: (value: ChatListFilterStatus) => void;
|
|
36
45
|
/** 受控:筛选选择器是否展开 */
|
|
37
46
|
filterOpen?: boolean;
|
|
38
47
|
defaultFilterOpen?: boolean;
|
|
@@ -59,7 +68,9 @@ export interface ChatListProps {
|
|
|
59
68
|
export declare function matchChatListFilterTime(time: ChatListItem['time'], filter: ChatListFilterTime, now?: number): boolean;
|
|
60
69
|
/** 按类型筛选项判断会话是否命中。缺省 `type` 视为 `'ai'`。 */
|
|
61
70
|
export declare function matchChatListFilterType(type: ChatListItem['type'], filter: ChatListFilterType): boolean;
|
|
62
|
-
|
|
71
|
+
/** 按状态筛选项判断会话是否命中。无 `status` 时仅在「全部」下保留。 */
|
|
72
|
+
export declare function matchChatListFilterStatus(status: ChatListItem['status'], filter: ChatListFilterStatus): boolean;
|
|
73
|
+
export declare function ChatList({ items, title, pinnedSectionTitle, recentSectionTitle, filterTime: filterTimeProp, defaultFilterTime, filterType: filterTypeProp, defaultFilterType, onFilterTypeChange, filterStatus: filterStatusProp, defaultFilterStatus, onFilterStatusChange, filterOpen: filterOpenProp, defaultFilterOpen, onFilterOpenChange, empty, actionMenuZIndex, filterMenuZIndex, className, onItemClick, onRename, onPin, onDelete, renderItem, renderRestScroll, }: ChatListProps): import("react").JSX.Element;
|
|
63
74
|
export declare namespace ChatList {
|
|
64
75
|
var displayName: string;
|
|
65
76
|
}
|
package/dist/chat-list/index.js
CHANGED
|
@@ -6,32 +6,37 @@ import Dropdown from "../dropdown";
|
|
|
6
6
|
import Icon from "../icon";
|
|
7
7
|
import "./style";
|
|
8
8
|
|
|
9
|
-
/**
|
|
9
|
+
/** 按会话时间筛选(面板不含时间组;`filterTime` 仅受控 API)。 */
|
|
10
10
|
|
|
11
|
-
/** 按会话类型筛选:全部 / AI / 人工客服。 */
|
|
11
|
+
/** 按会话类型筛选:全部 / AI 任务 / 人工客服。 */
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/** 按会话状态筛选:全部 / 生成中 / 待回复 / 未读 / 任务报错。 */
|
|
14
|
+
|
|
15
|
+
var TYPE_OPTIONS = [{
|
|
14
16
|
value: 'all',
|
|
15
17
|
label: '全部'
|
|
16
18
|
}, {
|
|
17
|
-
value: '
|
|
18
|
-
label: '
|
|
19
|
-
}, {
|
|
20
|
-
value: '7d',
|
|
21
|
-
label: '近 7 天'
|
|
19
|
+
value: 'ai',
|
|
20
|
+
label: 'AI 任务'
|
|
22
21
|
}, {
|
|
23
|
-
value: '
|
|
24
|
-
label: '
|
|
22
|
+
value: 'human',
|
|
23
|
+
label: '人工客服'
|
|
25
24
|
}];
|
|
26
|
-
var
|
|
25
|
+
var STATUS_OPTIONS = [{
|
|
27
26
|
value: 'all',
|
|
28
27
|
label: '全部'
|
|
29
28
|
}, {
|
|
30
|
-
value: '
|
|
31
|
-
label: '
|
|
29
|
+
value: 'generating',
|
|
30
|
+
label: '生成中'
|
|
32
31
|
}, {
|
|
33
|
-
value: '
|
|
34
|
-
label: '
|
|
32
|
+
value: 'waiting',
|
|
33
|
+
label: '待回复'
|
|
34
|
+
}, {
|
|
35
|
+
value: 'unread',
|
|
36
|
+
label: '未读'
|
|
37
|
+
}, {
|
|
38
|
+
value: 'error',
|
|
39
|
+
label: '任务报错'
|
|
35
40
|
}];
|
|
36
41
|
function parseItemTime(time) {
|
|
37
42
|
if (time === null || time === undefined) return null;
|
|
@@ -62,6 +67,12 @@ export function matchChatListFilterType(type, filter) {
|
|
|
62
67
|
if (filter === 'all') return true;
|
|
63
68
|
return (type !== null && type !== void 0 ? type : 'ai') === filter;
|
|
64
69
|
}
|
|
70
|
+
|
|
71
|
+
/** 按状态筛选项判断会话是否命中。无 `status` 时仅在「全部」下保留。 */
|
|
72
|
+
export function matchChatListFilterStatus(status, filter) {
|
|
73
|
+
if (filter === 'all') return true;
|
|
74
|
+
return status === filter;
|
|
75
|
+
}
|
|
65
76
|
function useControllable(controlled, defaultValue, onChange) {
|
|
66
77
|
var _useState = useState(defaultValue),
|
|
67
78
|
_useState2 = _slicedToArray(_useState, 2),
|
|
@@ -84,33 +95,33 @@ function filterOptionLabel(label, selected) {
|
|
|
84
95
|
"data-odn-chat-list-filter-option-label": true
|
|
85
96
|
}, label), selected ? /*#__PURE__*/React.createElement(Icon, {
|
|
86
97
|
name: "check",
|
|
87
|
-
size:
|
|
98
|
+
size: 12,
|
|
88
99
|
"data-odn-chat-list-filter-option-check": true
|
|
89
100
|
}) : null);
|
|
90
101
|
}
|
|
91
|
-
function buildFilterMenu(
|
|
102
|
+
function buildFilterMenu(filterType, filterStatus) {
|
|
92
103
|
return [{
|
|
93
104
|
type: 'label',
|
|
94
|
-
label: '
|
|
105
|
+
label: '类型'
|
|
95
106
|
}, {
|
|
96
107
|
type: 'group',
|
|
97
|
-
children:
|
|
108
|
+
children: TYPE_OPTIONS.map(function (opt) {
|
|
98
109
|
return {
|
|
99
|
-
value: "
|
|
100
|
-
label: filterOptionLabel(opt.label,
|
|
110
|
+
value: "type:".concat(opt.value),
|
|
111
|
+
label: filterOptionLabel(opt.label, filterType === opt.value)
|
|
101
112
|
};
|
|
102
113
|
})
|
|
103
114
|
}, {
|
|
104
115
|
type: 'separator'
|
|
105
116
|
}, {
|
|
106
117
|
type: 'label',
|
|
107
|
-
label: '
|
|
118
|
+
label: '状态'
|
|
108
119
|
}, {
|
|
109
120
|
type: 'group',
|
|
110
|
-
children:
|
|
121
|
+
children: STATUS_OPTIONS.map(function (opt) {
|
|
111
122
|
return {
|
|
112
|
-
value: "
|
|
113
|
-
label: filterOptionLabel(opt.label,
|
|
123
|
+
value: "status:".concat(opt.value),
|
|
124
|
+
label: filterOptionLabel(opt.label, filterStatus === opt.value)
|
|
114
125
|
};
|
|
115
126
|
})
|
|
116
127
|
}];
|
|
@@ -126,11 +137,14 @@ export function ChatList(_ref) {
|
|
|
126
137
|
filterTimeProp = _ref.filterTime,
|
|
127
138
|
_ref$defaultFilterTim = _ref.defaultFilterTime,
|
|
128
139
|
defaultFilterTime = _ref$defaultFilterTim === void 0 ? 'all' : _ref$defaultFilterTim,
|
|
129
|
-
onFilterTimeChange = _ref.onFilterTimeChange,
|
|
130
140
|
filterTypeProp = _ref.filterType,
|
|
131
141
|
_ref$defaultFilterTyp = _ref.defaultFilterType,
|
|
132
142
|
defaultFilterType = _ref$defaultFilterTyp === void 0 ? 'all' : _ref$defaultFilterTyp,
|
|
133
143
|
onFilterTypeChange = _ref.onFilterTypeChange,
|
|
144
|
+
filterStatusProp = _ref.filterStatus,
|
|
145
|
+
_ref$defaultFilterSta = _ref.defaultFilterStatus,
|
|
146
|
+
defaultFilterStatus = _ref$defaultFilterSta === void 0 ? 'all' : _ref$defaultFilterSta,
|
|
147
|
+
onFilterStatusChange = _ref.onFilterStatusChange,
|
|
134
148
|
filterOpenProp = _ref.filterOpen,
|
|
135
149
|
_ref$defaultFilterOpe = _ref.defaultFilterOpen,
|
|
136
150
|
defaultFilterOpen = _ref$defaultFilterOpe === void 0 ? false : _ref$defaultFilterOpe,
|
|
@@ -146,23 +160,24 @@ export function ChatList(_ref) {
|
|
|
146
160
|
_ref$renderItem = _ref.renderItem,
|
|
147
161
|
renderItem = _ref$renderItem === void 0 ? defaultRenderItem : _ref$renderItem,
|
|
148
162
|
renderRestScroll = _ref.renderRestScroll;
|
|
149
|
-
var
|
|
163
|
+
var filterTime = filterTimeProp !== null && filterTimeProp !== void 0 ? filterTimeProp : defaultFilterTime;
|
|
164
|
+
var _useControllable = useControllable(filterTypeProp, defaultFilterType, onFilterTypeChange),
|
|
150
165
|
_useControllable2 = _slicedToArray(_useControllable, 2),
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
var _useControllable3 = useControllable(
|
|
166
|
+
filterType = _useControllable2[0],
|
|
167
|
+
setFilterType = _useControllable2[1];
|
|
168
|
+
var _useControllable3 = useControllable(filterStatusProp, defaultFilterStatus, onFilterStatusChange),
|
|
154
169
|
_useControllable4 = _slicedToArray(_useControllable3, 2),
|
|
155
|
-
|
|
156
|
-
|
|
170
|
+
filterStatus = _useControllable4[0],
|
|
171
|
+
setFilterStatus = _useControllable4[1];
|
|
157
172
|
var _useControllable5 = useControllable(filterOpenProp, defaultFilterOpen, onFilterOpenChange),
|
|
158
173
|
_useControllable6 = _slicedToArray(_useControllable5, 2),
|
|
159
174
|
filterOpen = _useControllable6[0],
|
|
160
175
|
setFilterOpen = _useControllable6[1];
|
|
161
176
|
var filteredItems = useMemo(function () {
|
|
162
177
|
return items.filter(function (item) {
|
|
163
|
-
return matchChatListFilterTime(item.time, filterTime) && matchChatListFilterType(item.type, filterType);
|
|
178
|
+
return matchChatListFilterTime(item.time, filterTime) && matchChatListFilterType(item.type, filterType) && matchChatListFilterStatus(item.status, filterStatus);
|
|
164
179
|
});
|
|
165
|
-
}, [items, filterTime, filterType]);
|
|
180
|
+
}, [items, filterTime, filterType, filterStatus]);
|
|
166
181
|
var pinnedItems = useMemo(function () {
|
|
167
182
|
return filteredItems.filter(function (item) {
|
|
168
183
|
return item.pinned;
|
|
@@ -174,8 +189,8 @@ export function ChatList(_ref) {
|
|
|
174
189
|
});
|
|
175
190
|
}, [filteredItems]);
|
|
176
191
|
var filterMenu = useMemo(function () {
|
|
177
|
-
return buildFilterMenu(
|
|
178
|
-
}, [
|
|
192
|
+
return buildFilterMenu(filterType, filterStatus);
|
|
193
|
+
}, [filterType, filterStatus]);
|
|
179
194
|
var renderChatItem = function renderChatItem(item) {
|
|
180
195
|
var node = /*#__PURE__*/React.createElement(ChatItem, {
|
|
181
196
|
key: item.id,
|
|
@@ -229,13 +244,13 @@ export function ChatList(_ref) {
|
|
|
229
244
|
onVisibleChange: setFilterOpen,
|
|
230
245
|
menu: filterMenu,
|
|
231
246
|
onSelect: function onSelect(value) {
|
|
232
|
-
if (value.startsWith('
|
|
233
|
-
|
|
247
|
+
if (value.startsWith('type:')) {
|
|
248
|
+
setFilterType(value.slice(5));
|
|
234
249
|
setFilterOpen(false);
|
|
235
250
|
return;
|
|
236
251
|
}
|
|
237
|
-
if (value.startsWith('
|
|
238
|
-
|
|
252
|
+
if (value.startsWith('status:')) {
|
|
253
|
+
setFilterStatus(value.slice(7));
|
|
239
254
|
setFilterOpen(false);
|
|
240
255
|
}
|
|
241
256
|
}
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
gap: 8px;
|
|
16
16
|
min-height: 32px;
|
|
17
17
|
min-width: 0;
|
|
18
|
-
/*
|
|
19
|
-
padding: 0 12px;
|
|
18
|
+
/* 左缘与 ChatItem / 分区标题 12px 对齐;右侧贴齐,筛选项不再多 12px */
|
|
19
|
+
padding: 0 4px 0 12px;
|
|
20
20
|
background: transparent;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -90,9 +90,38 @@
|
|
|
90
90
|
color: var(--odn-color-black-8);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu {
|
|
94
|
+
/* 比默认 Dropdown 小一号:对齐 popup 字号 + Select small 行高 */
|
|
95
|
+
--odn-font-size: var(--odn-popup-font-size);
|
|
96
|
+
--odn-line-height: var(--odn-popup-line-height);
|
|
97
|
+
--odn-popup-control-height: 28px;
|
|
98
|
+
}
|
|
99
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu [data-odn-dropdown-label] {
|
|
100
|
+
height: auto;
|
|
101
|
+
padding: 0 12px 2px;
|
|
102
|
+
}
|
|
103
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu {
|
|
104
|
+
/* hover 不通栏:左右各缩 4px,圆角 4px;padding 8px 使文案仍落在 12px */
|
|
105
|
+
}
|
|
106
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu [data-odn-dropdown-item] {
|
|
107
|
+
margin: 0 4px;
|
|
108
|
+
padding-inline: 8px;
|
|
109
|
+
border-radius: 4px;
|
|
110
|
+
}
|
|
93
111
|
[data-odn-dropdown-content].odn-chat-list-filter-menu [data-odn-dropdown-item-label] {
|
|
94
112
|
overflow: visible;
|
|
95
113
|
}
|
|
114
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu {
|
|
115
|
+
/* 组间线:上下各 8px padding,线画在 content-box,左右内缩 */
|
|
116
|
+
}
|
|
117
|
+
[data-odn-dropdown-content].odn-chat-list-filter-menu [data-odn-dropdown-separator] {
|
|
118
|
+
box-sizing: content-box;
|
|
119
|
+
height: 1px;
|
|
120
|
+
margin: 0 12px;
|
|
121
|
+
padding: 8px 0;
|
|
122
|
+
background-color: var(--odn-color-black-5);
|
|
123
|
+
background-clip: content-box;
|
|
124
|
+
}
|
|
96
125
|
|
|
97
126
|
[data-odn-chat-list-body] {
|
|
98
127
|
display: flex;
|
|
@@ -30,6 +30,8 @@ export interface ComposerEditorTriggerInfo {
|
|
|
30
30
|
*/
|
|
31
31
|
rect: DOMRect;
|
|
32
32
|
}
|
|
33
|
+
/** 编辑器 10 行真实高度,缩放按钮在内容达到此高度后隐藏。 */
|
|
34
|
+
export declare const COMPOSER_EDITOR_MAX_ROWS_PX: number;
|
|
33
35
|
export interface ComposerEditorAutoSize {
|
|
34
36
|
minRows?: number;
|
|
35
37
|
maxRows?: number;
|
|
@@ -79,7 +81,8 @@ export interface ComposerEditorProps {
|
|
|
79
81
|
onTriggerKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => boolean | void;
|
|
80
82
|
/**
|
|
81
83
|
* 编辑器可视高度变化回调。
|
|
82
|
-
* height =
|
|
84
|
+
* height = 内容自然高度(scrollHeight,未 clamp);atMax 表示已超过 10 行
|
|
85
|
+
* 真实高度。若整框被 50vh 挤矮,则以盒内分给编辑器的剩余高度为准。
|
|
83
86
|
* Composer 的 lite 升格逻辑、scrollbar 显隐都用这个。
|
|
84
87
|
*/
|
|
85
88
|
onHeightChange?: (height: number, atMax: boolean) => void;
|
package/dist/composer/editor.js
CHANGED
|
@@ -77,7 +77,14 @@ var scrollCaretIntoView = function scrollCaretIntoView(viewport) {
|
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
79
|
var LINE_HEIGHT = 24;
|
|
80
|
-
|
|
80
|
+
/** 与 SCSS `padding: 2px … 0` 对齐。10 行 = 10 * 24 + 2 = 242px。 */
|
|
81
|
+
var EDITOR_PADDING_BLOCK = 2;
|
|
82
|
+
var contentHeightForRows = function contentHeightForRows(rows) {
|
|
83
|
+
return rows * LINE_HEIGHT + EDITOR_PADDING_BLOCK;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
/** 编辑器 10 行真实高度,缩放按钮在内容达到此高度后隐藏。 */
|
|
87
|
+
export var COMPOSER_EDITOR_MAX_ROWS_PX = contentHeightForRows(10);
|
|
81
88
|
export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref, ref) {
|
|
82
89
|
var _autoSize$minRows;
|
|
83
90
|
var valueProp = _ref.value,
|
|
@@ -110,11 +117,15 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
110
117
|
return (_scrollRef$current$vi = (_scrollRef$current = scrollRef.current) === null || _scrollRef$current === void 0 ? void 0 : _scrollRef$current.viewport) !== null && _scrollRef$current$vi !== void 0 ? _scrollRef$current$vi : null;
|
|
111
118
|
}, []);
|
|
112
119
|
var isComposingRef = useRef(false);
|
|
120
|
+
var onTriggerChangeRef = useRef(onTriggerChange);
|
|
121
|
+
onTriggerChangeRef.current = onTriggerChange;
|
|
113
122
|
var isControlled = valueProp !== undefined;
|
|
114
123
|
var minRows = (_autoSize$minRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.minRows) !== null && _autoSize$minRows !== void 0 ? _autoSize$minRows : 1;
|
|
115
124
|
var maxRows = autoSize === null || autoSize === void 0 ? void 0 : autoSize.maxRows;
|
|
116
|
-
var minHeightPx = minRows
|
|
117
|
-
var
|
|
125
|
+
var minHeightPx = contentHeightForRows(minRows);
|
|
126
|
+
var rowContentPx = maxRows !== undefined ? contentHeightForRows(maxRows) : undefined;
|
|
127
|
+
/** 仅 10 行封顶(242px);50vh 由外层 box 负责。 */
|
|
128
|
+
var maxHeightPx = rowContentPx;
|
|
118
129
|
|
|
119
130
|
/** 当前活动 trigger probe;null 表示无触发态。 */
|
|
120
131
|
var triggerRef = useRef(null);
|
|
@@ -179,17 +190,22 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
179
190
|
* 主动调 syncHeight(确保升格判定能拿到 scrollHeight)。
|
|
180
191
|
* ───────────────────────────────────── */
|
|
181
192
|
var syncHeight = useCallback(function () {
|
|
182
|
-
var _onHeightChangeRef$cu;
|
|
193
|
+
var _getViewport, _box$getBoundingClien, _onHeightChangeRef$cu;
|
|
183
194
|
var el = editorRef.current;
|
|
184
195
|
if (!el) return;
|
|
185
196
|
var natural = Math.ceil(el.scrollHeight);
|
|
186
197
|
var clamped = Math.max(minHeightPx, maxHeightPx !== undefined ? Math.min(natural, maxHeightPx) : natural);
|
|
187
|
-
var
|
|
198
|
+
var allocated = (_getViewport = getViewport()) === null || _getViewport === void 0 ? void 0 : _getViewport.clientHeight;
|
|
199
|
+
var box = el.closest('[data-odn-composer-box]');
|
|
200
|
+
var boxH = (_box$getBoundingClien = box === null || box === void 0 ? void 0 : box.getBoundingClientRect().height) !== null && _box$getBoundingClien !== void 0 ? _box$getBoundingClien : 0;
|
|
201
|
+
var vhCap = typeof window === 'undefined' ? Number.POSITIVE_INFINITY : window.innerHeight * 0.5;
|
|
202
|
+
var boxAtVhCap = boxH > 0 && boxH >= vhCap - 2;
|
|
203
|
+
var overflow = boxAtVhCap ? allocated !== undefined && allocated > 0 && natural > allocated + 1 : rowContentPx !== undefined && natural > rowContentPx + 1;
|
|
188
204
|
setScrollHeight(function (prev) {
|
|
189
205
|
return prev === clamped ? prev : clamped;
|
|
190
206
|
});
|
|
191
207
|
(_onHeightChangeRef$cu = onHeightChangeRef.current) === null || _onHeightChangeRef$cu === void 0 || _onHeightChangeRef$cu.call(onHeightChangeRef, natural, overflow);
|
|
192
|
-
}, [minHeightPx, maxHeightPx]);
|
|
208
|
+
}, [getViewport, minHeightPx, maxHeightPx, rowContentPx]);
|
|
193
209
|
var shouldShowPlaceholder = useCallback(function (el) {
|
|
194
210
|
if (!isEditorEmpty(el)) return false;
|
|
195
211
|
// placeholder 仅在「单行且空内容」展示。
|
|
@@ -472,10 +488,12 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
472
488
|
syncHeight();
|
|
473
489
|
var ro = new ResizeObserver(syncHeight);
|
|
474
490
|
ro.observe(el);
|
|
491
|
+
var vp = getViewport();
|
|
492
|
+
if (vp) ro.observe(vp);
|
|
475
493
|
return function () {
|
|
476
494
|
return ro.disconnect();
|
|
477
495
|
};
|
|
478
|
-
}, [syncHeight]);
|
|
496
|
+
}, [getViewport, syncHeight]);
|
|
479
497
|
|
|
480
498
|
/* ─────────────────────────────────────
|
|
481
499
|
* 受控同步:仅在外部 value 变化,或输入后延迟校验 tick 变化时校验 DOM。
|
|
@@ -518,12 +536,13 @@ export var ComposerEditor = /*#__PURE__*/forwardRef(function ComposerEditor(_ref
|
|
|
518
536
|
resetChips();
|
|
519
537
|
setEmpty(shouldShowPlaceholder(el));
|
|
520
538
|
if (triggerRef.current) {
|
|
539
|
+
var _onTriggerChangeRef$c;
|
|
521
540
|
triggerRef.current = null;
|
|
522
|
-
|
|
541
|
+
(_onTriggerChangeRef$c = onTriggerChangeRef.current) === null || _onTriggerChangeRef$c === void 0 || _onTriggerChangeRef$c.call(onTriggerChangeRef, null);
|
|
523
542
|
}
|
|
524
543
|
syncHeight();
|
|
525
544
|
}
|
|
526
|
-
}, [controlledSyncTick, valueProp, isControlled, resetChips,
|
|
545
|
+
}, [controlledSyncTick, valueProp, isControlled, resetChips, shouldShowPlaceholder, syncHeight]);
|
|
527
546
|
|
|
528
547
|
/* ─────────────────────────────────────
|
|
529
548
|
* 输入事件
|