one-design-next 0.0.96 → 0.0.98

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.
@@ -133,7 +133,7 @@ export interface ChipData {
133
133
  * 'invocation' = `/` 或 Skill 按钮;'mention' = `@`(预留)。
134
134
  * 其他值归 invocation。
135
135
  */
136
- kind?: 'invocation' | 'mention' | (string & {});
136
+ kind?: 'invocation' | 'mention' | (string & NonNullable<unknown>);
137
137
  state?: InlineRefState;
138
138
  payload?: Record<string, unknown>;
139
139
  }
@@ -222,6 +222,8 @@ export interface Conversation {
222
222
  status?: 'generating' | 'waiting' | 'unread' | 'error';
223
223
  /** 是否置顶。排序由列表容器负责。 */
224
224
  pinned?: boolean;
225
+ /** 所属分组 id。分组编排由 ChatList 负责。 */
226
+ groupId?: string;
225
227
  }
226
228
  export interface MessageSnapshot {
227
229
  content: string;
@@ -45,5 +45,7 @@ export var ComposerSegmentType = {
45
45
  Invocation: 'invocation',
46
46
  Mention: 'mention'
47
47
  };
48
+ // 同名 type 供 `seg.type === ComposerSegmentType.Invocation` 收窄,与 const 对象并存。
49
+ // eslint-disable-next-line @typescript-eslint/no-redeclare -- 有意的 const + type 同名
48
50
 
49
51
  /** `onSend(segments, meta?)` 第二参数:非正文的附加数据。 */
@@ -0,0 +1,48 @@
1
+ import { type HTMLAttributes, type ReactNode } from 'react';
2
+ import './style';
3
+ /** 组内预览条数。仅收起后再打开时生效;默认展开态展示全部。 */
4
+ export declare const CHAT_GROUP_PREVIEW_LIMIT = 5;
5
+ export interface ChatGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
6
+ /** 分组标题 */
7
+ title: ReactNode;
8
+ /** 是否可折叠。默认 `true`。 */
9
+ collapsible?: boolean;
10
+ /** 受控:是否折叠 */
11
+ collapsed?: boolean;
12
+ /** 非受控:初始是否折叠 */
13
+ defaultCollapsed?: boolean;
14
+ onCollapsedChange?: (collapsed: boolean) => void;
15
+ /** 受控:是否处于重命名 */
16
+ renaming?: boolean;
17
+ defaultRenaming?: boolean;
18
+ onRenamingChange?: (renaming: boolean) => void;
19
+ /**
20
+ * 重命名提交。配合 `renaming` / 菜单进入编辑(`title` 需为 string)。
21
+ */
22
+ onRename?: (title: string) => void;
23
+ /**
24
+ * 左侧文件夹 icon(用户分组缩进标识)。默认 `false`。
25
+ */
26
+ folderIcon?: boolean;
27
+ /**
28
+ * 分区头样式(如「未分组」)。与 ChatList「分组」同为 12px / black-9,
29
+ * 不是用户文件夹组。
30
+ */
31
+ section?: boolean;
32
+ /** 标题右侧扩展区(组级 … / + 等);默认仅 hover / 菜单打开时显示 */
33
+ extra?: ReactNode;
34
+ /** 强制显示 extra(如菜单打开时) */
35
+ extraVisible?: boolean;
36
+ /**
37
+ * 组内预览条数。默认 5;`false` 关闭截断(未分组 / 搜索命中)。
38
+ * 仅在收起后再展开时截成前 N 条 +「展开其余 N 条」;默认展开态展示全部,
39
+ * 其间新增超过 N 条也不出现展开按钮。
40
+ */
41
+ previewLimit?: number | false;
42
+ children?: ReactNode;
43
+ }
44
+ export declare function ChatGroup({ title, collapsible, collapsed: collapsedProp, defaultCollapsed, onCollapsedChange, renaming: renamingProp, defaultRenaming, onRenamingChange, onRename, folderIcon, section, extra, extraVisible, previewLimit, children, className, ...rest }: ChatGroupProps): import("react").JSX.Element;
45
+ export declare namespace ChatGroup {
46
+ var displayName: string;
47
+ }
48
+ export default ChatGroup;
@@ -0,0 +1,250 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
4
+ var _excluded = ["title", "collapsible", "collapsed", "defaultCollapsed", "onCollapsedChange", "renaming", "defaultRenaming", "onRenamingChange", "onRename", "folderIcon", "section", "extra", "extraVisible", "previewLimit", "children", "className"];
5
+ import clsx from 'clsx';
6
+ import { Children, useEffect, useLayoutEffect, useRef, useState } from 'react';
7
+ import HoverFill from "../hover-fill";
8
+ import Icon from "../icon";
9
+ import { PRESENCE_TOTAL_MS, PresenceSlots } from "./presence-list";
10
+ import "./style";
11
+
12
+ /** 组内预览条数。仅收起后再打开时生效;默认展开态展示全部。 */
13
+ export var CHAT_GROUP_PREVIEW_LIMIT = 5;
14
+ function useControllableBool(controlled, defaultValue, onChange) {
15
+ var _useState = useState(defaultValue),
16
+ _useState2 = _slicedToArray(_useState, 2),
17
+ internal = _useState2[0],
18
+ setInternal = _useState2[1];
19
+ var value = controlled !== null && controlled !== void 0 ? controlled : internal;
20
+ var setValue = function setValue(next) {
21
+ onChange === null || onChange === void 0 || onChange(next);
22
+ if (controlled === undefined) setInternal(next);
23
+ };
24
+ return [value, setValue];
25
+ }
26
+ function ChatGroupHintRow(_ref) {
27
+ var kind = _ref.kind,
28
+ onExpand = _ref.onExpand,
29
+ _ref$remaining = _ref.remaining,
30
+ remaining = _ref$remaining === void 0 ? 0 : _ref$remaining,
31
+ _ref$expanded = _ref.expanded,
32
+ expanded = _ref$expanded === void 0 ? false : _ref$expanded;
33
+ var label = kind === 'empty' ? '暂无对话' : "\u5C55\u5F00\u5176\u4F59 ".concat(remaining, " \u6761");
34
+ if (kind === 'expand') {
35
+ return /*#__PURE__*/React.createElement(HoverFill, {
36
+ "data-odn-chat-group-hint": true,
37
+ "data-odn-chat-group-hint-kind": "expand",
38
+ bgClassName: "odn-chat-group-hint-bg"
39
+ }, /*#__PURE__*/React.createElement("button", {
40
+ type: "button",
41
+ "data-odn-chat-group-hint-inner": true,
42
+ "aria-expanded": expanded,
43
+ onMouseDown: function onMouseDown(e) {
44
+ return e.preventDefault();
45
+ },
46
+ onClick: onExpand
47
+ }, label));
48
+ }
49
+ return /*#__PURE__*/React.createElement("div", {
50
+ "data-odn-chat-group-hint": true,
51
+ "data-odn-chat-group-hint-kind": "empty"
52
+ }, /*#__PURE__*/React.createElement("div", {
53
+ "data-odn-chat-group-hint-inner": true
54
+ }, label));
55
+ }
56
+ export function ChatGroup(_ref2) {
57
+ var title = _ref2.title,
58
+ _ref2$collapsible = _ref2.collapsible,
59
+ collapsible = _ref2$collapsible === void 0 ? true : _ref2$collapsible,
60
+ collapsedProp = _ref2.collapsed,
61
+ _ref2$defaultCollapse = _ref2.defaultCollapsed,
62
+ defaultCollapsed = _ref2$defaultCollapse === void 0 ? false : _ref2$defaultCollapse,
63
+ onCollapsedChange = _ref2.onCollapsedChange,
64
+ renamingProp = _ref2.renaming,
65
+ _ref2$defaultRenaming = _ref2.defaultRenaming,
66
+ defaultRenaming = _ref2$defaultRenaming === void 0 ? false : _ref2$defaultRenaming,
67
+ onRenamingChange = _ref2.onRenamingChange,
68
+ onRename = _ref2.onRename,
69
+ _ref2$folderIcon = _ref2.folderIcon,
70
+ folderIcon = _ref2$folderIcon === void 0 ? false : _ref2$folderIcon,
71
+ _ref2$section = _ref2.section,
72
+ section = _ref2$section === void 0 ? false : _ref2$section,
73
+ extra = _ref2.extra,
74
+ extraVisible = _ref2.extraVisible,
75
+ previewLimit = _ref2.previewLimit,
76
+ children = _ref2.children,
77
+ className = _ref2.className,
78
+ rest = _objectWithoutProperties(_ref2, _excluded);
79
+ var _useControllableBool = useControllableBool(collapsedProp, defaultCollapsed, onCollapsedChange),
80
+ _useControllableBool2 = _slicedToArray(_useControllableBool, 2),
81
+ collapsed = _useControllableBool2[0],
82
+ setCollapsed = _useControllableBool2[1];
83
+ var _useControllableBool3 = useControllableBool(renamingProp, defaultRenaming, onRenamingChange),
84
+ _useControllableBool4 = _slicedToArray(_useControllableBool3, 2),
85
+ renaming = _useControllableBool4[0],
86
+ setRenaming = _useControllableBool4[1];
87
+ var titleText = typeof title === 'string' ? title : '';
88
+ var _useState3 = useState(titleText),
89
+ _useState4 = _slicedToArray(_useState3, 2),
90
+ draft = _useState4[0],
91
+ setDraft = _useState4[1];
92
+ var inputRef = useRef(null);
93
+ var canRename = Boolean(onRename) && typeof title === 'string';
94
+ useEffect(function () {
95
+ if (!renaming) setDraft(titleText);
96
+ }, [titleText, renaming]);
97
+ useEffect(function () {
98
+ if (!renaming) return;
99
+ var el = inputRef.current;
100
+ if (!el) return;
101
+ el.focus();
102
+ el.select();
103
+ }, [renaming]);
104
+ var toggle = function toggle() {
105
+ if (!collapsible || renaming) return;
106
+ setCollapsed(!collapsed);
107
+ };
108
+ var commitRename = function commitRename() {
109
+ var trimmed = draft.trim();
110
+ if (trimmed && trimmed !== titleText) onRename === null || onRename === void 0 || onRename(trimmed);
111
+ setRenaming(false);
112
+ };
113
+ var cancelRename = function cancelRename() {
114
+ setDraft(titleText);
115
+ setRenaming(false);
116
+ };
117
+ var startsExpanded = !(collapsedProp !== null && collapsedProp !== void 0 ? collapsedProp : defaultCollapsed);
118
+ var _useState5 = useState(startsExpanded),
119
+ _useState6 = _slicedToArray(_useState5, 2),
120
+ overflowOpen = _useState6[0],
121
+ setOverflowOpen = _useState6[1];
122
+ var _useState7 = useState(false),
123
+ _useState8 = _slicedToArray(_useState7, 2),
124
+ hintLeaving = _useState8[0],
125
+ setHintLeaving = _useState8[1];
126
+ useLayoutEffect(function () {
127
+ if (collapsed) {
128
+ setOverflowOpen(false);
129
+ setHintLeaving(false);
130
+ }
131
+ }, [collapsed]);
132
+ useEffect(function () {
133
+ if (!hintLeaving) return;
134
+ var t = window.setTimeout(function () {
135
+ return setHintLeaving(false);
136
+ }, PRESENCE_TOTAL_MS);
137
+ return function () {
138
+ return window.clearTimeout(t);
139
+ };
140
+ }, [hintLeaving]);
141
+ var expandOverflow = function expandOverflow() {
142
+ var _window$matchMedia, _window;
143
+ setOverflowOpen(true);
144
+ if (typeof window !== 'undefined' && (_window$matchMedia = (_window = window).matchMedia) !== null && _window$matchMedia !== void 0 && _window$matchMedia.call(_window, '(prefers-reduced-motion: reduce)').matches) {
145
+ return;
146
+ }
147
+ setHintLeaving(true);
148
+ };
149
+ var childList = Children.toArray(children).filter(Boolean);
150
+ var resolvedLimit = previewLimit === false ? Number.POSITIVE_INFINITY : previewLimit !== null && previewLimit !== void 0 ? previewLimit : CHAT_GROUP_PREVIEW_LIMIT;
151
+ // 折叠过程中不要截成预览:否则 scrollHeight 先跳一截,滚动锚定会把列表拽走。
152
+ var truncated = !collapsed && !overflowOpen && Number.isFinite(resolvedLimit) && childList.length > resolvedLimit;
153
+ var remaining = Math.max(0, childList.length - resolvedLimit);
154
+ var expandHint = /*#__PURE__*/React.createElement(ChatGroupHintRow, {
155
+ kind: "expand",
156
+ remaining: remaining,
157
+ expanded: hintLeaving,
158
+ onExpand: expandOverflow
159
+ });
160
+ var body = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(PresenceSlots, {
161
+ enabled: !collapsed,
162
+ displayLimit: truncated ? resolvedLimit : undefined,
163
+ empty: /*#__PURE__*/React.createElement(ChatGroupHintRow, {
164
+ kind: "empty"
165
+ })
166
+ }, children), truncated || hintLeaving ? hintLeaving ? /*#__PURE__*/React.createElement("div", {
167
+ "data-odn-chat-group-slot": true,
168
+ "data-odn-chat-group-leave": "swap",
169
+ "aria-hidden": true
170
+ }, /*#__PURE__*/React.createElement("div", {
171
+ "data-odn-chat-group-slot-inner": true
172
+ }, expandHint)) : expandHint : null);
173
+ var header = /*#__PURE__*/React.createElement("div", {
174
+ "data-odn-chat-group-header": true
175
+ }, renaming && canRename ? /*#__PURE__*/React.createElement("div", {
176
+ "data-odn-chat-group-rename": true
177
+ }, folderIcon ? /*#__PURE__*/React.createElement(Icon, {
178
+ name: "folder",
179
+ size: 14,
180
+ "data-odn-chat-group-folder-icon": true
181
+ }) : null, /*#__PURE__*/React.createElement("input", {
182
+ ref: inputRef,
183
+ value: draft,
184
+ "aria-label": "\u91CD\u547D\u540D\u5206\u7EC4",
185
+ "data-odn-chat-group-rename-input": true,
186
+ onChange: function onChange(e) {
187
+ return setDraft(e.target.value);
188
+ },
189
+ onBlur: commitRename,
190
+ onClick: function onClick(e) {
191
+ return e.stopPropagation();
192
+ },
193
+ onKeyDown: function onKeyDown(e) {
194
+ if (e.nativeEvent.isComposing || e.keyCode === 229) return;
195
+ if (e.key === 'Enter') {
196
+ e.preventDefault();
197
+ commitRename();
198
+ }
199
+ if (e.key === 'Escape') {
200
+ e.preventDefault();
201
+ cancelRename();
202
+ }
203
+ }
204
+ })) : collapsible ? /*#__PURE__*/React.createElement("button", {
205
+ type: "button",
206
+ "data-odn-chat-group-trigger": true,
207
+ onClick: toggle,
208
+ "aria-expanded": !collapsed
209
+ }, folderIcon ? /*#__PURE__*/React.createElement(Icon, {
210
+ name: "folder",
211
+ size: 14,
212
+ "data-odn-chat-group-folder-icon": true
213
+ }) : null, /*#__PURE__*/React.createElement("span", {
214
+ "data-odn-chat-group-title": true
215
+ }, title), /*#__PURE__*/React.createElement(Icon, {
216
+ name: "right",
217
+ size: 12,
218
+ "data-odn-chat-group-chevron": true
219
+ })) : /*#__PURE__*/React.createElement("div", {
220
+ "data-odn-chat-group-title-row": true
221
+ }, folderIcon ? /*#__PURE__*/React.createElement(Icon, {
222
+ name: "folder",
223
+ size: 14,
224
+ "data-odn-chat-group-folder-icon": true
225
+ }) : null, /*#__PURE__*/React.createElement("span", {
226
+ "data-odn-chat-group-title": true
227
+ }, title)), extra ? /*#__PURE__*/React.createElement("div", {
228
+ "data-odn-chat-group-extra": true
229
+ }, extra) : null);
230
+ return /*#__PURE__*/React.createElement("div", _extends({
231
+ "data-odn-chat-group": true,
232
+ "data-odn-chat-group-collapsed": collapsed || undefined,
233
+ "data-odn-chat-group-renaming": renaming || undefined,
234
+ "data-odn-chat-group-folder": folderIcon || undefined,
235
+ "data-odn-chat-group-section": section || undefined,
236
+ "data-odn-chat-group-extra-visible": extraVisible || undefined,
237
+ className: clsx(className)
238
+ }, rest), section ? header : /*#__PURE__*/React.createElement(HoverFill, {
239
+ "data-odn-chat-group-header-fill": true,
240
+ bgClassName: "odn-chat-group-header-bg",
241
+ disabled: renaming
242
+ }, header), /*#__PURE__*/React.createElement("div", {
243
+ "data-odn-chat-group-collapse": true,
244
+ "aria-hidden": collapsed || undefined
245
+ }, /*#__PURE__*/React.createElement("div", {
246
+ "data-odn-chat-group-body": true
247
+ }, body)));
248
+ }
249
+ ChatGroup.displayName = 'ChatGroup';
250
+ export default ChatGroup;
@@ -0,0 +1,29 @@
1
+ import { type ReactNode } from 'react';
2
+ export declare const PRESENCE_SHIFT_MS = 180;
3
+ export declare const PRESENCE_FADE_MS = 160;
4
+ export declare const PRESENCE_TOTAL_MS: number;
5
+ export type PresenceKind = 'shift' | 'fade';
6
+ type Entering = {
7
+ key: string;
8
+ kind: PresenceKind;
9
+ };
10
+ type Leaving = {
11
+ key: string;
12
+ kind: PresenceKind;
13
+ node: ReactNode;
14
+ index: number;
15
+ };
16
+ export declare function childSlotKey(child: ReactNode, index: number): string;
17
+ export declare function usePresence(childList: ReactNode[], enabled: boolean): {
18
+ entering: Entering | null;
19
+ leaving: Leaving | null;
20
+ };
21
+ export declare function buildPresenceSlots(childList: ReactNode[], entering: Entering | null, leaving: Leaving | null, displayLimit?: number, revealingKeys?: string[] | null): import("react").JSX.Element[];
22
+ export declare function PresenceSlots({ children, enabled, displayLimit, empty, host, }: {
23
+ children?: ReactNode;
24
+ enabled?: boolean;
25
+ displayLimit?: number;
26
+ empty?: ReactNode;
27
+ host?: (content: ReactNode, occupied: boolean) => ReactNode;
28
+ }): import("react").JSX.Element;
29
+ export {};
@@ -0,0 +1,194 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import { Children, cloneElement, Fragment, isValidElement, useEffect, useLayoutEffect, useRef, useState } from 'react';
3
+ export var PRESENCE_SHIFT_MS = 180;
4
+ export var PRESENCE_FADE_MS = 160;
5
+ export var PRESENCE_TOTAL_MS = PRESENCE_SHIFT_MS + PRESENCE_FADE_MS + 40;
6
+ export function childSlotKey(child, index) {
7
+ if ( /*#__PURE__*/isValidElement(child) && child.key !== null && child.key !== undefined) {
8
+ return String(child.key);
9
+ }
10
+ return "idx-".concat(index);
11
+ }
12
+ function prefersReducedMotion() {
13
+ var _window$matchMedia, _window;
14
+ return Boolean(typeof window !== 'undefined' && ((_window$matchMedia = (_window = window).matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(_window, '(prefers-reduced-motion: reduce)').matches));
15
+ }
16
+ export function usePresence(childList, enabled) {
17
+ var _prevRef$current;
18
+ var keys = childList.map(function (child, i) {
19
+ return childSlotKey(child, i);
20
+ });
21
+ var keysSig = keys.join('\0');
22
+ var _useState = useState(null),
23
+ _useState2 = _slicedToArray(_useState, 2),
24
+ entering = _useState2[0],
25
+ setEntering = _useState2[1];
26
+ var _useState3 = useState(null),
27
+ _useState4 = _slicedToArray(_useState3, 2),
28
+ leaving = _useState4[0],
29
+ setLeaving = _useState4[1];
30
+ var prevRef = useRef(null);
31
+ if (((_prevRef$current = prevRef.current) === null || _prevRef$current === void 0 ? void 0 : _prevRef$current.keys.join('\0')) === keysSig) {
32
+ prevRef.current.nodes = childList;
33
+ }
34
+ useLayoutEffect(function () {
35
+ var nextKeys = keysSig.length === 0 ? [] : keysSig.split('\0');
36
+ var prev = prevRef.current;
37
+ prevRef.current = {
38
+ keys: nextKeys,
39
+ nodes: childList
40
+ };
41
+ if (prev === null || !enabled || prefersReducedMotion()) return;
42
+ var added = nextKeys.filter(function (k) {
43
+ return !prev.keys.includes(k);
44
+ });
45
+ var removed = prev.keys.filter(function (k) {
46
+ return !nextKeys.includes(k);
47
+ });
48
+ if (added.length === 1 && removed.length === 0 && nextKeys[0] === added[0]) {
49
+ setLeaving(null);
50
+ setEntering({
51
+ key: added[0],
52
+ kind: prev.keys.length === 0 ? 'fade' : 'shift'
53
+ });
54
+ return;
55
+ }
56
+ if (removed.length === 1 && added.length === 0) {
57
+ var key = removed[0];
58
+ var index = prev.keys.indexOf(key);
59
+ setEntering(null);
60
+ setLeaving({
61
+ key: key,
62
+ node: prev.nodes[index],
63
+ index: index,
64
+ kind: nextKeys.length === 0 ? 'fade' : 'shift'
65
+ });
66
+ }
67
+ // childList 与 keysSig 同步;只跟签名,避免引用抖动。
68
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
+ }, [keysSig, enabled]);
70
+ useEffect(function () {
71
+ if (!entering) return;
72
+ var t = window.setTimeout(function () {
73
+ return setEntering(null);
74
+ }, PRESENCE_TOTAL_MS);
75
+ return function () {
76
+ return window.clearTimeout(t);
77
+ };
78
+ }, [entering]);
79
+ useEffect(function () {
80
+ if (!leaving) return;
81
+ var t = window.setTimeout(function () {
82
+ return setLeaving(null);
83
+ }, PRESENCE_TOTAL_MS);
84
+ return function () {
85
+ return window.clearTimeout(t);
86
+ };
87
+ }, [leaving]);
88
+ return {
89
+ entering: entering,
90
+ leaving: leaving
91
+ };
92
+ }
93
+ function renderSlot(key, node, enter, leave) {
94
+ // 空闲项不包一层:HoverFill 共享底要求同一 parentNode。
95
+ // 入场/离场才用 slot 做 0fr↔1fr 高度动画。
96
+ if (!enter && !leave) {
97
+ if ( /*#__PURE__*/isValidElement(node)) return /*#__PURE__*/cloneElement(node, {
98
+ key: key
99
+ });
100
+ return /*#__PURE__*/React.createElement(Fragment, {
101
+ key: key
102
+ }, node);
103
+ }
104
+ return /*#__PURE__*/React.createElement("div", {
105
+ key: key,
106
+ "data-odn-chat-group-slot": true,
107
+ "data-odn-chat-group-enter": enter,
108
+ "data-odn-chat-group-leave": leave,
109
+ "aria-hidden": leave ? true : undefined
110
+ }, /*#__PURE__*/React.createElement("div", {
111
+ "data-odn-chat-group-slot-inner": true
112
+ }, node));
113
+ }
114
+ export function buildPresenceSlots(childList, entering, leaving, displayLimit, revealingKeys) {
115
+ var display = displayLimit !== undefined && Number.isFinite(displayLimit) ? childList.slice(0, displayLimit) : childList;
116
+ var revealing = revealingKeys !== null && revealingKeys !== void 0 && revealingKeys.length ? new Set(revealingKeys) : null;
117
+ var slots = display.map(function (node, i) {
118
+ var key = childSlotKey(node, i);
119
+ return {
120
+ key: key,
121
+ node: node,
122
+ enter: (entering === null || entering === void 0 ? void 0 : entering.key) === key ? entering.kind : revealing !== null && revealing !== void 0 && revealing.has(key) ? 'shift' : undefined,
123
+ leave: undefined
124
+ };
125
+ });
126
+ if (leaving) {
127
+ var inDisplay = slots.some(function (s) {
128
+ return s.key === leaving.key;
129
+ });
130
+ var windowSize = displayLimit !== null && displayLimit !== void 0 ? displayLimit : Number.POSITIVE_INFINITY;
131
+ if (!inDisplay && leaving.index < windowSize) {
132
+ slots.splice(Math.min(leaving.index, slots.length), 0, {
133
+ key: leaving.key,
134
+ node: leaving.node,
135
+ enter: undefined,
136
+ leave: leaving.kind
137
+ });
138
+ }
139
+ }
140
+ return slots.map(function (s) {
141
+ return renderSlot(s.key, s.node, s.enter, s.leave);
142
+ });
143
+ }
144
+ export function PresenceSlots(_ref) {
145
+ var children = _ref.children,
146
+ _ref$enabled = _ref.enabled,
147
+ enabled = _ref$enabled === void 0 ? true : _ref$enabled,
148
+ displayLimit = _ref.displayLimit,
149
+ _ref$empty = _ref.empty,
150
+ empty = _ref$empty === void 0 ? null : _ref$empty,
151
+ host = _ref.host;
152
+ var childList = Children.toArray(children).filter(Boolean);
153
+ var _usePresence = usePresence(childList, enabled),
154
+ entering = _usePresence.entering,
155
+ leaving = _usePresence.leaving;
156
+ var keysSig = childList.map(function (child, i) {
157
+ return childSlotKey(child, i);
158
+ }).join('\0');
159
+ var _useState5 = useState(null),
160
+ _useState6 = _slicedToArray(_useState5, 2),
161
+ revealingKeys = _useState6[0],
162
+ setRevealingKeys = _useState6[1];
163
+ var prevLimitRef = useRef(undefined);
164
+ var limitReadyRef = useRef(false);
165
+ useLayoutEffect(function () {
166
+ var prevLimit = prevLimitRef.current;
167
+ prevLimitRef.current = displayLimit;
168
+ if (!limitReadyRef.current) {
169
+ limitReadyRef.current = true;
170
+ return;
171
+ }
172
+ if (!enabled || prefersReducedMotion()) return;
173
+ if (prevLimit !== undefined && Number.isFinite(prevLimit) && displayLimit === undefined && childList.length > prevLimit) {
174
+ setRevealingKeys(childList.slice(prevLimit).map(function (child, i) {
175
+ return childSlotKey(child, prevLimit + i);
176
+ }));
177
+ }
178
+ // eslint-disable-next-line react-hooks/exhaustive-deps
179
+ }, [displayLimit, keysSig, enabled]);
180
+ useEffect(function () {
181
+ if (!revealingKeys) return;
182
+ var t = window.setTimeout(function () {
183
+ return setRevealingKeys(null);
184
+ }, PRESENCE_TOTAL_MS);
185
+ return function () {
186
+ return window.clearTimeout(t);
187
+ };
188
+ }, [revealingKeys]);
189
+ var occupied = childList.length > 0 || leaving !== null;
190
+ var content = occupied ? buildPresenceSlots(childList, entering, leaving, displayLimit, revealingKeys) : empty;
191
+ if (host) return /*#__PURE__*/React.createElement(React.Fragment, null, host(content, occupied));
192
+ if (!occupied) return /*#__PURE__*/React.createElement(React.Fragment, null, empty);
193
+ return /*#__PURE__*/React.createElement(React.Fragment, null, content);
194
+ }