New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@rchat/react

Package Overview
Dependencies
Maintainers
3
Versions
72
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@rchat/react - npm Package Compare versions

Comparing version
0.12.1
to
0.12.2
+0
-0
LICENSE

@@ -0,0 +0,0 @@ MIT License

+1
-1
{
"name": "@rchat/react",
"description": "Awesome React chat",
"version": "0.12.1",
"version": "0.12.2",
"main": "./dist/src/index.js",

@@ -6,0 +6,0 @@ "types": "./dist/src/index.d.ts",

@@ -0,0 +0,0 @@ export * from './EndlessList';

'use strict'
if(process.env.NODE_ENV === 'production') {
module.exports = require('./rchat-react.cjs.production.min.js');
} else {
module.exports = require('./rchat-react.cjs.development.js');
}
import React from 'react';
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var src_exports = {};
__export(src_exports, {
Chat: () => Chat,
EndlessList: () => EndlessList,
MessageList: () => MessageList,
Room: () => Room,
useEndlessList: () => useEndlessList,
useMessages: () => useMessages,
useVisibleItems: () => useVisibleItems
});
module.exports = __toCommonJS(src_exports);
// src/EndlessList/EndlessList.tsx
var import_react8 = require("react");
// src/internal/mergeReferences.ts
var mergeReferences = /* @__PURE__ */ __name((...inputReferences) => {
const filteredInputReferences = inputReferences.filter(Boolean);
if (filteredInputReferences.length <= 1) {
return filteredInputReferences[0];
}
return /* @__PURE__ */ __name(function mergedReferences(reference) {
for (const inputReference of filteredInputReferences) {
if (typeof inputReference === "function") {
inputReference(reference);
} else if (inputReference) {
inputReference.current = reference;
}
}
}, "mergedReferences");
}, "mergeReferences");
// src/internal/smoothScrollToCenter.ts
var smoothScrollToCenter = /* @__PURE__ */ __name(async (container, element, parameters, controller) => {
const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
const top = elementRect.top - containerRect.top - containerRect.height / 2 + elementRect.height / 2;
const startPos = container.scrollTop;
const clientHeight = container.clientHeight;
const maxScroll = container.scrollHeight - clientHeight;
const scrollIntendedDestination = startPos + top;
const scrollEndValue = Math.min(Math.max(scrollIntendedDestination, 0), maxScroll);
let startTime = 0;
const duration = parameters.duration(scrollEndValue - startPos);
return new Promise((resolve, reject) => {
const scroll = /* @__PURE__ */ __name((timestamp) => {
if (controller == null ? void 0 : controller.signal.aborted) {
reject(controller.signal.reason);
return;
}
startTime = startTime || timestamp;
const elapsed = timestamp - startTime;
container.scrollTop = startPos + (scrollEndValue - startPos) * parameters.easing(elapsed / duration);
if (elapsed <= duration) {
window.requestAnimationFrame(scroll);
} else {
resolve();
}
}, "scroll");
if (startPos !== scrollEndValue) {
window.requestAnimationFrame(scroll);
} else {
resolve();
}
});
}, "smoothScrollToCenter");
// src/internal/useEvent.ts
var import_react = require("react");
var useEvent = /* @__PURE__ */ __name((handler) => {
const handlerReference = (0, import_react.useRef)(handler);
handlerReference.current = handler;
return (0, import_react.useCallback)((...parameters) => {
return handlerReference.current(...parameters);
}, []);
}, "useEvent");
// src/internal/useScheduleOnNextRender.tsx
var import_react2 = require("react");
var useScheduleOnNextRender = /* @__PURE__ */ __name((handler) => {
const unresolvedHandle = (0, import_react2.useRef)();
(0, import_react2.useLayoutEffect)(() => {
const currentHandle = unresolvedHandle.current;
unresolvedHandle.current = void 0;
if (currentHandle) {
handler(...currentHandle.parameters).then(currentHandle.resolve).catch(currentHandle.reject);
}
});
const wrappedFunction = (0, import_react2.useCallback)((...parameters) => {
return new Promise((resolve, reject) => {
unresolvedHandle.current = {
parameters,
resolve,
reject
};
});
}, []);
const isScheduled = (0, import_react2.useCallback)(() => {
return unresolvedHandle.current !== void 0;
}, []);
return [wrappedFunction, isScheduled];
}, "useScheduleOnNextRender");
// src/internal/useToggleEvent.ts
var import_react3 = require("react");
var useToggleEvent = /* @__PURE__ */ __name((onTurnedOn) => {
const value = (0, import_react3.useRef)(false);
const toggle = (0, import_react3.useCallback)(
(newValue) => {
if (!value.current && newValue) {
onTurnedOn();
}
value.current = newValue;
},
[onTurnedOn]
);
return toggle;
}, "useToggleEvent");
// src/EndlessList/EndlessListItemView.tsx
var import_react4 = require("react");
var EndlessListItemView = /* @__PURE__ */ __name((_a) => {
var _b = _a, {
ItemComponent,
PlaceholderComponent,
itemObserver,
focusElementReference
} = _b, item = __objRest(_b, [
"ItemComponent",
"PlaceholderComponent",
"itemObserver",
"focusElementReference"
]);
const itemReference = (0, import_react4.useRef)(null);
(0, import_react4.useEffect)(() => {
const currentElement = itemReference.current;
if (currentElement && itemObserver) {
itemObserver.observe(currentElement);
return () => itemObserver.unobserve(currentElement);
}
}, [itemObserver]);
if (item.type === "placeholder") {
return /* @__PURE__ */ React.createElement(PlaceholderComponent, { ref: itemReference, itemKey: item.itemKey });
}
return /* @__PURE__ */ React.createElement(ItemComponent, __spreadValues({ ref: mergeReferences(itemReference, item.focused && focusElementReference) }, item));
}, "EndlessListItemView");
// src/EndlessList/useEndlessList.tsx
var import_react6 = require("react");
var import_use_isomorphic_layout_effect = __toESM(require("use-isomorphic-layout-effect"));
// src/internal/binarySearch.ts
var binarySearch = /* @__PURE__ */ __name((array, value, comparator) => {
let low = 0;
let high = array.length;
if (high === 0) {
return 0;
}
while (low < high) {
const middle = Math.floor((low + high) / 2);
if (comparator(value, { value: array[middle], index: middle }) > 0) {
low = middle + 1;
} else {
high = middle;
}
}
return high;
}, "binarySearch");
// src/internal/useIdGenerator.ts
var import_react5 = require("react");
var useIdGenerator = /* @__PURE__ */ __name(() => {
const counter = (0, import_react5.useRef)(0);
return (0, import_react5.useCallback)(() => `:rchat:-${++counter.current}`, []);
}, "useIdGenerator");
// src/EndlessList/useEndlessList.tsx
var valueToEndlessListItem = /* @__PURE__ */ __name((getKey, focusItemKey) => {
return (value, index, array) => {
const key = getKey(value);
return {
type: "real",
value,
index,
array,
focused: key === focusItemKey,
itemKey: key
};
};
}, "valueToEndlessListItem");
var useEndlessList = /* @__PURE__ */ __name(({
initialItems,
items,
getKey,
focusedItem,
compareItems,
handleJump,
visibleItemKeys,
lastScrolledItem
}) => {
const focusedItemKey = focusedItem === void 0 ? void 0 : getKey(focusedItem);
const defaultConvertItem = (0, import_react6.useMemo)(() => valueToEndlessListItem(getKey, focusedItemKey), [getKey, focusedItemKey]);
const [renderedItems, setRenderedItems] = (0, import_react6.useState)(() => items.map(defaultConvertItem));
const jumpAbortController = (0, import_react6.useRef)();
const initialItemsReference = (0, import_react6.useRef)(initialItems);
const hasMounted = (0, import_react6.useRef)(false);
const getUniquePlaceholderKey = useIdGenerator();
const performFixup = useEvent(() => {
const visibleItems = renderedItems.filter(({ itemKey, type }, index, array) => {
if (visibleItemKeys.current.has(itemKey)) {
return true;
}
if (type === "placeholder") {
return false;
}
const previousItem = array[index - 1];
if (previousItem && previousItem.type !== "placeholder" && visibleItemKeys.current.has(previousItem.itemKey)) {
return true;
}
const nextItem = array[index + 1];
if (nextItem && nextItem.type !== "placeholder" && visibleItemKeys.current.has(nextItem.itemKey)) {
return true;
}
return false;
}).map((item) => {
if (item.type === "real" && item.focused) {
item.focused = false;
}
return item;
});
const keys = new Set(items.map(getKey));
if (visibleItems.every((item) => !keys.has(item.itemKey))) {
return [visibleItems, true];
}
const comparator = /* @__PURE__ */ __name((a, b) => {
if (b.value.type === "placeholder") {
const nextValue = visibleItems[b.index + 1];
if (nextValue !== void 0 && nextValue.type !== "placeholder") {
return compareItems(nextValue.value, a.value);
}
return 1;
}
return compareItems(a.value, b.value.value);
}, "comparator");
const jumpKey = focusedItemKey != null ? focusedItemKey : getKey(items[Math.floor(items.length / 2)]);
const convertedItems = [...items.map(valueToEndlessListItem(getKey, jumpKey))];
let pivotIndex = visibleItems.findIndex((item) => keys.has(item.itemKey));
if (pivotIndex === -1) {
pivotIndex = binarySearch(visibleItems, convertedItems.at(0), comparator);
}
visibleItems.splice(pivotIndex, 1, ...convertedItems);
const dedupedKeys = /* @__PURE__ */ new Set();
const filteredItems = visibleItems.filter((item) => {
if (dedupedKeys.has(item.itemKey)) {
return false;
}
dedupedKeys.add(item.itemKey);
return true;
});
return [filteredItems, false];
});
const update = useEvent(async () => {
var _a, _b;
if (jumpAbortController.current) {
jumpAbortController.current.abort();
jumpAbortController.current = void 0;
}
if (renderedItems.length === 0 || items.length === 0 || initialItemsReference.current !== initialItems) {
setRenderedItems(items.map(defaultConvertItem));
initialItemsReference.current = initialItems;
return;
}
const isAbortedPreviousJump = renderedItems.some((item) => item.type === "placeholder");
let oldItems;
let constructItems = true;
if (isAbortedPreviousJump) {
[oldItems, constructItems] = performFixup();
let array = [];
let index = 0;
for (const item of oldItems) {
if (item.type === "placeholder") {
index = 0;
array = [];
} else {
item.index = index;
item.array = array;
array.push(item.value);
++index;
}
}
} else {
const keys = items.map(getKey);
const oldKeys = renderedItems.map((item) => item.itemKey);
const mustMoveForward = !oldKeys.includes(keys[0]) && !keys.includes(oldKeys.at(-1));
const mustMoveBack = !keys.includes(oldKeys[0]) && !oldKeys.includes(keys.at(-1));
const mustJump = mustMoveForward && mustMoveBack;
if (!mustJump) {
setRenderedItems(items.map(defaultConvertItem));
return;
}
oldItems = renderedItems.map((item) => {
if (item.type === "real" && item.focused) {
item.focused = false;
}
return item;
});
}
let constructedItems;
if (constructItems) {
const firstItem = oldItems.find((item) => item.type === "real");
let jumpDirection = "forward";
if (firstItem) {
jumpDirection = compareItems(items[0], firstItem.value) < 0 ? "forward" : "back";
}
const jumpKey = focusedItemKey != null ? focusedItemKey : getKey(items[Math.floor(items.length / 2)]);
let nextItems;
let previousItems;
const convertItem = valueToEndlessListItem(getKey, jumpKey);
if (jumpDirection === "forward") {
nextItems = items.map(convertItem);
previousItems = oldItems;
} else {
nextItems = oldItems;
previousItems = items.map(convertItem);
}
const alreadyHasPlaceholder = ((_a = nextItems.at(-1)) == null ? void 0 : _a.type) === "placeholder" || ((_b = previousItems.at(0)) == null ? void 0 : _b.type) === "placeholder";
constructedItems = [
...nextItems,
...alreadyHasPlaceholder ? [] : [{ type: "placeholder", itemKey: getUniquePlaceholderKey() }],
...previousItems
];
} else {
constructedItems = oldItems;
}
lastScrolledItem.current = items[Math.floor(items.length / 2)];
setRenderedItems(constructedItems);
const newController = new AbortController();
jumpAbortController.current = newController;
try {
if (hasMounted.current) {
await handleJump(newController);
}
setRenderedItems(items.map(defaultConvertItem));
} catch (e) {
} finally {
jumpAbortController.current = void 0;
}
});
(0, import_use_isomorphic_layout_effect.default)(() => {
update();
hasMounted.current = true;
}, [update, items]);
(0, import_react6.useEffect)(() => {
return () => {
hasMounted.current = false;
};
}, []);
return renderedItems;
}, "useEndlessList");
// src/EndlessList/useVisibleFrame.tsx
var useVisibleFrame = /* @__PURE__ */ __name(({
items,
getKey,
onVisibleFrameUpdated
}) => {
const updateVisibleFrame = useEvent((visibleItemKeys) => {
let begin = -1;
for (const [index, item] of items.entries()) {
if (visibleItemKeys.has(getKey(item))) {
begin = index;
break;
}
}
let end = -1;
for (let index = 0; index <= items.length; ++index) {
const item = items.at(-index - 1);
if (item && visibleItemKeys.has(getKey(item))) {
end = index;
break;
}
}
onVisibleFrameUpdated({ begin, end });
});
return updateVisibleFrame;
}, "useVisibleFrame");
// src/EndlessList/useVisibleItems.tsx
var import_react7 = require("react");
var useVisibleItems = /* @__PURE__ */ __name((containerReference, onVisibleItemsChange) => {
const [observer, setObserver] = (0, import_react7.useState)();
const visibleItemKeysReference = (0, import_react7.useRef)(/* @__PURE__ */ new Set());
const updateVisibleFrame = useEvent((entries) => {
for (const { target, isIntersecting } of entries) {
const key = target.dataset.key;
if (!key) {
console.warn(`Item component doesn't have "data-key" attribute.`);
} else if (isIntersecting) {
visibleItemKeysReference.current.add(key);
} else {
visibleItemKeysReference.current.delete(key);
}
}
onVisibleItemsChange == null ? void 0 : onVisibleItemsChange(visibleItemKeysReference.current);
});
(0, import_react7.useEffect)(() => {
const containerElement = containerReference.current;
if (containerElement) {
const observer2 = new IntersectionObserver(updateVisibleFrame, { root: containerElement, threshold: 0 });
setObserver(observer2);
}
}, [containerReference, updateVisibleFrame]);
return { observer, visibleItemKeys: visibleItemKeysReference };
}, "useVisibleItems");
// src/EndlessList/EndlessList.tsx
var noop = /* @__PURE__ */ __name(() => {
}, "noop");
var defaultAnimationParameters = {
duration: () => 500,
easing: (t) => t
};
var EndlessList = /* @__PURE__ */ __name(({
ItemComponent,
initialItems,
items,
itemKey,
triggerDistance,
onTopReached,
onBottomReached,
compareItems,
PlaceholderComponent,
jumpAnimation = defaultAnimationParameters,
focusedItem,
ContainerComponent,
canStickToBottom,
onVisibleFrameChange,
containerReference: propsContainerReference
}) => {
const containerReference = (0, import_react8.useRef)(null);
const focusElementReference = (0, import_react8.useRef)(null);
const stickToBottomReached = (0, import_react8.useRef)(false);
const isScrolling = (0, import_react8.useRef)(false);
const visibleFrame = (0, import_react8.useRef)({ begin: -1, end: -1 });
const hasMounted = (0, import_react8.useRef)(false);
const setBottomReached = useToggleEvent(onBottomReached != null ? onBottomReached : noop);
const setTopReached = useToggleEvent(onTopReached != null ? onTopReached : noop);
const getKey = (0, import_react8.useMemo)(() => {
return typeof itemKey === "function" ? itemKey : (value) => value[itemKey];
}, [itemKey]);
(0, import_react8.useEffect)(() => {
setBottomReached(false);
setTopReached(false);
}, [items, setBottomReached, setTopReached]);
const checkBounds = useEvent((frame = visibleFrame.current) => {
onVisibleFrameChange == null ? void 0 : onVisibleFrameChange(frame);
visibleFrame.current = frame;
if (frame.begin === -1 || frame.end === -1 || isScrolling.current) {
return;
}
setBottomReached(frame.end <= triggerDistance);
setTopReached(frame.begin <= triggerDistance);
stickToBottomReached.current = frame.end === 0;
});
const smoothScrolling = useEvent((container, item, abortController) => {
return smoothScrollToCenter(container, item, jumpAnimation, abortController);
});
const abortControllerReference = (0, import_react8.useRef)();
const handleJumpScroll = (0, import_react8.useCallback)(
async (abortController = new AbortController()) => {
if (abortControllerReference.current) {
abortControllerReference.current.abort();
}
if (!containerReference.current || !focusElementReference.current) {
return;
}
abortControllerReference.current = abortController;
isScrolling.current = true;
if (hasMounted.current) {
await smoothScrolling(containerReference.current, focusElementReference.current, abortController);
} else {
focusElementReference.current.scrollIntoView({ behavior: "auto", block: "center" });
}
isScrolling.current = false;
checkBounds();
},
[checkBounds, smoothScrolling]
);
const onVisibleItemsChange = useVisibleFrame({
getKey,
items,
onVisibleFrameUpdated: checkBounds
});
const { observer, visibleItemKeys } = useVisibleItems(containerReference, onVisibleItemsChange);
const [scheduleJumpScroll, isJumpScheduled] = useScheduleOnNextRender(handleJumpScroll);
const lastScrolledItem = (0, import_react8.useRef)();
const handleScrollToFocusItem = useEvent(() => {
if (focusedItem === lastScrolledItem.current) {
return;
}
lastScrolledItem.current = focusedItem;
if (focusedItem && !isJumpScheduled()) {
handleJumpScroll().catch(() => {
});
}
});
const itemsToRender = useEndlessList({
getKey,
initialItems,
items,
compareItems,
handleJump: scheduleJumpScroll,
focusedItem,
visibleItemKeys,
lastScrolledItem
});
(0, import_react8.useEffect)(() => {
handleScrollToFocusItem();
hasMounted.current = true;
}, [handleScrollToFocusItem, itemsToRender]);
(0, import_react8.useEffect)(() => {
return () => {
hasMounted.current = false;
};
}, []);
const handleStickToBottom = useEvent(() => {
const container = containerReference.current;
if (container && stickToBottomReached.current && !focusedItem) {
container.scrollTo({ top: container.scrollHeight });
}
});
(0, import_react8.useLayoutEffect)(() => {
if (canStickToBottom) {
handleStickToBottom();
}
}, [itemsToRender, canStickToBottom, handleStickToBottom]);
return /* @__PURE__ */ React.createElement(ContainerComponent, { ref: mergeReferences(containerReference, propsContainerReference) }, itemsToRender.map((item) => /* @__PURE__ */ React.createElement(
EndlessListItemView,
__spreadValues({
key: item.itemKey,
focusElementReference,
ItemComponent,
PlaceholderComponent,
itemObserver: observer
}, item)
)));
}, "EndlessList");
// src/internal/RChatContext.tsx
var import_safe_context = require("@sirse-dev/safe-context");
var RChatContext = (0, import_safe_context.createSafeContext)();
// src/Chat.tsx
var Chat = /* @__PURE__ */ __name((_a) => {
var _b = _a, { children } = _b, context = __objRest(_b, ["children"]);
return /* @__PURE__ */ React.createElement(RChatContext.Provider, { value: __spreadValues({}, context) }, children);
}, "Chat");
// src/MessageList.tsx
var import_safe_context3 = require("@sirse-dev/safe-context");
// src/internal/RoomContext.tsx
var import_safe_context2 = require("@sirse-dev/safe-context");
var RoomContext = (0, import_safe_context2.createSafeContext)();
// src/useMessages.tsx
var import_react10 = require("react");
// src/internal/clamp.ts
var clamp = /* @__PURE__ */ __name((value, min, max) => Math.max(Math.min(value, max), min), "clamp");
// src/internal/useBoundedArray.tsx
var import_react9 = require("react");
var getClippedArray = /* @__PURE__ */ __name((items, maxSize, keep) => {
if (items.length <= maxSize) {
return items;
}
if (keep === "beginning") {
return items.slice(0, maxSize);
}
if (keep === "ending") {
return items.slice(-maxSize);
}
throw new Error(`Unrecognized "keep" option value: "${keep}"`);
}, "getClippedArray");
var useBoundedArray = /* @__PURE__ */ __name((initial, maxChunkSize) => {
const [itemsState, setItemsState] = (0, import_react9.useState)(initial);
const itemsReference = (0, import_react9.useRef)(initial);
const setItems = (0, import_react9.useCallback)(
(items, keep) => {
const clippedItems = getClippedArray(items, maxChunkSize, keep);
setItemsState(clippedItems);
itemsReference.current = clippedItems;
return items.length > clippedItems.length;
},
[maxChunkSize]
);
const unshift = (0, import_react9.useCallback)(
(items) => {
return setItems([...items, ...itemsReference.current], "beginning");
},
[setItems]
);
const push = (0, import_react9.useCallback)(
(items) => {
return setItems([...itemsReference.current, ...items], "ending");
},
[setItems]
);
const at = (0, import_react9.useCallback)((index) => {
return itemsReference.current.at(index);
}, []);
const insert = (0, import_react9.useCallback)(
(item, index, keep) => {
itemsReference.current.splice(index, 0, item);
return setItems([...itemsReference.current], keep);
},
[setItems]
);
const getAll = (0, import_react9.useCallback)(() => itemsReference.current, []);
const refresh = (0, import_react9.useCallback)(() => setItemsState((old) => [...old]), []);
return [itemsState, { push, unshift, set: setItems, at, getAll, insert, refresh }];
}, "useBoundedArray");
// src/useMessages.tsx
var findNewElementIndex = /* @__PURE__ */ __name((elements, element, compare) => {
return elements.length - 1 - [...elements].reverse().findIndex((a) => {
return compare(element, a) > 0;
});
}, "findNewElementIndex");
var useMessages = /* @__PURE__ */ __name(({
maxChunkSize,
additionalChunkSize,
chatClient,
roomIdentifier,
compareItems,
initialMessagesState,
initialSearchResult
}) => {
const isFetching = (0, import_react10.useRef)(false);
const visibleFrame = (0, import_react10.useRef)({ begin: -1, end: -1 });
const containerReference = (0, import_react10.useRef)(null);
const searchResults = (0, import_react10.useRef)(initialSearchResult);
const selectedSearchResult = (0, import_react10.useRef)(0);
const focusedItem = (0, import_react10.useRef)(initialSearchResult == null ? void 0 : initialSearchResult.results[0]);
const [
messages,
{
push: pushMessages,
unshift: unshiftMessages,
set: setMessages,
insert: insertMessage,
at: getMessage,
getAll: getAllMessages,
refresh
}
] = useBoundedArray([...initialMessagesState.messages], maxChunkSize);
const messagesState = (0, import_react10.useRef)(initialMessagesState);
const handleIncomingMessage = (0, import_react10.useCallback)(
(message, messageRoomIdentifier) => {
if (messageRoomIdentifier === roomIdentifier && messagesState.current.noMessagesAfter) {
const incomingMessageIndex = findNewElementIndex(getAllMessages(), message, compareItems);
const keepDirection = visibleFrame.current.begin < visibleFrame.current.end ? "beginning" : "ending";
const clipped = insertMessage(message, incomingMessageIndex + 1, keepDirection);
if (clipped) {
if (keepDirection === "beginning") {
messagesState.current.noMessagesAfter = false;
} else {
messagesState.current.noMessagesBefore = false;
}
}
}
},
[roomIdentifier, getAllMessages, compareItems, insertMessage]
);
const focusItem = (0, import_react10.useCallback)(
async (item) => {
if (!item) {
if (focusedItem.current) {
refresh();
}
focusedItem.current = item;
return;
}
focusedItem.current = item;
const [previousChunk, nextChunk] = await Promise.all([
chatClient.fetchMessages(roomIdentifier, additionalChunkSize, item, void 0),
chatClient.fetchMessages(roomIdentifier, additionalChunkSize, void 0, item)
]);
messagesState.current = {
noMessagesBefore: previousChunk.noMessagesBefore,
noMessagesAfter: nextChunk.noMessagesAfter
};
setMessages([...previousChunk.messages, item, ...nextChunk.messages], "beginning");
},
[additionalChunkSize, chatClient, roomIdentifier, setMessages, refresh]
);
const handleSearch = (0, import_react10.useCallback)(
(searchRoomIdentifier, searchResult, focusIndex) => {
if (searchRoomIdentifier === roomIdentifier) {
searchResults.current = searchResult;
focusIndex = Math.min(focusIndex, searchResult.results.length - 1);
selectedSearchResult.current = focusIndex;
focusItem(searchResult.results[focusIndex]);
}
},
[focusItem, roomIdentifier]
);
const handlePreviousSearchResult = (0, import_react10.useCallback)(
(searchRoomIdentifier) => {
if (searchResults.current && searchRoomIdentifier === roomIdentifier) {
selectedSearchResult.current = clamp(
selectedSearchResult.current - 1,
0,
Math.max(searchResults.current.results.length - 1, 0)
);
focusItem(searchResults.current.results[selectedSearchResult.current]);
}
},
[focusItem, roomIdentifier]
);
const handleNextSearchResult = (0, import_react10.useCallback)(
(searchRoomIdentifier) => {
if (searchResults.current && searchRoomIdentifier === roomIdentifier) {
selectedSearchResult.current = clamp(
selectedSearchResult.current + 1,
0,
Math.max(searchResults.current.results.length - 1, 0)
);
focusItem(searchResults.current.results[selectedSearchResult.current]);
}
},
[focusItem, roomIdentifier]
);
(0, import_react10.useEffect)(() => {
chatClient.addEventListener("receiveMessage", handleIncomingMessage);
chatClient.addEventListener("receiveSearchResults", handleSearch);
chatClient.addEventListener("nextSearchResult", handleNextSearchResult);
chatClient.addEventListener("previousSearchResult", handlePreviousSearchResult);
return () => {
chatClient.removeEventListener("receiveMessage", handleIncomingMessage);
chatClient.removeEventListener("receiveSearchResults", handleSearch);
chatClient.removeEventListener("nextSearchResult", handleNextSearchResult);
chatClient.removeEventListener("previousSearchResult", handlePreviousSearchResult);
};
}, [chatClient, handleIncomingMessage, handleNextSearchResult, handlePreviousSearchResult, handleSearch]);
(0, import_react10.useEffect)(() => {
if (!initialSearchResult) {
const container = containerReference.current;
if (container) {
container.scrollTo({ top: container.scrollHeight });
} else {
console.warn(
"RChat: container reference wasn't passed into EndlessList, so scrolling to the bottom after initial chat load failed. This may cause inconsistent behavior"
);
}
}
}, [initialSearchResult]);
(0, import_react10.useEffect)(() => {
setMessages([...initialMessagesState.messages], "beginning");
messagesState.current = initialMessagesState;
}, [initialMessagesState, setMessages]);
(0, import_react10.useEffect)(() => {
searchResults.current = initialSearchResult;
focusedItem.current = initialSearchResult == null ? void 0 : initialSearchResult.results[0];
}, [initialSearchResult]);
const handleTopReached = useEvent(async () => {
if (messagesState.current.noMessagesBefore || isFetching.current) {
return;
}
isFetching.current = true;
const { messages: fetchedMessages, noMessagesBefore } = await chatClient.fetchMessages(
roomIdentifier,
additionalChunkSize,
getMessage(0),
void 0
);
const clipped = unshiftMessages(fetchedMessages);
const newState = {
noMessagesBefore,
noMessagesAfter: !clipped && messagesState.current.noMessagesAfter
};
messagesState.current = newState;
isFetching.current = false;
});
const handleBottomReached = useEvent(async () => {
if (messagesState.current.noMessagesAfter || isFetching.current) {
return;
}
isFetching.current = true;
const { messages: fetchedMessages, noMessagesAfter } = await chatClient.fetchMessages(
roomIdentifier,
additionalChunkSize,
void 0,
getMessage(-1)
);
const clipped = pushMessages(fetchedMessages);
const newState = {
noMessagesAfter,
noMessagesBefore: !clipped && messagesState.current.noMessagesBefore
};
messagesState.current = newState;
isFetching.current = false;
});
const onVisibleFrameChange = /* @__PURE__ */ __name((frame) => {
visibleFrame.current = frame;
}, "onVisibleFrameChange");
return {
messages,
onTopReached: handleTopReached,
onBottomReached: handleBottomReached,
noMessagesBefore: messagesState.current.noMessagesBefore,
noMessagesAfter: messagesState.current.noMessagesAfter,
onVisibleFrameChange,
containerReference,
focusedItem: focusedItem.current
};
}, "useMessages");
// src/MessageList.tsx
var MessageList = /* @__PURE__ */ __name(({
jumpAnimation,
initialMessagesState,
initialSearchResult
}) => {
const {
client,
MessageComponent,
PlaceholderComponent,
ContainerComponent,
triggerDistance,
compareItems,
itemKey
} = (0, import_safe_context3.useSafeContext)(RChatContext);
const { roomIdentifier } = (0, import_safe_context3.useSafeContext)(RoomContext);
const {
messages,
onBottomReached,
onTopReached,
noMessagesAfter,
onVisibleFrameChange,
containerReference,
focusedItem
} = useMessages({
chatClient: client,
additionalChunkSize: 20,
maxChunkSize: 100,
roomIdentifier,
compareItems,
initialMessagesState,
initialSearchResult
});
return /* @__PURE__ */ React.createElement(
EndlessList,
{
initialItems: initialMessagesState.messages,
items: messages,
onTopReached,
onBottomReached,
triggerDistance,
ContainerComponent,
ItemComponent: MessageComponent,
PlaceholderComponent,
compareItems,
itemKey,
onVisibleFrameChange,
canStickToBottom: noMessagesAfter,
containerReference,
focusedItem,
jumpAnimation
}
);
}, "MessageList");
// src/Room.tsx
var Room = /* @__PURE__ */ __name(({ identifier, children }) => {
return /* @__PURE__ */ React.createElement(RoomContext.Provider, { value: { roomIdentifier: identifier } }, children);
}, "Room");
{
"version": 3,
"sources": ["../src/index.ts", "../src/EndlessList/EndlessList.tsx", "../src/internal/mergeReferences.ts", "../src/internal/smoothScrollToCenter.ts", "../src/internal/useEvent.ts", "../src/internal/useScheduleOnNextRender.tsx", "../src/internal/useToggleEvent.ts", "../src/EndlessList/EndlessListItemView.tsx", "../src/EndlessList/useEndlessList.tsx", "../src/internal/binarySearch.ts", "../src/internal/useIdGenerator.ts", "../src/EndlessList/useVisibleFrame.tsx", "../src/EndlessList/useVisibleItems.tsx", "../src/internal/RChatContext.tsx", "../src/Chat.tsx", "../src/MessageList.tsx", "../src/internal/RoomContext.tsx", "../src/useMessages.tsx", "../src/internal/clamp.ts", "../src/internal/useBoundedArray.tsx", "../src/Room.tsx"],
"sourcesContent": ["export * from './EndlessList';\r\nexport * from './Chat';\r\nexport * from './MessageList';\r\nexport * from './Room';\r\nexport * from './useMessages';\r\nexport { type AnimationParameters } from './internal/smoothScrollToCenter';\r\n", "import {\r\n\tComponentType,\r\n\tPropsWithChildren,\r\n\tRef,\r\n\tRefAttributes,\r\n\tuseCallback,\r\n\tuseEffect,\r\n\tuseLayoutEffect,\r\n\tuseMemo,\r\n\tuseRef,\r\n} from 'react';\r\n\r\nimport { mergeReferences } from '../internal/mergeReferences';\r\nimport { AnimationParameters, smoothScrollToCenter } from '../internal/smoothScrollToCenter';\r\nimport { useEvent } from '../internal/useEvent';\r\nimport { useScheduleOnNextRender } from '../internal/useScheduleOnNextRender';\r\nimport { useToggleEvent } from '../internal/useToggleEvent';\r\n\r\nimport { EndlessListItemView } from './EndlessListItemView';\r\nimport { ItemComponentType } from './ItemComponentType';\r\nimport { PlaceholderComponentType } from './PlaceholderComponentType';\r\nimport { useEndlessList } from './useEndlessList';\r\nimport { Frame, useVisibleFrame } from './useVisibleFrame';\r\nimport { useVisibleItems } from './useVisibleItems';\r\nimport type { KeysOfType } from '../internal/KeysOfType';\r\n\r\nexport type ContainerComponentProps = PropsWithChildren<RefAttributes<HTMLElement>>;\r\n\r\nexport type ItemKey<T> = KeysOfType<T, string> | ((value: T) => string);\r\n\r\nexport type EndlessListProps<TItemType> = {\r\n\tItemComponent: ItemComponentType<TItemType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\tContainerComponent: ComponentType<ContainerComponentProps>;\r\n\tinitialItems: TItemType[];\r\n\titems: TItemType[];\r\n\titemKey: ItemKey<TItemType>;\r\n\ttriggerDistance: number;\r\n\tonTopReached?: () => void;\r\n\tonBottomReached?: () => void;\r\n\tcompareItems: (first: TItemType, second: TItemType) => number;\r\n\tfocusedItem?: TItemType;\r\n\tjumpAnimation?: AnimationParameters;\r\n\tcanStickToBottom?: boolean;\r\n\tonVisibleFrameChange?: (frame: Frame) => void;\r\n\tcontainerReference?: Ref<HTMLElement>;\r\n};\r\n\r\nconst noop = () => {\r\n\t/** No operation */\r\n};\r\n\r\nconst defaultAnimationParameters: AnimationParameters = {\r\n\t// Constant duration\r\n\tduration: () => 500,\r\n\t// Linear easing\r\n\teasing: (t) => t,\r\n};\r\n\r\nexport const EndlessList = <T,>({\r\n\tItemComponent,\r\n\tinitialItems,\r\n\titems,\r\n\titemKey,\r\n\ttriggerDistance,\r\n\tonTopReached,\r\n\tonBottomReached,\r\n\tcompareItems,\r\n\tPlaceholderComponent,\r\n\tjumpAnimation = defaultAnimationParameters,\r\n\tfocusedItem,\r\n\tContainerComponent,\r\n\tcanStickToBottom,\r\n\tonVisibleFrameChange,\r\n\tcontainerReference: propsContainerReference,\r\n}: EndlessListProps<T>) => {\r\n\tconst containerReference = useRef<HTMLElement>(null);\r\n\tconst focusElementReference = useRef<HTMLElement>(null);\r\n\tconst stickToBottomReached = useRef(false);\r\n\tconst isScrolling = useRef(false);\r\n\tconst visibleFrame = useRef<Frame>({ begin: -1, end: -1 });\r\n\tconst hasMounted = useRef(false);\r\n\r\n\tconst setBottomReached = useToggleEvent(onBottomReached ?? noop);\r\n\tconst setTopReached = useToggleEvent(onTopReached ?? noop);\r\n\r\n\tconst getKey = useMemo(() => {\r\n\t\treturn typeof itemKey === 'function' ? itemKey : (value: T) => value[itemKey] as unknown as string;\r\n\t}, [itemKey]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsetBottomReached(false);\r\n\t\tsetTopReached(false);\r\n\t}, [items, setBottomReached, setTopReached]);\r\n\r\n\tconst checkBounds = useEvent((frame: Frame = visibleFrame.current) => {\r\n\t\tonVisibleFrameChange?.(frame);\r\n\t\tvisibleFrame.current = frame;\r\n\t\tif (frame.begin === -1 || frame.end === -1 || isScrolling.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tsetBottomReached(frame.end <= triggerDistance);\r\n\t\tsetTopReached(frame.begin <= triggerDistance);\r\n\t\tstickToBottomReached.current = frame.end === 0;\r\n\t});\r\n\r\n\tconst smoothScrolling = useEvent((container: HTMLElement, item: HTMLElement, abortController?: AbortController) => {\r\n\t\treturn smoothScrollToCenter(container, item, jumpAnimation, abortController);\r\n\t});\r\n\r\n\tconst abortControllerReference = useRef<AbortController>();\r\n\tconst handleJumpScroll = useCallback(\r\n\t\tasync (abortController = new AbortController()) => {\r\n\t\t\tif (abortControllerReference.current) {\r\n\t\t\t\tabortControllerReference.current.abort();\r\n\t\t\t}\r\n\r\n\t\t\tif (!containerReference.current || !focusElementReference.current) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tabortControllerReference.current = abortController;\r\n\t\t\tisScrolling.current = true;\r\n\r\n\t\t\tif (hasMounted.current) {\r\n\t\t\t\tawait smoothScrolling(containerReference.current, focusElementReference.current, abortController);\r\n\t\t\t} else {\r\n\t\t\t\tfocusElementReference.current.scrollIntoView({ behavior: 'auto', block: 'center' });\r\n\t\t\t}\r\n\r\n\t\t\tisScrolling.current = false;\r\n\r\n\t\t\tcheckBounds();\r\n\t\t},\r\n\t\t[checkBounds, smoothScrolling],\r\n\t);\r\n\r\n\tconst onVisibleItemsChange = useVisibleFrame({\r\n\t\tgetKey,\r\n\t\titems,\r\n\t\tonVisibleFrameUpdated: checkBounds,\r\n\t});\r\n\tconst { observer, visibleItemKeys } = useVisibleItems(containerReference, onVisibleItemsChange);\r\n\tconst [scheduleJumpScroll, isJumpScheduled] = useScheduleOnNextRender(handleJumpScroll);\r\n\r\n\tconst lastScrolledItem = useRef<T | undefined>();\r\n\tconst handleScrollToFocusItem = useEvent(() => {\r\n\t\tif (focusedItem === lastScrolledItem.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlastScrolledItem.current = focusedItem;\r\n\t\tif (focusedItem && !isJumpScheduled()) {\r\n\t\t\thandleJumpScroll().catch(() => {\r\n\t\t\t\t/* Ignore aborted jump error */\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\n\tconst itemsToRender = useEndlessList({\r\n\t\tgetKey,\r\n\t\tinitialItems,\r\n\t\titems,\r\n\t\tcompareItems,\r\n\t\thandleJump: scheduleJumpScroll,\r\n\t\tfocusedItem,\r\n\t\tvisibleItemKeys,\r\n\t\tlastScrolledItem,\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\thandleScrollToFocusItem();\r\n\t\thasMounted.current = true;\r\n\t}, [handleScrollToFocusItem, itemsToRender]);\r\n\r\n\tuseEffect(() => {\r\n\t\treturn () => {\r\n\t\t\thasMounted.current = false;\r\n\t\t};\r\n\t}, []);\r\n\r\n\tconst handleStickToBottom = useEvent(() => {\r\n\t\tconst container = containerReference.current;\r\n\t\tif (container && stickToBottomReached.current && !focusedItem) {\r\n\t\t\tcontainer.scrollTo({ top: container.scrollHeight });\r\n\t\t}\r\n\t});\r\n\r\n\tuseLayoutEffect(() => {\r\n\t\tif (canStickToBottom) {\r\n\t\t\thandleStickToBottom();\r\n\t\t}\r\n\t}, [itemsToRender, canStickToBottom, handleStickToBottom]);\r\n\r\n\treturn (\r\n\t\t<ContainerComponent ref={mergeReferences(containerReference, propsContainerReference)}>\r\n\t\t\t{itemsToRender.map((item) => (\r\n\t\t\t\t<EndlessListItemView\r\n\t\t\t\t\tkey={item.itemKey}\r\n\t\t\t\t\tfocusElementReference={focusElementReference}\r\n\t\t\t\t\tItemComponent={ItemComponent}\r\n\t\t\t\t\tPlaceholderComponent={PlaceholderComponent}\r\n\t\t\t\t\titemObserver={observer}\r\n\t\t\t\t\t{...item}\r\n\t\t\t\t/>\r\n\t\t\t))}\r\n\t\t</ContainerComponent>\r\n\t);\r\n};\r\n", "import { Ref, MutableRefObject } from 'react';\r\n\r\nexport const mergeReferences = <T>(\r\n\t...inputReferences: Array<Ref<T> | MutableRefObject<T> | undefined | false>\r\n): Ref<T> | undefined => {\r\n\tconst filteredInputReferences = inputReferences.filter(Boolean as unknown as (value: unknown) => value is Ref<T>);\r\n\r\n\tif (filteredInputReferences.length <= 1) {\r\n\t\treturn filteredInputReferences[0];\r\n\t}\r\n\treturn function mergedReferences(reference: T | null) {\r\n\t\tfor (const inputReference of filteredInputReferences) {\r\n\t\t\tif (typeof inputReference === 'function') {\r\n\t\t\t\tinputReference(reference);\r\n\t\t\t} else if (inputReference) {\r\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n\t\t\t\t(inputReference as any).current = reference;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n};\r\n", "export type AnimationParameters = {\r\n\t/**\r\n\t * Easing function.\r\n\t * Takes an argument in range [0, 1] and returns value in range [0, 1].\r\n\t */\r\n\teasing: (t: number) => number;\r\n\r\n\t/**\r\n\t * Animation duration function.\r\n\t * Takes distance in pixels and returns duration in milliseconds.\r\n\t */\r\n\tduration: (distance: number) => number;\r\n};\r\n\r\nexport const smoothScrollToCenter = async (\r\n\tcontainer: HTMLElement,\r\n\telement: HTMLElement,\r\n\tparameters: AnimationParameters,\r\n\tcontroller?: AbortController,\r\n) => {\r\n\tconst elementRect = element.getBoundingClientRect();\r\n\tconst containerRect = container.getBoundingClientRect();\r\n\r\n\tconst top = elementRect.top - containerRect.top - containerRect.height / 2 + elementRect.height / 2;\r\n\r\n\tconst startPos = container.scrollTop;\r\n\tconst clientHeight = container.clientHeight;\r\n\tconst maxScroll = container.scrollHeight - clientHeight;\r\n\tconst scrollIntendedDestination = startPos + top;\r\n\tconst scrollEndValue = Math.min(Math.max(scrollIntendedDestination, 0), maxScroll);\r\n\tlet startTime = 0;\r\n\r\n\tconst duration = parameters.duration(scrollEndValue - startPos);\r\n\r\n\treturn new Promise<void>((resolve, reject) => {\r\n\t\tconst scroll = (timestamp: number) => {\r\n\t\t\tif (controller?.signal.aborted) {\r\n\t\t\t\treject(controller.signal.reason);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tstartTime = startTime || timestamp;\r\n\t\t\tconst elapsed = timestamp - startTime;\r\n\t\t\tcontainer.scrollTop = startPos + (scrollEndValue - startPos) * parameters.easing(elapsed / duration);\r\n\t\t\tif (elapsed <= duration) {\r\n\t\t\t\twindow.requestAnimationFrame(scroll);\r\n\t\t\t} else {\r\n\t\t\t\tresolve();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif (startPos !== scrollEndValue) {\r\n\t\t\twindow.requestAnimationFrame(scroll);\r\n\t\t} else {\r\n\t\t\tresolve();\r\n\t\t}\r\n\t});\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyFunction = (...arguments_: any[]) => any;\r\n\r\nexport const useEvent = <T extends AnyFunction>(handler: T): T => {\r\n\tconst handlerReference = useRef(handler);\r\n\thandlerReference.current = handler;\r\n\r\n\treturn useCallback((...parameters: Parameters<T>): ReturnType<T> => {\r\n\t\treturn handlerReference.current(...parameters);\r\n\t}, []) as T;\r\n};\r\n", "import { useCallback, useLayoutEffect, useRef } from 'react';\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyAsyncFunction = (...arguments_: any[]) => Promise<any>;\r\n\r\nexport const useScheduleOnNextRender = <T extends AnyAsyncFunction>(\r\n\thandler: T,\r\n): [schedule: (...parameters: Parameters<T>) => ReturnType<T>, isScheduled: () => boolean] => {\r\n\ttype PromiseHandle = {\r\n\t\tparameters: Parameters<T>;\r\n\t\tresolve: (value: ReturnType<Awaited<T>>) => void;\r\n\t\treject: (reason: unknown) => void;\r\n\t};\r\n\tconst unresolvedHandle = useRef<PromiseHandle>();\r\n\r\n\tuseLayoutEffect(() => {\r\n\t\tconst currentHandle = unresolvedHandle.current;\r\n\t\tunresolvedHandle.current = undefined;\r\n\t\tif (currentHandle) {\r\n\t\t\thandler(...currentHandle.parameters)\r\n\t\t\t\t.then(currentHandle.resolve)\r\n\t\t\t\t.catch(currentHandle.reject);\r\n\t\t}\r\n\t});\r\n\r\n\tconst wrappedFunction = useCallback((...parameters: Parameters<T>): ReturnType<T> => {\r\n\t\treturn new Promise<Awaited<ReturnType<T>>>((resolve, reject) => {\r\n\t\t\tunresolvedHandle.current = {\r\n\t\t\t\tparameters,\r\n\t\t\t\tresolve,\r\n\t\t\t\treject,\r\n\t\t\t};\r\n\t\t}) as ReturnType<T>;\r\n\t}, []);\r\n\r\n\tconst isScheduled = useCallback(() => {\r\n\t\treturn unresolvedHandle.current !== undefined;\r\n\t}, []);\r\n\r\n\treturn [wrappedFunction, isScheduled];\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\nexport const useToggleEvent = (onTurnedOn: () => void): ((value: boolean) => void) => {\r\n\tconst value = useRef(false);\r\n\r\n\tconst toggle = useCallback(\r\n\t\t(newValue: boolean) => {\r\n\t\t\tif (!value.current && newValue) {\r\n\t\t\t\tonTurnedOn();\r\n\t\t\t}\r\n\r\n\t\t\tvalue.current = newValue;\r\n\t\t},\r\n\t\t[onTurnedOn],\r\n\t);\r\n\r\n\treturn toggle;\r\n};\r\n", "import { RefObject, useEffect, useRef } from 'react';\r\nimport { mergeReferences } from '../internal/mergeReferences';\r\nimport { ItemComponentType } from './ItemComponentType';\r\nimport { PlaceholderComponentType } from './PlaceholderComponentType';\r\nimport type { EndlessListItem } from './useEndlessList';\r\n\r\nexport type EndlessListItemViewProps<TMessageType> = EndlessListItem<TMessageType> & {\r\n\tItemComponent: ItemComponentType<TMessageType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\titemObserver: IntersectionObserver | undefined;\r\n\tfocusElementReference: RefObject<HTMLElement>;\r\n};\r\n\r\nexport const EndlessListItemView = <TMessageType,>({\r\n\tItemComponent,\r\n\tPlaceholderComponent,\r\n\titemObserver,\r\n\tfocusElementReference,\r\n\t...item\r\n}: EndlessListItemViewProps<TMessageType>) => {\r\n\tconst itemReference = useRef<HTMLElement>(null);\r\n\r\n\tuseEffect(() => {\r\n\t\tconst currentElement = itemReference.current;\r\n\t\tif (currentElement && itemObserver) {\r\n\t\t\titemObserver.observe(currentElement);\r\n\r\n\t\t\treturn () => itemObserver.unobserve(currentElement);\r\n\t\t}\r\n\t}, [itemObserver]);\r\n\r\n\tif (item.type === 'placeholder') {\r\n\t\treturn <PlaceholderComponent ref={itemReference} itemKey={item.itemKey} />;\r\n\t}\r\n\r\n\treturn <ItemComponent ref={mergeReferences(itemReference, item.focused && focusElementReference)} {...item} />;\r\n};\r\n", "import { Key, useMemo, useRef, useState, MutableRefObject, useEffect } from 'react';\r\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';\r\nimport { binarySearch } from '../internal/binarySearch';\r\nimport { useEvent } from '../internal/useEvent';\r\nimport { useIdGenerator } from '../internal/useIdGenerator';\r\n\r\nexport type UseEndlessListConfig<T> = {\r\n\tinitialItems: T[];\r\n\titems: T[];\r\n\tgetKey: (item: T) => string;\r\n\tcompareItems: (a: T, b: T) => number;\r\n\thandleJump: (abortController: AbortController) => Promise<void>;\r\n\tfocusedItem?: T;\r\n\tvisibleItemKeys: MutableRefObject<Set<string>>;\r\n\tlastScrolledItem: MutableRefObject<T | undefined>;\r\n};\r\n\r\nexport type EndlessListRealItem<TValue> = {\r\n\ttype: 'real';\r\n\tvalue: TValue;\r\n\tindex: number;\r\n\tarray: TValue[];\r\n\titemKey: string;\r\n\tfocused: boolean;\r\n};\r\n\r\nexport type EndlessListPlaceholderItem = {\r\n\ttype: 'placeholder';\r\n\titemKey: string;\r\n};\r\n\r\nexport type EndlessListItem<TValue> = EndlessListRealItem<TValue> | EndlessListPlaceholderItem;\r\n\r\nconst valueToEndlessListItem = <T,>(getKey: (value: T) => string, focusItemKey: string | undefined) => {\r\n\treturn (value: T, index: number, array: T[]): EndlessListRealItem<T> => {\r\n\t\tconst key = getKey(value);\r\n\r\n\t\treturn {\r\n\t\t\ttype: 'real',\r\n\t\t\tvalue,\r\n\t\t\tindex,\r\n\t\t\tarray,\r\n\t\t\tfocused: key === focusItemKey,\r\n\t\t\titemKey: key,\r\n\t\t};\r\n\t};\r\n};\r\n\r\nexport const useEndlessList = <T,>({\r\n\tinitialItems,\r\n\titems,\r\n\tgetKey,\r\n\tfocusedItem,\r\n\tcompareItems,\r\n\thandleJump,\r\n\tvisibleItemKeys,\r\n\tlastScrolledItem,\r\n}: UseEndlessListConfig<T>): Array<EndlessListItem<T>> => {\r\n\tconst focusedItemKey = focusedItem === undefined ? undefined : getKey(focusedItem);\r\n\tconst defaultConvertItem = useMemo(() => valueToEndlessListItem(getKey, focusedItemKey), [getKey, focusedItemKey]);\r\n\tconst [renderedItems, setRenderedItems] = useState<Array<EndlessListItem<T>>>(() => items.map(defaultConvertItem));\r\n\tconst jumpAbortController = useRef<AbortController>();\r\n\tconst initialItemsReference = useRef(initialItems);\r\n\tconst hasMounted = useRef(false);\r\n\r\n\tconst getUniquePlaceholderKey = useIdGenerator();\r\n\r\n\tconst performFixup = useEvent((): [items: Array<EndlessListItem<T>>, constructItems: boolean] => {\r\n\t\t/**\r\n\t\t * Visible items fixup algorithm.\r\n\t\t *\r\n\t\t * Firstly, take all items, which are displayed on the screen.\r\n\t\t */\r\n\r\n\t\tconst visibleItems = renderedItems\r\n\t\t\t.filter(({ itemKey, type }, index, array) => {\r\n\t\t\t\tif (visibleItemKeys.current.has(itemKey)) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (type === 'placeholder') {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst previousItem = array[index - 1];\r\n\t\t\t\tif (\r\n\t\t\t\t\tpreviousItem &&\r\n\t\t\t\t\tpreviousItem.type !== 'placeholder' &&\r\n\t\t\t\t\tvisibleItemKeys.current.has(previousItem.itemKey)\r\n\t\t\t\t) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst nextItem = array[index + 1];\r\n\t\t\t\tif (nextItem && nextItem.type !== 'placeholder' && visibleItemKeys.current.has(nextItem.itemKey)) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn false;\r\n\t\t\t})\r\n\t\t\t.map((item) => {\r\n\t\t\t\tif (item.type === 'real' && item.focused) {\r\n\t\t\t\t\titem.focused = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn item;\r\n\t\t\t});\r\n\r\n\t\tconst keys = new Set(items.map(getKey));\r\n\t\tif (visibleItems.every((item) => !keys.has(item.itemKey))) {\r\n\t\t\treturn [visibleItems, true];\r\n\t\t}\r\n\r\n\t\tconst comparator = (a: EndlessListRealItem<T>, b: { value: EndlessListItem<T>; index: number }): number => {\r\n\t\t\tif (b.value.type === 'placeholder') {\r\n\t\t\t\tconst nextValue = visibleItems[b.index + 1];\r\n\r\n\t\t\t\tif (nextValue !== undefined && nextValue.type !== 'placeholder') {\r\n\t\t\t\t\treturn compareItems(nextValue.value, a.value);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\r\n\t\t\treturn compareItems(a.value, b.value.value);\r\n\t\t};\r\n\r\n\t\tconst jumpKey = focusedItemKey ?? getKey(items[Math.floor(items.length / 2)]);\r\n\t\tconst convertedItems = [...items.map(valueToEndlessListItem(getKey, jumpKey))];\r\n\r\n\t\tlet pivotIndex = visibleItems.findIndex((item) => keys.has(item.itemKey));\r\n\r\n\t\tif (pivotIndex === -1) {\r\n\t\t\tpivotIndex = binarySearch(visibleItems, convertedItems.at(0)!, comparator);\r\n\t\t}\r\n\t\tvisibleItems.splice(pivotIndex, 1, ...convertedItems);\r\n\r\n\t\tconst dedupedKeys = new Set<Key>();\r\n\t\tconst filteredItems = visibleItems.filter((item) => {\r\n\t\t\tif (dedupedKeys.has(item.itemKey)) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tdedupedKeys.add(item.itemKey);\r\n\t\t\treturn true;\r\n\t\t});\r\n\r\n\t\treturn [filteredItems, false];\r\n\t});\r\n\r\n\tconst update = useEvent(async () => {\r\n\t\tif (jumpAbortController.current) {\r\n\t\t\tjumpAbortController.current.abort();\r\n\t\t\tjumpAbortController.current = undefined;\r\n\t\t}\r\n\r\n\t\tif (renderedItems.length === 0 || items.length === 0 || initialItemsReference.current !== initialItems) {\r\n\t\t\t/**\r\n\t\t\t * There is nothing to do:\r\n\t\t\t * 1. If renderedItems array is empty, it means that there is nothing on the screen - render all items.\r\n\t\t\t * 2. If items array is empty, it means that all items must disappear from the screen.\r\n\t\t\t * \t 3. If initial items has been changed\r\n\t\t\t */\r\n\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t\tinitialItemsReference.current = initialItems;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Determine, if current update call has aborted previous jump.\r\n\t\t */\r\n\t\tconst isAbortedPreviousJump = renderedItems.some((item) => item.type === 'placeholder');\r\n\r\n\t\tlet oldItems: Array<EndlessListItem<T>>;\r\n\t\tlet constructItems = true;\r\n\t\tif (isAbortedPreviousJump) {\r\n\t\t\t/**\r\n\t\t\t * Previous jump was terminated by current state update.\r\n\t\t\t * Must perform one-time fixup.\r\n\t\t\t */\r\n\t\t\t[oldItems, constructItems] = performFixup();\r\n\r\n\t\t\tlet array = [];\r\n\t\t\tlet index = 0;\r\n\t\t\tfor (const item of oldItems) {\r\n\t\t\t\tif (item.type === 'placeholder') {\r\n\t\t\t\t\tindex = 0;\r\n\t\t\t\t\tarray = [];\r\n\t\t\t\t} else {\r\n\t\t\t\t\titem.index = index;\r\n\t\t\t\t\titem.array = array;\r\n\t\t\t\t\tarray.push(item.value);\r\n\t\t\t\t\t++index;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst keys = items.map(getKey);\r\n\t\t\tconst oldKeys = renderedItems.map((item) => item.itemKey);\r\n\r\n\t\t\tconst mustMoveForward = !oldKeys.includes(keys[0]) && !keys.includes(oldKeys.at(-1)!);\r\n\t\t\tconst mustMoveBack = !keys.includes(oldKeys[0]) && !oldKeys.includes(keys.at(-1)!);\r\n\r\n\t\t\tconst mustJump = mustMoveForward && mustMoveBack;\r\n\r\n\t\t\tif (!mustJump) {\r\n\t\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\toldItems = renderedItems.map((item) => {\r\n\t\t\t\tif (item.type === 'real' && item.focused) {\r\n\t\t\t\t\titem.focused = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn item;\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tlet constructedItems: Array<EndlessListItem<T>>;\r\n\t\tif (constructItems) {\r\n\t\t\tconst firstItem = oldItems.find((item): item is EndlessListRealItem<T> => item.type === 'real');\r\n\t\t\tlet jumpDirection = 'forward';\r\n\t\t\tif (firstItem) {\r\n\t\t\t\tjumpDirection = compareItems(items[0], firstItem.value) < 0 ? 'forward' : 'back';\r\n\t\t\t}\r\n\r\n\t\t\tconst jumpKey = focusedItemKey ?? getKey(items[Math.floor(items.length / 2)]);\r\n\r\n\t\t\tlet nextItems: Array<EndlessListItem<T>> | undefined;\r\n\t\t\tlet previousItems: Array<EndlessListItem<T>> | undefined;\r\n\r\n\t\t\tconst convertItem = valueToEndlessListItem(getKey, jumpKey);\r\n\t\t\tif (jumpDirection === 'forward') {\r\n\t\t\t\tnextItems = items.map(convertItem);\r\n\t\t\t\tpreviousItems = oldItems;\r\n\t\t\t} else {\r\n\t\t\t\tnextItems = oldItems;\r\n\t\t\t\tpreviousItems = items.map(convertItem);\r\n\t\t\t}\r\n\r\n\t\t\tconst alreadyHasPlaceholder =\r\n\t\t\t\tnextItems.at(-1)?.type === 'placeholder' || previousItems.at(0)?.type === 'placeholder';\r\n\r\n\t\t\tconstructedItems = [\r\n\t\t\t\t...nextItems,\r\n\t\t\t\t...(alreadyHasPlaceholder\r\n\t\t\t\t\t? []\r\n\t\t\t\t\t: [{ type: 'placeholder' as const, itemKey: getUniquePlaceholderKey() }]),\r\n\t\t\t\t...previousItems,\r\n\t\t\t];\r\n\t\t} else {\r\n\t\t\tconstructedItems = oldItems;\r\n\t\t}\r\n\r\n\t\tlastScrolledItem.current = items[Math.floor(items.length / 2)];\r\n\r\n\t\tsetRenderedItems(constructedItems);\r\n\t\tconst newController = new AbortController();\r\n\t\tjumpAbortController.current = newController;\r\n\r\n\t\ttry {\r\n\t\t\tif (hasMounted.current) {\r\n\t\t\t\tawait handleJump(newController);\r\n\t\t\t}\r\n\r\n\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t} catch {\r\n\t\t\t/* Noop */\r\n\t\t} finally {\r\n\t\t\tjumpAbortController.current = undefined;\r\n\t\t}\r\n\t});\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tupdate();\r\n\t\thasMounted.current = true;\r\n\t}, [update, items]);\r\n\r\n\tuseEffect(() => {\r\n\t\treturn () => {\r\n\t\t\thasMounted.current = false;\r\n\t\t};\r\n\t}, []);\r\n\r\n\treturn renderedItems;\r\n};\r\n", "export const binarySearch = <TItem, TValue extends TItem = TItem>(\r\n\tarray: TItem[],\r\n\tvalue: TValue,\r\n\tcomparator: (a: TValue, b: { value: TItem; index: number }) => number,\r\n): number => {\r\n\tlet low = 0;\r\n\tlet high = array.length;\r\n\r\n\tif (high === 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\twhile (low < high) {\r\n\t\tconst middle = Math.floor((low + high) / 2);\r\n\r\n\t\tif (comparator(value, { value: array[middle], index: middle }) > 0) {\r\n\t\t\tlow = middle + 1;\r\n\t\t} else {\r\n\t\t\thigh = middle;\r\n\t\t}\r\n\t}\r\n\r\n\treturn high;\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\nexport const useIdGenerator = (): (() => string) => {\r\n\tconst counter = useRef(0);\r\n\r\n\treturn useCallback(() => `:rchat:-${++counter.current}`, []);\r\n};\r\n", "import { useEvent } from '../internal/useEvent';\r\n\r\nexport type UseVisibleFrameConfig<TValue> = {\r\n\titems: TValue[];\r\n\tgetKey: (item: TValue) => string;\r\n\tonVisibleFrameUpdated: (frame: Frame) => void;\r\n};\r\n\r\nexport type Frame = {\r\n\tbegin: number;\r\n\tend: number;\r\n};\r\n\r\nexport const useVisibleFrame = <TValue,>({\r\n\titems,\r\n\tgetKey,\r\n\tonVisibleFrameUpdated,\r\n}: UseVisibleFrameConfig<TValue>): ((keys: Set<string>) => void) => {\r\n\tconst updateVisibleFrame = useEvent((visibleItemKeys: Set<string>) => {\r\n\t\tlet begin = -1;\r\n\t\tfor (const [index, item] of items.entries()) {\r\n\t\t\tif (visibleItemKeys.has(getKey(item))) {\r\n\t\t\t\tbegin = index;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet end = -1;\r\n\t\tfor (let index = 0; index <= items.length; ++index) {\r\n\t\t\tconst item = items.at(-index - 1);\r\n\t\t\tif (item && visibleItemKeys.has(getKey(item))) {\r\n\t\t\t\tend = index;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tonVisibleFrameUpdated({ begin, end });\r\n\t});\r\n\r\n\treturn updateVisibleFrame;\r\n};\r\n", "import { RefObject, useEffect, useState, MutableRefObject, useRef } from 'react';\r\nimport { useEvent } from '../internal/useEvent';\r\n\r\nexport type VisibleItemsBag = {\r\n\tobserver: IntersectionObserver | undefined;\r\n\tvisibleItemKeys: MutableRefObject<Set<string>>;\r\n};\r\n\r\nexport const useVisibleItems = (\r\n\tcontainerReference: RefObject<HTMLElement>,\r\n\tonVisibleItemsChange?: (items: Set<string>) => void,\r\n): VisibleItemsBag => {\r\n\tconst [observer, setObserver] = useState<IntersectionObserver>();\r\n\tconst visibleItemKeysReference = useRef(new Set<string>());\r\n\r\n\tconst updateVisibleFrame = useEvent((entries: IntersectionObserverEntry[]) => {\r\n\t\tfor (const { target, isIntersecting } of entries) {\r\n\t\t\tconst key = (target as HTMLElement).dataset.key;\r\n\r\n\t\t\tif (!key) {\r\n\t\t\t\t// eslint-disable-next-line no-console\r\n\t\t\t\tconsole.warn('Item component doesn\\'t have \"data-key\" attribute.');\r\n\t\t\t} else if (isIntersecting) {\r\n\t\t\t\tvisibleItemKeysReference.current.add(key);\r\n\t\t\t} else {\r\n\t\t\t\tvisibleItemKeysReference.current.delete(key);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tonVisibleItemsChange?.(visibleItemKeysReference.current);\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\tconst containerElement = containerReference.current;\r\n\t\tif (containerElement) {\r\n\t\t\tconst observer = new IntersectionObserver(updateVisibleFrame, { root: containerElement, threshold: 0 });\r\n\r\n\t\t\tsetObserver(observer);\r\n\t\t}\r\n\t}, [containerReference, updateVisibleFrame]);\r\n\r\n\treturn { observer, visibleItemKeys: visibleItemKeysReference };\r\n};\r\n", "import { ChatClient } from '@rchat/client';\r\nimport { createSafeContext } from '@sirse-dev/safe-context';\r\nimport type { ContainerComponentProps, ItemComponentType, ItemKey, PlaceholderComponentType } from '../EndlessList';\r\nimport type { ComponentType } from 'react';\r\n\r\nexport type RChatContextType<TMessageType> = {\r\n\tclient: ChatClient<TMessageType>;\r\n\tMessageComponent: ItemComponentType<TMessageType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\tContainerComponent: ComponentType<ContainerComponentProps>;\r\n\ttriggerDistance: number;\r\n\titemKey: ItemKey<TMessageType>;\r\n\tcompareItems: (first: TMessageType, second: TMessageType) => number;\r\n};\r\n\r\nexport const RChatContext = createSafeContext<RChatContextType<unknown>>();\r\n", "import { PropsWithChildren } from 'react';\r\n\r\nimport { RChatContext, RChatContextType } from './internal/RChatContext';\r\n\r\nexport type ChatProps<TMessageType> = PropsWithChildren<RChatContextType<TMessageType>>;\r\n\r\nexport const Chat = <TMessageType,>({ children, ...context }: ChatProps<TMessageType>) => (\r\n\t<RChatContext.Provider value={{ ...(context as RChatContextType<unknown>) }}>{children}</RChatContext.Provider>\r\n);\r\n", "import { MessageFetchResult, MessageSearchResult } from '@rchat/client';\r\nimport { useSafeContext } from '@sirse-dev/safe-context';\r\nimport { EndlessList } from './EndlessList';\r\nimport { RChatContext } from './internal/RChatContext';\r\nimport { RoomContext } from './internal/RoomContext';\r\nimport { AnimationParameters } from './internal/smoothScrollToCenter';\r\nimport { useMessages } from './useMessages';\r\n\r\nexport type MessageListProps<TMessage> = {\r\n\tinitialMessagesState: MessageFetchResult<TMessage>;\r\n\tinitialSearchResult?: MessageSearchResult<TMessage>;\r\n\tjumpAnimation?: AnimationParameters;\r\n};\r\n\r\nexport const MessageList = <TMessage,>({\r\n\tjumpAnimation,\r\n\tinitialMessagesState,\r\n\tinitialSearchResult,\r\n}: MessageListProps<TMessage>) => {\r\n\tconst {\r\n\t\tclient,\r\n\t\tMessageComponent,\r\n\t\tPlaceholderComponent,\r\n\t\tContainerComponent,\r\n\t\ttriggerDistance,\r\n\t\tcompareItems,\r\n\t\titemKey,\r\n\t} = useSafeContext(RChatContext);\r\n\tconst { roomIdentifier } = useSafeContext(RoomContext);\r\n\r\n\tconst {\r\n\t\tmessages,\r\n\t\tonBottomReached,\r\n\t\tonTopReached,\r\n\t\tnoMessagesAfter,\r\n\t\tonVisibleFrameChange,\r\n\t\tcontainerReference,\r\n\t\tfocusedItem,\r\n\t} = useMessages({\r\n\t\tchatClient: client,\r\n\t\tadditionalChunkSize: 20,\r\n\t\tmaxChunkSize: 100,\r\n\t\troomIdentifier,\r\n\t\tcompareItems,\r\n\t\tinitialMessagesState,\r\n\t\tinitialSearchResult,\r\n\t});\r\n\r\n\treturn (\r\n\t\t<EndlessList\r\n\t\t\tinitialItems={initialMessagesState.messages}\r\n\t\t\titems={messages}\r\n\t\t\tonTopReached={onTopReached}\r\n\t\t\tonBottomReached={onBottomReached}\r\n\t\t\ttriggerDistance={triggerDistance}\r\n\t\t\tContainerComponent={ContainerComponent}\r\n\t\t\tItemComponent={MessageComponent}\r\n\t\t\tPlaceholderComponent={PlaceholderComponent}\r\n\t\t\tcompareItems={compareItems}\r\n\t\t\titemKey={itemKey}\r\n\t\t\tonVisibleFrameChange={onVisibleFrameChange}\r\n\t\t\tcanStickToBottom={noMessagesAfter}\r\n\t\t\tcontainerReference={containerReference}\r\n\t\t\tfocusedItem={focusedItem}\r\n\t\t\tjumpAnimation={jumpAnimation}\r\n\t\t/>\r\n\t);\r\n};\r\n", "import { createSafeContext } from '@sirse-dev/safe-context';\r\n\r\nexport type RoomContextType = {\r\n\troomIdentifier: string;\r\n};\r\n\r\nexport const RoomContext = createSafeContext<RoomContextType>();\r\n", "import { MessageFetchResult, MessageSearchResult } from '@rchat/client';\r\nimport { ChatClient } from '@rchat/client';\r\nimport { Ref, useCallback, useEffect, useRef } from 'react';\r\nimport { Frame } from './EndlessList/useVisibleFrame';\r\nimport { clamp } from './internal/clamp';\r\nimport { KeepDirection, useBoundedArray } from './internal/useBoundedArray';\r\nimport { useEvent } from './internal/useEvent';\r\n\r\nexport type UseMessagesBag<T> = {\r\n\tmessages: T[];\r\n\tonTopReached: () => void;\r\n\tonBottomReached: () => void;\r\n\tnoMessagesBefore: boolean;\r\n\tnoMessagesAfter: boolean;\r\n\tonVisibleFrameChange: (frame: Frame) => void;\r\n\tcontainerReference: Ref<HTMLElement>;\r\n\tfocusedItem?: T;\r\n};\r\n\r\nexport type UseMessagesConfig<T> = {\r\n\tinitialMessagesState: MessageFetchResult<T>;\r\n\tinitialSearchResult?: MessageSearchResult<T>;\r\n\tcompareItems: (a: T, b: T) => number;\r\n\tmaxChunkSize: number;\r\n\tadditionalChunkSize: number;\r\n\tchatClient: ChatClient<T>;\r\n\troomIdentifier: string;\r\n};\r\n\r\n// TODO: replace with binary search\r\nconst findNewElementIndex = <T,>(elements: readonly T[], element: T, compare: (a: T, b: T) => number): number => {\r\n\treturn (\r\n\t\telements.length -\r\n\t\t1 -\r\n\t\t[...elements].reverse().findIndex((a) => {\r\n\t\t\treturn compare(element, a) > 0;\r\n\t\t})\r\n\t);\r\n};\r\n\r\nexport const useMessages = <TMessage,>({\r\n\tmaxChunkSize,\r\n\tadditionalChunkSize,\r\n\tchatClient,\r\n\troomIdentifier,\r\n\tcompareItems,\r\n\tinitialMessagesState,\r\n\tinitialSearchResult,\r\n}: UseMessagesConfig<TMessage>): UseMessagesBag<TMessage> => {\r\n\tconst isFetching = useRef(false);\r\n\tconst visibleFrame = useRef<Frame>({ begin: -1, end: -1 });\r\n\tconst containerReference = useRef<HTMLElement>(null);\r\n\tconst searchResults = useRef<MessageSearchResult<TMessage> | undefined>(initialSearchResult);\r\n\tconst selectedSearchResult = useRef(0);\r\n\tconst focusedItem = useRef<TMessage | undefined>(initialSearchResult?.results[0]);\r\n\r\n\tconst [\r\n\t\tmessages,\r\n\t\t{\r\n\t\t\tpush: pushMessages,\r\n\t\t\tunshift: unshiftMessages,\r\n\t\t\tset: setMessages,\r\n\t\t\tinsert: insertMessage,\r\n\t\t\tat: getMessage,\r\n\t\t\tgetAll: getAllMessages,\r\n\t\t\trefresh,\r\n\t\t},\r\n\t] = useBoundedArray<TMessage>([...initialMessagesState.messages], maxChunkSize);\r\n\r\n\tconst messagesState = useRef<Omit<MessageFetchResult<TMessage>, 'messages'>>(initialMessagesState);\r\n\r\n\tconst handleIncomingMessage = useCallback(\r\n\t\t(message: TMessage, messageRoomIdentifier: string) => {\r\n\t\t\tif (messageRoomIdentifier === roomIdentifier && messagesState.current.noMessagesAfter) {\r\n\t\t\t\tconst incomingMessageIndex = findNewElementIndex(getAllMessages(), message, compareItems);\r\n\r\n\t\t\t\tconst keepDirection: KeepDirection =\r\n\t\t\t\t\tvisibleFrame.current.begin < visibleFrame.current.end ? 'beginning' : 'ending';\r\n\r\n\t\t\t\tconst clipped = insertMessage(message, incomingMessageIndex + 1, keepDirection);\r\n\r\n\t\t\t\tif (clipped) {\r\n\t\t\t\t\tif (keepDirection === 'beginning') {\r\n\t\t\t\t\t\tmessagesState.current.noMessagesAfter = false;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tmessagesState.current.noMessagesBefore = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t[roomIdentifier, getAllMessages, compareItems, insertMessage],\r\n\t);\r\n\r\n\tconst focusItem = useCallback(\r\n\t\tasync (item: TMessage | undefined) => {\r\n\t\t\tif (!item) {\r\n\t\t\t\tif (focusedItem.current) {\r\n\t\t\t\t\trefresh();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfocusedItem.current = item;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tfocusedItem.current = item;\r\n\r\n\t\t\tconst [previousChunk, nextChunk] = await Promise.all([\r\n\t\t\t\tchatClient.fetchMessages(roomIdentifier, additionalChunkSize, item, undefined),\r\n\t\t\t\tchatClient.fetchMessages(roomIdentifier, additionalChunkSize, undefined, item),\r\n\t\t\t]);\r\n\r\n\t\t\tmessagesState.current = {\r\n\t\t\t\tnoMessagesBefore: previousChunk.noMessagesBefore,\r\n\t\t\t\tnoMessagesAfter: nextChunk.noMessagesAfter,\r\n\t\t\t};\r\n\r\n\t\t\tsetMessages([...previousChunk.messages, item, ...nextChunk.messages], 'beginning');\r\n\t\t},\r\n\t\t[additionalChunkSize, chatClient, roomIdentifier, setMessages, refresh],\r\n\t);\r\n\r\n\tconst handleSearch = useCallback(\r\n\t\t(searchRoomIdentifier: string, searchResult: MessageSearchResult<TMessage>, focusIndex: number) => {\r\n\t\t\tif (searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tsearchResults.current = searchResult;\r\n\t\t\t\tfocusIndex = Math.min(focusIndex, searchResult.results.length - 1);\r\n\t\t\t\tselectedSearchResult.current = focusIndex;\r\n\t\t\t\tfocusItem(searchResult.results[focusIndex]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tconst handlePreviousSearchResult = useCallback(\r\n\t\t(searchRoomIdentifier: string) => {\r\n\t\t\tif (searchResults.current && searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tselectedSearchResult.current = clamp(\r\n\t\t\t\t\tselectedSearchResult.current - 1,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tMath.max(searchResults.current.results.length - 1, 0),\r\n\t\t\t\t);\r\n\t\t\t\tfocusItem(searchResults.current.results[selectedSearchResult.current]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tconst handleNextSearchResult = useCallback(\r\n\t\t(searchRoomIdentifier: string) => {\r\n\t\t\tif (searchResults.current && searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tselectedSearchResult.current = clamp(\r\n\t\t\t\t\tselectedSearchResult.current + 1,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tMath.max(searchResults.current.results.length - 1, 0),\r\n\t\t\t\t);\r\n\t\t\t\tfocusItem(searchResults.current.results[selectedSearchResult.current]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tuseEffect(() => {\r\n\t\tchatClient.addEventListener('receiveMessage', handleIncomingMessage);\r\n\t\tchatClient.addEventListener('receiveSearchResults', handleSearch);\r\n\t\tchatClient.addEventListener('nextSearchResult', handleNextSearchResult);\r\n\t\tchatClient.addEventListener('previousSearchResult', handlePreviousSearchResult);\r\n\r\n\t\treturn () => {\r\n\t\t\tchatClient.removeEventListener('receiveMessage', handleIncomingMessage);\r\n\t\t\tchatClient.removeEventListener('receiveSearchResults', handleSearch);\r\n\t\t\tchatClient.removeEventListener('nextSearchResult', handleNextSearchResult);\r\n\t\t\tchatClient.removeEventListener('previousSearchResult', handlePreviousSearchResult);\r\n\t\t};\r\n\t}, [chatClient, handleIncomingMessage, handleNextSearchResult, handlePreviousSearchResult, handleSearch]);\r\n\r\n\t// Scroll to bottom if there was no initial search\r\n\tuseEffect(() => {\r\n\t\tif (!initialSearchResult) {\r\n\t\t\tconst container = containerReference.current;\r\n\t\t\tif (container) {\r\n\t\t\t\tcontainer.scrollTo({ top: container.scrollHeight });\r\n\t\t\t} else {\r\n\t\t\t\t// eslint-disable-next-line no-console\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\"RChat: container reference wasn't passed into EndlessList,\" +\r\n\t\t\t\t\t\t' so scrolling to the bottom after initial chat load failed.' +\r\n\t\t\t\t\t\t' This may cause inconsistent behavior',\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t}, [initialSearchResult]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsetMessages([...initialMessagesState.messages], 'beginning');\r\n\t\tmessagesState.current = initialMessagesState;\r\n\t}, [initialMessagesState, setMessages]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsearchResults.current = initialSearchResult;\r\n\t\tfocusedItem.current = initialSearchResult?.results[0];\r\n\t}, [initialSearchResult]);\r\n\r\n\tconst handleTopReached = useEvent(async () => {\r\n\t\tif (messagesState.current.noMessagesBefore || isFetching.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tisFetching.current = true;\r\n\t\tconst { messages: fetchedMessages, noMessagesBefore } = await chatClient.fetchMessages(\r\n\t\t\troomIdentifier,\r\n\t\t\tadditionalChunkSize,\r\n\t\t\tgetMessage(0),\r\n\t\t\tundefined,\r\n\t\t);\r\n\r\n\t\tconst clipped = unshiftMessages(fetchedMessages);\r\n\r\n\t\tconst newState = {\r\n\t\t\tnoMessagesBefore,\r\n\t\t\tnoMessagesAfter: !clipped && messagesState.current.noMessagesAfter,\r\n\t\t};\r\n\t\tmessagesState.current = newState;\r\n\t\tisFetching.current = false;\r\n\t});\r\n\r\n\tconst handleBottomReached = useEvent(async () => {\r\n\t\tif (messagesState.current.noMessagesAfter || isFetching.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tisFetching.current = true;\r\n\t\tconst { messages: fetchedMessages, noMessagesAfter } = await chatClient.fetchMessages(\r\n\t\t\troomIdentifier,\r\n\t\t\tadditionalChunkSize,\r\n\t\t\tundefined,\r\n\t\t\tgetMessage(-1),\r\n\t\t);\r\n\r\n\t\tconst clipped = pushMessages(fetchedMessages);\r\n\t\tconst newState = {\r\n\t\t\tnoMessagesAfter,\r\n\t\t\tnoMessagesBefore: !clipped && messagesState.current.noMessagesBefore,\r\n\t\t};\r\n\r\n\t\tmessagesState.current = newState;\r\n\t\tisFetching.current = false;\r\n\t});\r\n\r\n\tconst onVisibleFrameChange = (frame: Frame) => {\r\n\t\tvisibleFrame.current = frame;\r\n\t};\r\n\r\n\treturn {\r\n\t\tmessages,\r\n\t\tonTopReached: handleTopReached,\r\n\t\tonBottomReached: handleBottomReached,\r\n\t\tnoMessagesBefore: messagesState.current.noMessagesBefore,\r\n\t\tnoMessagesAfter: messagesState.current.noMessagesAfter,\r\n\t\tonVisibleFrameChange,\r\n\t\tcontainerReference,\r\n\t\tfocusedItem: focusedItem.current,\r\n\t};\r\n};\r\n", "export const clamp = (value: number, min: number, max: number) => Math.max(Math.min(value, max), min);\r\n", "import { useCallback, useRef, useState } from 'react';\r\n\r\nexport type KeepDirection = 'beginning' | 'ending';\r\n\r\nexport type BoundedArrayControl<T> = {\r\n\t/**\r\n\t * Add elements to the end of the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Ensures, that last item won't be clipped.\r\n\t */\r\n\tpush: (items: T[]) => boolean;\r\n\t/**\r\n\t * Add elements to the beginning of the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Ensures, that first item won't be clipped.\r\n\t */\r\n\tunshift: (items: T[]) => boolean;\r\n\t/**\r\n\t * Set all elements to the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Keeps elements according to \"keep\" argument's value:\r\n\t * beginning - array will be clipped from the end.\r\n\t * ending - array will be clipped from the beginning.\r\n\t */\r\n\tset: (items: T[], keep: KeepDirection) => boolean;\r\n\r\n\tinsert: (item: T, index: number, keep: KeepDirection) => boolean;\r\n\t/**\r\n\t * Works exactly like \"Array.prototype.at\".\r\n\t */\r\n\tat: (index: number) => T | undefined;\r\n\t/**\r\n\t * Returns reference to current array.\r\n\t */\r\n\tgetAll: () => readonly T[];\r\n\t/**\r\n\t * Sets state to the old one in order to rerender.\r\n\t */\r\n\trefresh: () => void;\r\n};\r\n\r\nconst getClippedArray = <T,>(items: T[], maxSize: number, keep: KeepDirection) => {\r\n\tif (items.length <= maxSize) {\r\n\t\treturn items;\r\n\t}\r\n\r\n\tif (keep === 'beginning') {\r\n\t\treturn items.slice(0, maxSize);\r\n\t}\r\n\r\n\tif (keep === 'ending') {\r\n\t\treturn items.slice(-maxSize);\r\n\t}\r\n\r\n\tthrow new Error(`Unrecognized \"keep\" option value: \"${keep}\"`);\r\n};\r\n\r\nexport const useBoundedArray = <T,>(\r\n\tinitial: T[],\r\n\tmaxChunkSize: number,\r\n): [items: T[], control: BoundedArrayControl<T>] => {\r\n\tconst [itemsState, setItemsState] = useState(initial);\r\n\tconst itemsReference = useRef(initial);\r\n\r\n\tconst setItems = useCallback(\r\n\t\t(items: T[], keep: KeepDirection) => {\r\n\t\t\tconst clippedItems = getClippedArray(items, maxChunkSize, keep);\r\n\t\t\tsetItemsState(clippedItems);\r\n\t\t\titemsReference.current = clippedItems;\r\n\r\n\t\t\treturn items.length > clippedItems.length;\r\n\t\t},\r\n\t\t[maxChunkSize],\r\n\t);\r\n\r\n\tconst unshift = useCallback(\r\n\t\t(items: T[]) => {\r\n\t\t\treturn setItems([...items, ...itemsReference.current], 'beginning');\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst push = useCallback(\r\n\t\t(items: T[]) => {\r\n\t\t\treturn setItems([...itemsReference.current, ...items], 'ending');\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst at = useCallback((index: number) => {\r\n\t\treturn itemsReference.current.at(index);\r\n\t}, []);\r\n\r\n\tconst insert = useCallback(\r\n\t\t(item: T, index: number, keep: KeepDirection) => {\r\n\t\t\titemsReference.current.splice(index, 0, item);\r\n\t\t\treturn setItems([...itemsReference.current], keep);\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst getAll = useCallback(() => itemsReference.current, []);\r\n\r\n\tconst refresh = useCallback(() => setItemsState((old) => [...old]), []);\r\n\r\n\treturn [itemsState, { push, unshift, set: setItems, at, getAll, insert, refresh }];\r\n};\r\n", "import { PropsWithChildren } from 'react';\r\nimport { RoomContext } from './internal/RoomContext';\r\n\r\nexport type RoomProps = PropsWithChildren<{\r\n\tidentifier: string;\r\n}>;\r\n\r\nexport const Room = ({ identifier, children }: RoomProps) => {\r\n\treturn <RoomContext.Provider value={{ roomIdentifier: identifier }}>{children}</RoomContext.Provider>;\r\n};\r\n"],
"mappings": "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",
"names": ["import_react", "import_react", "import_react", "import_react", "import_react", "import_react", "useIsomorphicLayoutEffect", "import_react", "observer", "import_safe_context", "import_safe_context", "import_react", "import_react"]
}
import React from 'react';
var Ae=Object.create;var J=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames,q=Object.getOwnPropertySymbols,Fe=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty,fe=Object.prototype.propertyIsEnumerable;var pe=(t,e,r)=>e in t?J(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,W=(t,e)=>{for(var r in e||(e={}))re.call(e,r)&&pe(t,r,e[r]);if(q)for(var r of q(e))fe.call(e,r)&&pe(t,r,e[r]);return t};var o=(t,e)=>J(t,"name",{value:e,configurable:!0});var G=(t,e)=>{var r={};for(var n in t)re.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&q)for(var n of q(t))e.indexOf(n)<0&&fe.call(t,n)&&(r[n]=t[n]);return r};var Se=(t,e)=>{for(var r in e)J(t,r,{get:e[r],enumerable:!0})},de=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of we(e))!re.call(t,s)&&s!==r&&J(t,s,{get:()=>e[s],enumerable:!(n=Le(e,s))||n.enumerable});return t};var ke=(t,e,r)=>(r=t!=null?Ae(Fe(t)):{},de(e||!t||!t.__esModule?J(r,"default",{value:t,enumerable:!0}):r,t)),Ke=t=>de(J({},"__esModule",{value:!0}),t);var Ue={};Se(Ue,{Chat:()=>Be,EndlessList:()=>ce,MessageList:()=>je,Room:()=>De,useEndlessList:()=>oe,useMessages:()=>ie,useVisibleItems:()=>ae});module.exports=Ke(Ue);var R=require("react");var _=o((...t)=>{let e=t.filter(Boolean);return e.length<=1?e[0]:o(function(n){for(let s of e)typeof s=="function"?s(n):s&&(s.current=n)},"mergedReferences")},"mergeReferences");var Te=o(async(t,e,r,n)=>{let s=e.getBoundingClientRect(),a=t.getBoundingClientRect(),u=s.top-a.top-a.height/2+s.height/2,l=t.scrollTop,p=t.clientHeight,b=t.scrollHeight-p,f=l+u,T=Math.min(Math.max(f,0),b),m=0,I=r.duration(T-l);return new Promise((x,S)=>{let A=o(k=>{if(n!=null&&n.signal.aborted){S(n.signal.reason);return}m=m||k;let M=k-m;t.scrollTop=l+(T-l)*r.easing(M/I),M<=I?window.requestAnimationFrame(A):x()},"scroll");l!==T?window.requestAnimationFrame(A):x()})},"smoothScrollToCenter");var $=require("react");var F=o(t=>{let e=(0,$.useRef)(t);return e.current=t,(0,$.useCallback)((...r)=>e.current(...r),[])},"useEvent");var U=require("react");var ge=o(t=>{let e=(0,U.useRef)();(0,U.useLayoutEffect)(()=>{let s=e.current;e.current=void 0,s&&t(...s.parameters).then(s.resolve).catch(s.reject)});let r=(0,U.useCallback)((...s)=>new Promise((a,u)=>{e.current={parameters:s,resolve:a,reject:u}}),[]),n=(0,U.useCallback)(()=>e.current!==void 0,[]);return[r,n]},"useScheduleOnNextRender");var Q=require("react");var ne=o(t=>{let e=(0,Q.useRef)(!1);return(0,Q.useCallback)(n=>{!e.current&&n&&t(),e.current=n},[t])},"useToggleEvent");var X=require("react");var ye=o(a=>{var u=a,{ItemComponent:t,PlaceholderComponent:e,itemObserver:r,focusElementReference:n}=u,s=G(u,["ItemComponent","PlaceholderComponent","itemObserver","focusElementReference"]);let l=(0,X.useRef)(null);return(0,X.useEffect)(()=>{let p=l.current;if(p&&r)return r.observe(p),()=>r.unobserve(p)},[r]),s.type==="placeholder"?React.createElement(e,{ref:l,itemKey:s.itemKey}):React.createElement(t,W({ref:_(l,s.focused&&n)},s))},"EndlessListItemView");var D=require("react"),Me=ke(require("use-isomorphic-layout-effect"));var he=o((t,e,r)=>{let n=0,s=t.length;if(s===0)return 0;for(;n<s;){let a=Math.floor((n+s)/2);r(e,{value:t[a],index:a})>0?n=a+1:s=a}return s},"binarySearch");var Y=require("react");var be=o(()=>{let t=(0,Y.useRef)(0);return(0,Y.useCallback)(()=>`:rchat:-${++t.current}`,[])},"useIdGenerator");var se=o((t,e)=>(r,n,s)=>{let a=t(r);return{type:"real",value:r,index:n,array:s,focused:a===e,itemKey:a}},"valueToEndlessListItem"),oe=o(({initialItems:t,items:e,getKey:r,focusedItem:n,compareItems:s,handleJump:a,visibleItemKeys:u,lastScrolledItem:l})=>{let p=n===void 0?void 0:r(n),b=(0,D.useMemo)(()=>se(r,p),[r,p]),[f,T]=(0,D.useState)(()=>e.map(b)),m=(0,D.useRef)(),I=(0,D.useRef)(t),x=(0,D.useRef)(!1),S=be(),A=F(()=>{let M=f.filter(({itemKey:i,type:C},E,B)=>{if(u.current.has(i))return!0;if(C==="placeholder")return!1;let c=B[E-1];if(c&&c.type!=="placeholder"&&u.current.has(c.itemKey))return!0;let h=B[E+1];return!!(h&&h.type!=="placeholder"&&u.current.has(h.itemKey))}).map(i=>(i.type==="real"&&i.focused&&(i.focused=!1),i)),L=new Set(e.map(r));if(M.every(i=>!L.has(i.itemKey)))return[M,!0];let O=o((i,C)=>{if(C.value.type==="placeholder"){let E=M[C.index+1];return E!==void 0&&E.type!=="placeholder"?s(E.value,i.value):1}return s(i.value,C.value.value)},"comparator"),d=p!=null?p:r(e[Math.floor(e.length/2)]),K=[...e.map(se(r,d))],w=M.findIndex(i=>L.has(i.itemKey));w===-1&&(w=he(M,K.at(0),O)),M.splice(w,1,...K);let V=new Set;return[M.filter(i=>V.has(i.itemKey)?!1:(V.add(i.itemKey),!0)),!1]}),k=F(async()=>{var w,V;if(m.current&&(m.current.abort(),m.current=void 0),f.length===0||e.length===0||I.current!==t){T(e.map(b)),I.current=t;return}let M=f.some(g=>g.type==="placeholder"),L,O=!0;if(M){[L,O]=A();let g=[],i=0;for(let C of L)C.type==="placeholder"?(i=0,g=[]):(C.index=i,C.array=g,g.push(C.value),++i)}else{let g=e.map(r),i=f.map(c=>c.itemKey),C=!i.includes(g[0])&&!g.includes(i.at(-1)),E=!g.includes(i[0])&&!i.includes(g.at(-1));if(!(C&&E)){T(e.map(b));return}L=f.map(c=>(c.type==="real"&&c.focused&&(c.focused=!1),c))}let d;if(O){let g=L.find(P=>P.type==="real"),i="forward";g&&(i=s(e[0],g.value)<0?"forward":"back");let C=p!=null?p:r(e[Math.floor(e.length/2)]),E,B,c=se(r,C);i==="forward"?(E=e.map(c),B=L):(E=L,B=e.map(c));let h=((w=E.at(-1))==null?void 0:w.type)==="placeholder"||((V=B.at(0))==null?void 0:V.type)==="placeholder";d=[...E,...h?[]:[{type:"placeholder",itemKey:S()}],...B]}else d=L;l.current=e[Math.floor(e.length/2)],T(d);let K=new AbortController;m.current=K;try{x.current&&await a(K),T(e.map(b))}catch(g){}finally{m.current=void 0}});return(0,Me.default)(()=>{k(),x.current=!0},[k,e]),(0,D.useEffect)(()=>()=>{x.current=!1},[]),f},"useEndlessList");var Ce=o(({items:t,getKey:e,onVisibleFrameUpdated:r})=>F(s=>{let a=-1;for(let[l,p]of t.entries())if(s.has(e(p))){a=l;break}let u=-1;for(let l=0;l<=t.length;++l){let p=t.at(-l-1);if(p&&s.has(e(p))){u=l;break}}r({begin:a,end:u})}),"useVisibleFrame");var N=require("react");var ae=o((t,e)=>{let[r,n]=(0,N.useState)(),s=(0,N.useRef)(new Set),a=F(u=>{for(let{target:l,isIntersecting:p}of u){let b=l.dataset.key;b?p?s.current.add(b):s.current.delete(b):console.warn(`Item component doesn't have "data-key" attribute.`)}e==null||e(s.current)});return(0,N.useEffect)(()=>{let u=t.current;if(u){let l=new IntersectionObserver(a,{root:u,threshold:0});n(l)}},[t,a]),{observer:r,visibleItemKeys:s}},"useVisibleItems");var Re=o(()=>{},"noop"),Ve={duration:()=>500,easing:t=>t},ce=o(({ItemComponent:t,initialItems:e,items:r,itemKey:n,triggerDistance:s,onTopReached:a,onBottomReached:u,compareItems:l,PlaceholderComponent:p,jumpAnimation:b=Ve,focusedItem:f,ContainerComponent:T,canStickToBottom:m,onVisibleFrameChange:I,containerReference:x})=>{let S=(0,R.useRef)(null),A=(0,R.useRef)(null),k=(0,R.useRef)(!1),M=(0,R.useRef)(!1),L=(0,R.useRef)({begin:-1,end:-1}),O=(0,R.useRef)(!1),d=ne(u!=null?u:Re),K=ne(a!=null?a:Re),w=(0,R.useMemo)(()=>typeof n=="function"?n:y=>y[n],[n]);(0,R.useEffect)(()=>{d(!1),K(!1)},[r,d,K]);let V=F((y=L.current)=>{I==null||I(y),L.current=y,!(y.begin===-1||y.end===-1||M.current)&&(d(y.end<=s),K(y.begin<=s),k.current=y.end===0)}),g=F((y,Ee,Pe)=>Te(y,Ee,b,Pe)),i=(0,R.useRef)(),C=(0,R.useCallback)(async(y=new AbortController)=>{i.current&&i.current.abort(),!(!S.current||!A.current)&&(i.current=y,M.current=!0,O.current?await g(S.current,A.current,y):A.current.scrollIntoView({behavior:"auto",block:"center"}),M.current=!1,V())},[V,g]),E=Ce({getKey:w,items:r,onVisibleFrameUpdated:V}),{observer:B,visibleItemKeys:c}=ae(S,E),[h,P]=ge(C),j=(0,R.useRef)(),ee=F(()=>{f!==j.current&&(j.current=f,f&&!P()&&C().catch(()=>{}))}),te=oe({getKey:w,initialItems:e,items:r,compareItems:l,handleJump:h,focusedItem:f,visibleItemKeys:c,lastScrolledItem:j});(0,R.useEffect)(()=>{ee(),O.current=!0},[ee,te]),(0,R.useEffect)(()=>()=>{O.current=!1},[]);let me=F(()=>{let y=S.current;y&&k.current&&!f&&y.scrollTo({top:y.scrollHeight})});return(0,R.useLayoutEffect)(()=>{m&&me()},[te,m,me]),React.createElement(T,{ref:_(S,x)},te.map(y=>React.createElement(ye,W({key:y.itemKey,focusElementReference:A,ItemComponent:t,PlaceholderComponent:p,itemObserver:B},y))))},"EndlessList");var ve=require("@sirse-dev/safe-context"),Z=(0,ve.createSafeContext)();var Be=o(r=>{var n=r,{children:t}=n,e=G(n,["children"]);return React.createElement(Z.Provider,{value:W({},e)},t)},"Chat");var le=require("@sirse-dev/safe-context");var xe=require("@sirse-dev/safe-context"),z=(0,xe.createSafeContext)();var v=require("react");var ue=o((t,e,r)=>Math.max(Math.min(t,r),e),"clamp");var H=require("react");var He=o((t,e,r)=>{if(t.length<=e)return t;if(r==="beginning")return t.slice(0,e);if(r==="ending")return t.slice(-e);throw new Error(`Unrecognized "keep" option value: "${r}"`)},"getClippedArray"),Ie=o((t,e)=>{let[r,n]=(0,H.useState)(t),s=(0,H.useRef)(t),a=(0,H.useCallback)((m,I)=>{let x=He(m,e,I);return n(x),s.current=x,m.length>x.length},[e]),u=(0,H.useCallback)(m=>a([...m,...s.current],"beginning"),[a]),l=(0,H.useCallback)(m=>a([...s.current,...m],"ending"),[a]),p=(0,H.useCallback)(m=>s.current.at(m),[]),b=(0,H.useCallback)((m,I,x)=>(s.current.splice(I,0,m),a([...s.current],x)),[a]),f=(0,H.useCallback)(()=>s.current,[]),T=(0,H.useCallback)(()=>n(m=>[...m]),[]);return[r,{push:l,unshift:u,set:a,at:p,getAll:f,insert:b,refresh:T}]},"useBoundedArray");var Oe=o((t,e,r)=>t.length-1-[...t].reverse().findIndex(n=>r(e,n)>0),"findNewElementIndex"),ie=o(({maxChunkSize:t,additionalChunkSize:e,chatClient:r,roomIdentifier:n,compareItems:s,initialMessagesState:a,initialSearchResult:u})=>{let l=(0,v.useRef)(!1),p=(0,v.useRef)({begin:-1,end:-1}),b=(0,v.useRef)(null),f=(0,v.useRef)(u),T=(0,v.useRef)(0),m=(0,v.useRef)(u==null?void 0:u.results[0]),[I,{push:x,unshift:S,set:A,insert:k,at:M,getAll:L,refresh:O}]=Ie([...a.messages],t),d=(0,v.useRef)(a),K=(0,v.useCallback)((c,h)=>{if(h===n&&d.current.noMessagesAfter){let P=Oe(L(),c,s),j=p.current.begin<p.current.end?"beginning":"ending";k(c,P+1,j)&&(j==="beginning"?d.current.noMessagesAfter=!1:d.current.noMessagesBefore=!1)}},[n,L,s,k]),w=(0,v.useCallback)(async c=>{if(!c){m.current&&O(),m.current=c;return}m.current=c;let[h,P]=await Promise.all([r.fetchMessages(n,e,c,void 0),r.fetchMessages(n,e,void 0,c)]);d.current={noMessagesBefore:h.noMessagesBefore,noMessagesAfter:P.noMessagesAfter},A([...h.messages,c,...P.messages],"beginning")},[e,r,n,A,O]),V=(0,v.useCallback)((c,h,P)=>{c===n&&(f.current=h,P=Math.min(P,h.results.length-1),T.current=P,w(h.results[P]))},[w,n]),g=(0,v.useCallback)(c=>{f.current&&c===n&&(T.current=ue(T.current-1,0,Math.max(f.current.results.length-1,0)),w(f.current.results[T.current]))},[w,n]),i=(0,v.useCallback)(c=>{f.current&&c===n&&(T.current=ue(T.current+1,0,Math.max(f.current.results.length-1,0)),w(f.current.results[T.current]))},[w,n]);(0,v.useEffect)(()=>(r.addEventListener("receiveMessage",K),r.addEventListener("receiveSearchResults",V),r.addEventListener("nextSearchResult",i),r.addEventListener("previousSearchResult",g),()=>{r.removeEventListener("receiveMessage",K),r.removeEventListener("receiveSearchResults",V),r.removeEventListener("nextSearchResult",i),r.removeEventListener("previousSearchResult",g)}),[r,K,i,g,V]),(0,v.useEffect)(()=>{if(!u){let c=b.current;c?c.scrollTo({top:c.scrollHeight}):console.warn("RChat: container reference wasn't passed into EndlessList, so scrolling to the bottom after initial chat load failed. This may cause inconsistent behavior")}},[u]),(0,v.useEffect)(()=>{A([...a.messages],"beginning"),d.current=a},[a,A]),(0,v.useEffect)(()=>{f.current=u,m.current=u==null?void 0:u.results[0]},[u]);let C=F(async()=>{if(d.current.noMessagesBefore||l.current)return;l.current=!0;let{messages:c,noMessagesBefore:h}=await r.fetchMessages(n,e,M(0),void 0),P=S(c),j={noMessagesBefore:h,noMessagesAfter:!P&&d.current.noMessagesAfter};d.current=j,l.current=!1}),E=F(async()=>{if(d.current.noMessagesAfter||l.current)return;l.current=!0;let{messages:c,noMessagesAfter:h}=await r.fetchMessages(n,e,void 0,M(-1)),P=x(c),j={noMessagesAfter:h,noMessagesBefore:!P&&d.current.noMessagesBefore};d.current=j,l.current=!1}),B=o(c=>{p.current=c},"onVisibleFrameChange");return{messages:I,onTopReached:C,onBottomReached:E,noMessagesBefore:d.current.noMessagesBefore,noMessagesAfter:d.current.noMessagesAfter,onVisibleFrameChange:B,containerReference:b,focusedItem:m.current}},"useMessages");var je=o(({jumpAnimation:t,initialMessagesState:e,initialSearchResult:r})=>{let{client:n,MessageComponent:s,PlaceholderComponent:a,ContainerComponent:u,triggerDistance:l,compareItems:p,itemKey:b}=(0,le.useSafeContext)(Z),{roomIdentifier:f}=(0,le.useSafeContext)(z),{messages:T,onBottomReached:m,onTopReached:I,noMessagesAfter:x,onVisibleFrameChange:S,containerReference:A,focusedItem:k}=ie({chatClient:n,additionalChunkSize:20,maxChunkSize:100,roomIdentifier:f,compareItems:p,initialMessagesState:e,initialSearchResult:r});return React.createElement(ce,{initialItems:e.messages,items:T,onTopReached:I,onBottomReached:m,triggerDistance:l,ContainerComponent:u,ItemComponent:s,PlaceholderComponent:a,compareItems:p,itemKey:b,onVisibleFrameChange:S,canStickToBottom:x,containerReference:A,focusedItem:k,jumpAnimation:t})},"MessageList");var De=o(({identifier:t,children:e})=>React.createElement(z.Provider,{value:{roomIdentifier:t}},e),"Room");

Sorry, the diff of this file is too big to display

// Generated by dts-bundle-generator v6.13.0
import { ComponentType, MutableRefObject, PropsWithChildren, Ref, RefAttributes, RefObject } from 'react';
export type AnimationParameters = {
/**
* Easing function.
* Takes an argument in range [0, 1] and returns value in range [0, 1].
*/
easing: (t: number) => number;
/**
* Animation duration function.
* Takes distance in pixels and returns duration in milliseconds.
*/
duration: (distance: number) => number;
};
export type UseEndlessListConfig<T> = {
initialItems: T[];
items: T[];
getKey: (item: T) => string;
compareItems: (a: T, b: T) => number;
handleJump: (abortController: AbortController) => Promise<void>;
focusedItem?: T;
visibleItemKeys: MutableRefObject<Set<string>>;
lastScrolledItem: MutableRefObject<T | undefined>;
};
export type EndlessListRealItem<TValue> = {
type: "real";
value: TValue;
index: number;
array: TValue[];
itemKey: string;
focused: boolean;
};
export type EndlessListPlaceholderItem = {
type: "placeholder";
itemKey: string;
};
export type EndlessListItem<TValue> = EndlessListRealItem<TValue> | EndlessListPlaceholderItem;
export declare const useEndlessList: <T>({ initialItems, items, getKey, focusedItem, compareItems, handleJump, visibleItemKeys, lastScrolledItem, }: UseEndlessListConfig<T>) => EndlessListItem<T>[];
export type ItemComponentProps<TMessageType> = Omit<EndlessListRealItem<TMessageType>, "type">;
export type ItemComponentType<TMessageType> = ComponentType<ItemComponentProps<TMessageType> & RefAttributes<HTMLElement>>;
export type PlaceholderComponentProps = {
itemKey: string;
};
export type PlaceholderComponentType = ComponentType<PlaceholderComponentProps & RefAttributes<HTMLElement>>;
export type Frame = {
begin: number;
end: number;
};
export type KeysOfType<T, V> = {
[K in keyof T]: T[K] extends V ? K : never;
}[keyof T];
export type ContainerComponentProps = PropsWithChildren<RefAttributes<HTMLElement>>;
export type ItemKey<T> = KeysOfType<T, string> | ((value: T) => string);
export type EndlessListProps<TItemType> = {
ItemComponent: ItemComponentType<TItemType>;
PlaceholderComponent: PlaceholderComponentType;
ContainerComponent: ComponentType<ContainerComponentProps>;
initialItems: TItemType[];
items: TItemType[];
itemKey: ItemKey<TItemType>;
triggerDistance: number;
onTopReached?: () => void;
onBottomReached?: () => void;
compareItems: (first: TItemType, second: TItemType) => number;
focusedItem?: TItemType;
jumpAnimation?: AnimationParameters;
canStickToBottom?: boolean;
onVisibleFrameChange?: (frame: Frame) => void;
containerReference?: Ref<HTMLElement>;
};
export declare const EndlessList: <T>({ ItemComponent, initialItems, items, itemKey, triggerDistance, onTopReached, onBottomReached, compareItems, PlaceholderComponent, jumpAnimation, focusedItem, ContainerComponent, canStickToBottom, onVisibleFrameChange, containerReference: propsContainerReference, }: EndlessListProps<T>) => import("react/jsx-runtime").JSX.Element;
export type VisibleItemsBag = {
observer: IntersectionObserver | undefined;
visibleItemKeys: MutableRefObject<Set<string>>;
};
export declare const useVisibleItems: (containerReference: RefObject<HTMLElement>, onVisibleItemsChange?: ((items: Set<string>) => void) | undefined) => VisibleItemsBag;
export type RChatContextType<TMessageType> = {
client: ChatClient<TMessageType>;
MessageComponent: ItemComponentType<TMessageType>;
PlaceholderComponent: PlaceholderComponentType;
ContainerComponent: ComponentType<ContainerComponentProps>;
triggerDistance: number;
itemKey: ItemKey<TMessageType>;
compareItems: (first: TMessageType, second: TMessageType) => number;
};
export type ChatProps<TMessageType> = PropsWithChildren<RChatContextType<TMessageType>>;
export declare const Chat: <TMessageType>({ children, ...context }: ChatProps<TMessageType>) => import("react/jsx-runtime").JSX.Element;
export type MessageListProps<TMessage> = {
initialMessagesState: MessageFetchResult<TMessage>;
initialSearchResult?: MessageSearchResult<TMessage>;
jumpAnimation?: AnimationParameters;
};
export declare const MessageList: <TMessage>({ jumpAnimation, initialMessagesState, initialSearchResult, }: MessageListProps<TMessage>) => import("react/jsx-runtime").JSX.Element;
export type RoomProps = PropsWithChildren<{
identifier: string;
}>;
export declare const Room: ({ identifier, children }: RoomProps) => import("react/jsx-runtime").JSX.Element;
export type UseMessagesBag<T> = {
messages: T[];
onTopReached: () => void;
onBottomReached: () => void;
noMessagesBefore: boolean;
noMessagesAfter: boolean;
onVisibleFrameChange: (frame: Frame) => void;
containerReference: Ref<HTMLElement>;
focusedItem?: T;
};
export type UseMessagesConfig<T> = {
initialMessagesState: MessageFetchResult<T>;
initialSearchResult?: MessageSearchResult<T>;
compareItems: (a: T, b: T) => number;
maxChunkSize: number;
additionalChunkSize: number;
chatClient: ChatClient<T>;
roomIdentifier: string;
};
export declare const useMessages: <TMessage>({ maxChunkSize, additionalChunkSize, chatClient, roomIdentifier, compareItems, initialMessagesState, initialSearchResult, }: UseMessagesConfig<TMessage>) => UseMessagesBag<TMessage>;
export {};
import React from 'react';
var __defProp = Object.defineProperty;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/EndlessList/EndlessList.tsx
import {
useCallback as useCallback5,
useEffect as useEffect4,
useLayoutEffect as useLayoutEffect2,
useMemo as useMemo2,
useRef as useRef8
} from "react";
// src/internal/mergeReferences.ts
var mergeReferences = /* @__PURE__ */ __name((...inputReferences) => {
const filteredInputReferences = inputReferences.filter(Boolean);
if (filteredInputReferences.length <= 1) {
return filteredInputReferences[0];
}
return /* @__PURE__ */ __name(function mergedReferences(reference) {
for (const inputReference of filteredInputReferences) {
if (typeof inputReference === "function") {
inputReference(reference);
} else if (inputReference) {
inputReference.current = reference;
}
}
}, "mergedReferences");
}, "mergeReferences");
// src/internal/smoothScrollToCenter.ts
var smoothScrollToCenter = /* @__PURE__ */ __name(async (container, element, parameters, controller) => {
const elementRect = element.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
const top = elementRect.top - containerRect.top - containerRect.height / 2 + elementRect.height / 2;
const startPos = container.scrollTop;
const clientHeight = container.clientHeight;
const maxScroll = container.scrollHeight - clientHeight;
const scrollIntendedDestination = startPos + top;
const scrollEndValue = Math.min(Math.max(scrollIntendedDestination, 0), maxScroll);
let startTime = 0;
const duration = parameters.duration(scrollEndValue - startPos);
return new Promise((resolve, reject) => {
const scroll = /* @__PURE__ */ __name((timestamp) => {
if (controller == null ? void 0 : controller.signal.aborted) {
reject(controller.signal.reason);
return;
}
startTime = startTime || timestamp;
const elapsed = timestamp - startTime;
container.scrollTop = startPos + (scrollEndValue - startPos) * parameters.easing(elapsed / duration);
if (elapsed <= duration) {
window.requestAnimationFrame(scroll);
} else {
resolve();
}
}, "scroll");
if (startPos !== scrollEndValue) {
window.requestAnimationFrame(scroll);
} else {
resolve();
}
});
}, "smoothScrollToCenter");
// src/internal/useEvent.ts
import { useCallback, useRef } from "react";
var useEvent = /* @__PURE__ */ __name((handler) => {
const handlerReference = useRef(handler);
handlerReference.current = handler;
return useCallback((...parameters) => {
return handlerReference.current(...parameters);
}, []);
}, "useEvent");
// src/internal/useScheduleOnNextRender.tsx
import { useCallback as useCallback2, useLayoutEffect, useRef as useRef2 } from "react";
var useScheduleOnNextRender = /* @__PURE__ */ __name((handler) => {
const unresolvedHandle = useRef2();
useLayoutEffect(() => {
const currentHandle = unresolvedHandle.current;
unresolvedHandle.current = void 0;
if (currentHandle) {
handler(...currentHandle.parameters).then(currentHandle.resolve).catch(currentHandle.reject);
}
});
const wrappedFunction = useCallback2((...parameters) => {
return new Promise((resolve, reject) => {
unresolvedHandle.current = {
parameters,
resolve,
reject
};
});
}, []);
const isScheduled = useCallback2(() => {
return unresolvedHandle.current !== void 0;
}, []);
return [wrappedFunction, isScheduled];
}, "useScheduleOnNextRender");
// src/internal/useToggleEvent.ts
import { useCallback as useCallback3, useRef as useRef3 } from "react";
var useToggleEvent = /* @__PURE__ */ __name((onTurnedOn) => {
const value = useRef3(false);
const toggle = useCallback3(
(newValue) => {
if (!value.current && newValue) {
onTurnedOn();
}
value.current = newValue;
},
[onTurnedOn]
);
return toggle;
}, "useToggleEvent");
// src/EndlessList/EndlessListItemView.tsx
import { useEffect, useRef as useRef4 } from "react";
var EndlessListItemView = /* @__PURE__ */ __name((_a) => {
var _b = _a, {
ItemComponent,
PlaceholderComponent,
itemObserver,
focusElementReference
} = _b, item = __objRest(_b, [
"ItemComponent",
"PlaceholderComponent",
"itemObserver",
"focusElementReference"
]);
const itemReference = useRef4(null);
useEffect(() => {
const currentElement = itemReference.current;
if (currentElement && itemObserver) {
itemObserver.observe(currentElement);
return () => itemObserver.unobserve(currentElement);
}
}, [itemObserver]);
if (item.type === "placeholder") {
return /* @__PURE__ */ React.createElement(PlaceholderComponent, { ref: itemReference, itemKey: item.itemKey });
}
return /* @__PURE__ */ React.createElement(ItemComponent, __spreadValues({ ref: mergeReferences(itemReference, item.focused && focusElementReference) }, item));
}, "EndlessListItemView");
// src/EndlessList/useEndlessList.tsx
import { useMemo, useRef as useRef6, useState, useEffect as useEffect2 } from "react";
import useIsomorphicLayoutEffect from "use-isomorphic-layout-effect";
// src/internal/binarySearch.ts
var binarySearch = /* @__PURE__ */ __name((array, value, comparator) => {
let low = 0;
let high = array.length;
if (high === 0) {
return 0;
}
while (low < high) {
const middle = Math.floor((low + high) / 2);
if (comparator(value, { value: array[middle], index: middle }) > 0) {
low = middle + 1;
} else {
high = middle;
}
}
return high;
}, "binarySearch");
// src/internal/useIdGenerator.ts
import { useCallback as useCallback4, useRef as useRef5 } from "react";
var useIdGenerator = /* @__PURE__ */ __name(() => {
const counter = useRef5(0);
return useCallback4(() => `:rchat:-${++counter.current}`, []);
}, "useIdGenerator");
// src/EndlessList/useEndlessList.tsx
var valueToEndlessListItem = /* @__PURE__ */ __name((getKey, focusItemKey) => {
return (value, index, array) => {
const key = getKey(value);
return {
type: "real",
value,
index,
array,
focused: key === focusItemKey,
itemKey: key
};
};
}, "valueToEndlessListItem");
var useEndlessList = /* @__PURE__ */ __name(({
initialItems,
items,
getKey,
focusedItem,
compareItems,
handleJump,
visibleItemKeys,
lastScrolledItem
}) => {
const focusedItemKey = focusedItem === void 0 ? void 0 : getKey(focusedItem);
const defaultConvertItem = useMemo(() => valueToEndlessListItem(getKey, focusedItemKey), [getKey, focusedItemKey]);
const [renderedItems, setRenderedItems] = useState(() => items.map(defaultConvertItem));
const jumpAbortController = useRef6();
const initialItemsReference = useRef6(initialItems);
const hasMounted = useRef6(false);
const getUniquePlaceholderKey = useIdGenerator();
const performFixup = useEvent(() => {
const visibleItems = renderedItems.filter(({ itemKey, type }, index, array) => {
if (visibleItemKeys.current.has(itemKey)) {
return true;
}
if (type === "placeholder") {
return false;
}
const previousItem = array[index - 1];
if (previousItem && previousItem.type !== "placeholder" && visibleItemKeys.current.has(previousItem.itemKey)) {
return true;
}
const nextItem = array[index + 1];
if (nextItem && nextItem.type !== "placeholder" && visibleItemKeys.current.has(nextItem.itemKey)) {
return true;
}
return false;
}).map((item) => {
if (item.type === "real" && item.focused) {
item.focused = false;
}
return item;
});
const keys = new Set(items.map(getKey));
if (visibleItems.every((item) => !keys.has(item.itemKey))) {
return [visibleItems, true];
}
const comparator = /* @__PURE__ */ __name((a, b) => {
if (b.value.type === "placeholder") {
const nextValue = visibleItems[b.index + 1];
if (nextValue !== void 0 && nextValue.type !== "placeholder") {
return compareItems(nextValue.value, a.value);
}
return 1;
}
return compareItems(a.value, b.value.value);
}, "comparator");
const jumpKey = focusedItemKey != null ? focusedItemKey : getKey(items[Math.floor(items.length / 2)]);
const convertedItems = [...items.map(valueToEndlessListItem(getKey, jumpKey))];
let pivotIndex = visibleItems.findIndex((item) => keys.has(item.itemKey));
if (pivotIndex === -1) {
pivotIndex = binarySearch(visibleItems, convertedItems.at(0), comparator);
}
visibleItems.splice(pivotIndex, 1, ...convertedItems);
const dedupedKeys = /* @__PURE__ */ new Set();
const filteredItems = visibleItems.filter((item) => {
if (dedupedKeys.has(item.itemKey)) {
return false;
}
dedupedKeys.add(item.itemKey);
return true;
});
return [filteredItems, false];
});
const update = useEvent(async () => {
var _a, _b;
if (jumpAbortController.current) {
jumpAbortController.current.abort();
jumpAbortController.current = void 0;
}
if (renderedItems.length === 0 || items.length === 0 || initialItemsReference.current !== initialItems) {
setRenderedItems(items.map(defaultConvertItem));
initialItemsReference.current = initialItems;
return;
}
const isAbortedPreviousJump = renderedItems.some((item) => item.type === "placeholder");
let oldItems;
let constructItems = true;
if (isAbortedPreviousJump) {
[oldItems, constructItems] = performFixup();
let array = [];
let index = 0;
for (const item of oldItems) {
if (item.type === "placeholder") {
index = 0;
array = [];
} else {
item.index = index;
item.array = array;
array.push(item.value);
++index;
}
}
} else {
const keys = items.map(getKey);
const oldKeys = renderedItems.map((item) => item.itemKey);
const mustMoveForward = !oldKeys.includes(keys[0]) && !keys.includes(oldKeys.at(-1));
const mustMoveBack = !keys.includes(oldKeys[0]) && !oldKeys.includes(keys.at(-1));
const mustJump = mustMoveForward && mustMoveBack;
if (!mustJump) {
setRenderedItems(items.map(defaultConvertItem));
return;
}
oldItems = renderedItems.map((item) => {
if (item.type === "real" && item.focused) {
item.focused = false;
}
return item;
});
}
let constructedItems;
if (constructItems) {
const firstItem = oldItems.find((item) => item.type === "real");
let jumpDirection = "forward";
if (firstItem) {
jumpDirection = compareItems(items[0], firstItem.value) < 0 ? "forward" : "back";
}
const jumpKey = focusedItemKey != null ? focusedItemKey : getKey(items[Math.floor(items.length / 2)]);
let nextItems;
let previousItems;
const convertItem = valueToEndlessListItem(getKey, jumpKey);
if (jumpDirection === "forward") {
nextItems = items.map(convertItem);
previousItems = oldItems;
} else {
nextItems = oldItems;
previousItems = items.map(convertItem);
}
const alreadyHasPlaceholder = ((_a = nextItems.at(-1)) == null ? void 0 : _a.type) === "placeholder" || ((_b = previousItems.at(0)) == null ? void 0 : _b.type) === "placeholder";
constructedItems = [
...nextItems,
...alreadyHasPlaceholder ? [] : [{ type: "placeholder", itemKey: getUniquePlaceholderKey() }],
...previousItems
];
} else {
constructedItems = oldItems;
}
lastScrolledItem.current = items[Math.floor(items.length / 2)];
setRenderedItems(constructedItems);
const newController = new AbortController();
jumpAbortController.current = newController;
try {
if (hasMounted.current) {
await handleJump(newController);
}
setRenderedItems(items.map(defaultConvertItem));
} catch (e) {
} finally {
jumpAbortController.current = void 0;
}
});
useIsomorphicLayoutEffect(() => {
update();
hasMounted.current = true;
}, [update, items]);
useEffect2(() => {
return () => {
hasMounted.current = false;
};
}, []);
return renderedItems;
}, "useEndlessList");
// src/EndlessList/useVisibleFrame.tsx
var useVisibleFrame = /* @__PURE__ */ __name(({
items,
getKey,
onVisibleFrameUpdated
}) => {
const updateVisibleFrame = useEvent((visibleItemKeys) => {
let begin = -1;
for (const [index, item] of items.entries()) {
if (visibleItemKeys.has(getKey(item))) {
begin = index;
break;
}
}
let end = -1;
for (let index = 0; index <= items.length; ++index) {
const item = items.at(-index - 1);
if (item && visibleItemKeys.has(getKey(item))) {
end = index;
break;
}
}
onVisibleFrameUpdated({ begin, end });
});
return updateVisibleFrame;
}, "useVisibleFrame");
// src/EndlessList/useVisibleItems.tsx
import { useEffect as useEffect3, useState as useState2, useRef as useRef7 } from "react";
var useVisibleItems = /* @__PURE__ */ __name((containerReference, onVisibleItemsChange) => {
const [observer, setObserver] = useState2();
const visibleItemKeysReference = useRef7(/* @__PURE__ */ new Set());
const updateVisibleFrame = useEvent((entries) => {
for (const { target, isIntersecting } of entries) {
const key = target.dataset.key;
if (!key) {
console.warn(`Item component doesn't have "data-key" attribute.`);
} else if (isIntersecting) {
visibleItemKeysReference.current.add(key);
} else {
visibleItemKeysReference.current.delete(key);
}
}
onVisibleItemsChange == null ? void 0 : onVisibleItemsChange(visibleItemKeysReference.current);
});
useEffect3(() => {
const containerElement = containerReference.current;
if (containerElement) {
const observer2 = new IntersectionObserver(updateVisibleFrame, { root: containerElement, threshold: 0 });
setObserver(observer2);
}
}, [containerReference, updateVisibleFrame]);
return { observer, visibleItemKeys: visibleItemKeysReference };
}, "useVisibleItems");
// src/EndlessList/EndlessList.tsx
var noop = /* @__PURE__ */ __name(() => {
}, "noop");
var defaultAnimationParameters = {
duration: () => 500,
easing: (t) => t
};
var EndlessList = /* @__PURE__ */ __name(({
ItemComponent,
initialItems,
items,
itemKey,
triggerDistance,
onTopReached,
onBottomReached,
compareItems,
PlaceholderComponent,
jumpAnimation = defaultAnimationParameters,
focusedItem,
ContainerComponent,
canStickToBottom,
onVisibleFrameChange,
containerReference: propsContainerReference
}) => {
const containerReference = useRef8(null);
const focusElementReference = useRef8(null);
const stickToBottomReached = useRef8(false);
const isScrolling = useRef8(false);
const visibleFrame = useRef8({ begin: -1, end: -1 });
const hasMounted = useRef8(false);
const setBottomReached = useToggleEvent(onBottomReached != null ? onBottomReached : noop);
const setTopReached = useToggleEvent(onTopReached != null ? onTopReached : noop);
const getKey = useMemo2(() => {
return typeof itemKey === "function" ? itemKey : (value) => value[itemKey];
}, [itemKey]);
useEffect4(() => {
setBottomReached(false);
setTopReached(false);
}, [items, setBottomReached, setTopReached]);
const checkBounds = useEvent((frame = visibleFrame.current) => {
onVisibleFrameChange == null ? void 0 : onVisibleFrameChange(frame);
visibleFrame.current = frame;
if (frame.begin === -1 || frame.end === -1 || isScrolling.current) {
return;
}
setBottomReached(frame.end <= triggerDistance);
setTopReached(frame.begin <= triggerDistance);
stickToBottomReached.current = frame.end === 0;
});
const smoothScrolling = useEvent((container, item, abortController) => {
return smoothScrollToCenter(container, item, jumpAnimation, abortController);
});
const abortControllerReference = useRef8();
const handleJumpScroll = useCallback5(
async (abortController = new AbortController()) => {
if (abortControllerReference.current) {
abortControllerReference.current.abort();
}
if (!containerReference.current || !focusElementReference.current) {
return;
}
abortControllerReference.current = abortController;
isScrolling.current = true;
if (hasMounted.current) {
await smoothScrolling(containerReference.current, focusElementReference.current, abortController);
} else {
focusElementReference.current.scrollIntoView({ behavior: "auto", block: "center" });
}
isScrolling.current = false;
checkBounds();
},
[checkBounds, smoothScrolling]
);
const onVisibleItemsChange = useVisibleFrame({
getKey,
items,
onVisibleFrameUpdated: checkBounds
});
const { observer, visibleItemKeys } = useVisibleItems(containerReference, onVisibleItemsChange);
const [scheduleJumpScroll, isJumpScheduled] = useScheduleOnNextRender(handleJumpScroll);
const lastScrolledItem = useRef8();
const handleScrollToFocusItem = useEvent(() => {
if (focusedItem === lastScrolledItem.current) {
return;
}
lastScrolledItem.current = focusedItem;
if (focusedItem && !isJumpScheduled()) {
handleJumpScroll().catch(() => {
});
}
});
const itemsToRender = useEndlessList({
getKey,
initialItems,
items,
compareItems,
handleJump: scheduleJumpScroll,
focusedItem,
visibleItemKeys,
lastScrolledItem
});
useEffect4(() => {
handleScrollToFocusItem();
hasMounted.current = true;
}, [handleScrollToFocusItem, itemsToRender]);
useEffect4(() => {
return () => {
hasMounted.current = false;
};
}, []);
const handleStickToBottom = useEvent(() => {
const container = containerReference.current;
if (container && stickToBottomReached.current && !focusedItem) {
container.scrollTo({ top: container.scrollHeight });
}
});
useLayoutEffect2(() => {
if (canStickToBottom) {
handleStickToBottom();
}
}, [itemsToRender, canStickToBottom, handleStickToBottom]);
return /* @__PURE__ */ React.createElement(ContainerComponent, { ref: mergeReferences(containerReference, propsContainerReference) }, itemsToRender.map((item) => /* @__PURE__ */ React.createElement(
EndlessListItemView,
__spreadValues({
key: item.itemKey,
focusElementReference,
ItemComponent,
PlaceholderComponent,
itemObserver: observer
}, item)
)));
}, "EndlessList");
// src/internal/RChatContext.tsx
import { createSafeContext } from "@sirse-dev/safe-context";
var RChatContext = createSafeContext();
// src/Chat.tsx
var Chat = /* @__PURE__ */ __name((_a) => {
var _b = _a, { children } = _b, context = __objRest(_b, ["children"]);
return /* @__PURE__ */ React.createElement(RChatContext.Provider, { value: __spreadValues({}, context) }, children);
}, "Chat");
// src/MessageList.tsx
import { useSafeContext } from "@sirse-dev/safe-context";
// src/internal/RoomContext.tsx
import { createSafeContext as createSafeContext2 } from "@sirse-dev/safe-context";
var RoomContext = createSafeContext2();
// src/useMessages.tsx
import { useCallback as useCallback7, useEffect as useEffect5, useRef as useRef10 } from "react";
// src/internal/clamp.ts
var clamp = /* @__PURE__ */ __name((value, min, max) => Math.max(Math.min(value, max), min), "clamp");
// src/internal/useBoundedArray.tsx
import { useCallback as useCallback6, useRef as useRef9, useState as useState3 } from "react";
var getClippedArray = /* @__PURE__ */ __name((items, maxSize, keep) => {
if (items.length <= maxSize) {
return items;
}
if (keep === "beginning") {
return items.slice(0, maxSize);
}
if (keep === "ending") {
return items.slice(-maxSize);
}
throw new Error(`Unrecognized "keep" option value: "${keep}"`);
}, "getClippedArray");
var useBoundedArray = /* @__PURE__ */ __name((initial, maxChunkSize) => {
const [itemsState, setItemsState] = useState3(initial);
const itemsReference = useRef9(initial);
const setItems = useCallback6(
(items, keep) => {
const clippedItems = getClippedArray(items, maxChunkSize, keep);
setItemsState(clippedItems);
itemsReference.current = clippedItems;
return items.length > clippedItems.length;
},
[maxChunkSize]
);
const unshift = useCallback6(
(items) => {
return setItems([...items, ...itemsReference.current], "beginning");
},
[setItems]
);
const push = useCallback6(
(items) => {
return setItems([...itemsReference.current, ...items], "ending");
},
[setItems]
);
const at = useCallback6((index) => {
return itemsReference.current.at(index);
}, []);
const insert = useCallback6(
(item, index, keep) => {
itemsReference.current.splice(index, 0, item);
return setItems([...itemsReference.current], keep);
},
[setItems]
);
const getAll = useCallback6(() => itemsReference.current, []);
const refresh = useCallback6(() => setItemsState((old) => [...old]), []);
return [itemsState, { push, unshift, set: setItems, at, getAll, insert, refresh }];
}, "useBoundedArray");
// src/useMessages.tsx
var findNewElementIndex = /* @__PURE__ */ __name((elements, element, compare) => {
return elements.length - 1 - [...elements].reverse().findIndex((a) => {
return compare(element, a) > 0;
});
}, "findNewElementIndex");
var useMessages = /* @__PURE__ */ __name(({
maxChunkSize,
additionalChunkSize,
chatClient,
roomIdentifier,
compareItems,
initialMessagesState,
initialSearchResult
}) => {
const isFetching = useRef10(false);
const visibleFrame = useRef10({ begin: -1, end: -1 });
const containerReference = useRef10(null);
const searchResults = useRef10(initialSearchResult);
const selectedSearchResult = useRef10(0);
const focusedItem = useRef10(initialSearchResult == null ? void 0 : initialSearchResult.results[0]);
const [
messages,
{
push: pushMessages,
unshift: unshiftMessages,
set: setMessages,
insert: insertMessage,
at: getMessage,
getAll: getAllMessages,
refresh
}
] = useBoundedArray([...initialMessagesState.messages], maxChunkSize);
const messagesState = useRef10(initialMessagesState);
const handleIncomingMessage = useCallback7(
(message, messageRoomIdentifier) => {
if (messageRoomIdentifier === roomIdentifier && messagesState.current.noMessagesAfter) {
const incomingMessageIndex = findNewElementIndex(getAllMessages(), message, compareItems);
const keepDirection = visibleFrame.current.begin < visibleFrame.current.end ? "beginning" : "ending";
const clipped = insertMessage(message, incomingMessageIndex + 1, keepDirection);
if (clipped) {
if (keepDirection === "beginning") {
messagesState.current.noMessagesAfter = false;
} else {
messagesState.current.noMessagesBefore = false;
}
}
}
},
[roomIdentifier, getAllMessages, compareItems, insertMessage]
);
const focusItem = useCallback7(
async (item) => {
if (!item) {
if (focusedItem.current) {
refresh();
}
focusedItem.current = item;
return;
}
focusedItem.current = item;
const [previousChunk, nextChunk] = await Promise.all([
chatClient.fetchMessages(roomIdentifier, additionalChunkSize, item, void 0),
chatClient.fetchMessages(roomIdentifier, additionalChunkSize, void 0, item)
]);
messagesState.current = {
noMessagesBefore: previousChunk.noMessagesBefore,
noMessagesAfter: nextChunk.noMessagesAfter
};
setMessages([...previousChunk.messages, item, ...nextChunk.messages], "beginning");
},
[additionalChunkSize, chatClient, roomIdentifier, setMessages, refresh]
);
const handleSearch = useCallback7(
(searchRoomIdentifier, searchResult, focusIndex) => {
if (searchRoomIdentifier === roomIdentifier) {
searchResults.current = searchResult;
focusIndex = Math.min(focusIndex, searchResult.results.length - 1);
selectedSearchResult.current = focusIndex;
focusItem(searchResult.results[focusIndex]);
}
},
[focusItem, roomIdentifier]
);
const handlePreviousSearchResult = useCallback7(
(searchRoomIdentifier) => {
if (searchResults.current && searchRoomIdentifier === roomIdentifier) {
selectedSearchResult.current = clamp(
selectedSearchResult.current - 1,
0,
Math.max(searchResults.current.results.length - 1, 0)
);
focusItem(searchResults.current.results[selectedSearchResult.current]);
}
},
[focusItem, roomIdentifier]
);
const handleNextSearchResult = useCallback7(
(searchRoomIdentifier) => {
if (searchResults.current && searchRoomIdentifier === roomIdentifier) {
selectedSearchResult.current = clamp(
selectedSearchResult.current + 1,
0,
Math.max(searchResults.current.results.length - 1, 0)
);
focusItem(searchResults.current.results[selectedSearchResult.current]);
}
},
[focusItem, roomIdentifier]
);
useEffect5(() => {
chatClient.addEventListener("receiveMessage", handleIncomingMessage);
chatClient.addEventListener("receiveSearchResults", handleSearch);
chatClient.addEventListener("nextSearchResult", handleNextSearchResult);
chatClient.addEventListener("previousSearchResult", handlePreviousSearchResult);
return () => {
chatClient.removeEventListener("receiveMessage", handleIncomingMessage);
chatClient.removeEventListener("receiveSearchResults", handleSearch);
chatClient.removeEventListener("nextSearchResult", handleNextSearchResult);
chatClient.removeEventListener("previousSearchResult", handlePreviousSearchResult);
};
}, [chatClient, handleIncomingMessage, handleNextSearchResult, handlePreviousSearchResult, handleSearch]);
useEffect5(() => {
if (!initialSearchResult) {
const container = containerReference.current;
if (container) {
container.scrollTo({ top: container.scrollHeight });
} else {
console.warn(
"RChat: container reference wasn't passed into EndlessList, so scrolling to the bottom after initial chat load failed. This may cause inconsistent behavior"
);
}
}
}, [initialSearchResult]);
useEffect5(() => {
setMessages([...initialMessagesState.messages], "beginning");
messagesState.current = initialMessagesState;
}, [initialMessagesState, setMessages]);
useEffect5(() => {
searchResults.current = initialSearchResult;
focusedItem.current = initialSearchResult == null ? void 0 : initialSearchResult.results[0];
}, [initialSearchResult]);
const handleTopReached = useEvent(async () => {
if (messagesState.current.noMessagesBefore || isFetching.current) {
return;
}
isFetching.current = true;
const { messages: fetchedMessages, noMessagesBefore } = await chatClient.fetchMessages(
roomIdentifier,
additionalChunkSize,
getMessage(0),
void 0
);
const clipped = unshiftMessages(fetchedMessages);
const newState = {
noMessagesBefore,
noMessagesAfter: !clipped && messagesState.current.noMessagesAfter
};
messagesState.current = newState;
isFetching.current = false;
});
const handleBottomReached = useEvent(async () => {
if (messagesState.current.noMessagesAfter || isFetching.current) {
return;
}
isFetching.current = true;
const { messages: fetchedMessages, noMessagesAfter } = await chatClient.fetchMessages(
roomIdentifier,
additionalChunkSize,
void 0,
getMessage(-1)
);
const clipped = pushMessages(fetchedMessages);
const newState = {
noMessagesAfter,
noMessagesBefore: !clipped && messagesState.current.noMessagesBefore
};
messagesState.current = newState;
isFetching.current = false;
});
const onVisibleFrameChange = /* @__PURE__ */ __name((frame) => {
visibleFrame.current = frame;
}, "onVisibleFrameChange");
return {
messages,
onTopReached: handleTopReached,
onBottomReached: handleBottomReached,
noMessagesBefore: messagesState.current.noMessagesBefore,
noMessagesAfter: messagesState.current.noMessagesAfter,
onVisibleFrameChange,
containerReference,
focusedItem: focusedItem.current
};
}, "useMessages");
// src/MessageList.tsx
var MessageList = /* @__PURE__ */ __name(({
jumpAnimation,
initialMessagesState,
initialSearchResult
}) => {
const {
client,
MessageComponent,
PlaceholderComponent,
ContainerComponent,
triggerDistance,
compareItems,
itemKey
} = useSafeContext(RChatContext);
const { roomIdentifier } = useSafeContext(RoomContext);
const {
messages,
onBottomReached,
onTopReached,
noMessagesAfter,
onVisibleFrameChange,
containerReference,
focusedItem
} = useMessages({
chatClient: client,
additionalChunkSize: 20,
maxChunkSize: 100,
roomIdentifier,
compareItems,
initialMessagesState,
initialSearchResult
});
return /* @__PURE__ */ React.createElement(
EndlessList,
{
initialItems: initialMessagesState.messages,
items: messages,
onTopReached,
onBottomReached,
triggerDistance,
ContainerComponent,
ItemComponent: MessageComponent,
PlaceholderComponent,
compareItems,
itemKey,
onVisibleFrameChange,
canStickToBottom: noMessagesAfter,
containerReference,
focusedItem,
jumpAnimation
}
);
}, "MessageList");
// src/Room.tsx
var Room = /* @__PURE__ */ __name(({ identifier, children }) => {
return /* @__PURE__ */ React.createElement(RoomContext.Provider, { value: { roomIdentifier: identifier } }, children);
}, "Room");
export {
Chat,
EndlessList,
MessageList,
Room,
useEndlessList,
useMessages,
useVisibleItems
};
{
"version": 3,
"sources": ["../src/EndlessList/EndlessList.tsx", "../src/internal/mergeReferences.ts", "../src/internal/smoothScrollToCenter.ts", "../src/internal/useEvent.ts", "../src/internal/useScheduleOnNextRender.tsx", "../src/internal/useToggleEvent.ts", "../src/EndlessList/EndlessListItemView.tsx", "../src/EndlessList/useEndlessList.tsx", "../src/internal/binarySearch.ts", "../src/internal/useIdGenerator.ts", "../src/EndlessList/useVisibleFrame.tsx", "../src/EndlessList/useVisibleItems.tsx", "../src/internal/RChatContext.tsx", "../src/Chat.tsx", "../src/MessageList.tsx", "../src/internal/RoomContext.tsx", "../src/useMessages.tsx", "../src/internal/clamp.ts", "../src/internal/useBoundedArray.tsx", "../src/Room.tsx"],
"sourcesContent": ["import {\r\n\tComponentType,\r\n\tPropsWithChildren,\r\n\tRef,\r\n\tRefAttributes,\r\n\tuseCallback,\r\n\tuseEffect,\r\n\tuseLayoutEffect,\r\n\tuseMemo,\r\n\tuseRef,\r\n} from 'react';\r\n\r\nimport { mergeReferences } from '../internal/mergeReferences';\r\nimport { AnimationParameters, smoothScrollToCenter } from '../internal/smoothScrollToCenter';\r\nimport { useEvent } from '../internal/useEvent';\r\nimport { useScheduleOnNextRender } from '../internal/useScheduleOnNextRender';\r\nimport { useToggleEvent } from '../internal/useToggleEvent';\r\n\r\nimport { EndlessListItemView } from './EndlessListItemView';\r\nimport { ItemComponentType } from './ItemComponentType';\r\nimport { PlaceholderComponentType } from './PlaceholderComponentType';\r\nimport { useEndlessList } from './useEndlessList';\r\nimport { Frame, useVisibleFrame } from './useVisibleFrame';\r\nimport { useVisibleItems } from './useVisibleItems';\r\nimport type { KeysOfType } from '../internal/KeysOfType';\r\n\r\nexport type ContainerComponentProps = PropsWithChildren<RefAttributes<HTMLElement>>;\r\n\r\nexport type ItemKey<T> = KeysOfType<T, string> | ((value: T) => string);\r\n\r\nexport type EndlessListProps<TItemType> = {\r\n\tItemComponent: ItemComponentType<TItemType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\tContainerComponent: ComponentType<ContainerComponentProps>;\r\n\tinitialItems: TItemType[];\r\n\titems: TItemType[];\r\n\titemKey: ItemKey<TItemType>;\r\n\ttriggerDistance: number;\r\n\tonTopReached?: () => void;\r\n\tonBottomReached?: () => void;\r\n\tcompareItems: (first: TItemType, second: TItemType) => number;\r\n\tfocusedItem?: TItemType;\r\n\tjumpAnimation?: AnimationParameters;\r\n\tcanStickToBottom?: boolean;\r\n\tonVisibleFrameChange?: (frame: Frame) => void;\r\n\tcontainerReference?: Ref<HTMLElement>;\r\n};\r\n\r\nconst noop = () => {\r\n\t/** No operation */\r\n};\r\n\r\nconst defaultAnimationParameters: AnimationParameters = {\r\n\t// Constant duration\r\n\tduration: () => 500,\r\n\t// Linear easing\r\n\teasing: (t) => t,\r\n};\r\n\r\nexport const EndlessList = <T,>({\r\n\tItemComponent,\r\n\tinitialItems,\r\n\titems,\r\n\titemKey,\r\n\ttriggerDistance,\r\n\tonTopReached,\r\n\tonBottomReached,\r\n\tcompareItems,\r\n\tPlaceholderComponent,\r\n\tjumpAnimation = defaultAnimationParameters,\r\n\tfocusedItem,\r\n\tContainerComponent,\r\n\tcanStickToBottom,\r\n\tonVisibleFrameChange,\r\n\tcontainerReference: propsContainerReference,\r\n}: EndlessListProps<T>) => {\r\n\tconst containerReference = useRef<HTMLElement>(null);\r\n\tconst focusElementReference = useRef<HTMLElement>(null);\r\n\tconst stickToBottomReached = useRef(false);\r\n\tconst isScrolling = useRef(false);\r\n\tconst visibleFrame = useRef<Frame>({ begin: -1, end: -1 });\r\n\tconst hasMounted = useRef(false);\r\n\r\n\tconst setBottomReached = useToggleEvent(onBottomReached ?? noop);\r\n\tconst setTopReached = useToggleEvent(onTopReached ?? noop);\r\n\r\n\tconst getKey = useMemo(() => {\r\n\t\treturn typeof itemKey === 'function' ? itemKey : (value: T) => value[itemKey] as unknown as string;\r\n\t}, [itemKey]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsetBottomReached(false);\r\n\t\tsetTopReached(false);\r\n\t}, [items, setBottomReached, setTopReached]);\r\n\r\n\tconst checkBounds = useEvent((frame: Frame = visibleFrame.current) => {\r\n\t\tonVisibleFrameChange?.(frame);\r\n\t\tvisibleFrame.current = frame;\r\n\t\tif (frame.begin === -1 || frame.end === -1 || isScrolling.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tsetBottomReached(frame.end <= triggerDistance);\r\n\t\tsetTopReached(frame.begin <= triggerDistance);\r\n\t\tstickToBottomReached.current = frame.end === 0;\r\n\t});\r\n\r\n\tconst smoothScrolling = useEvent((container: HTMLElement, item: HTMLElement, abortController?: AbortController) => {\r\n\t\treturn smoothScrollToCenter(container, item, jumpAnimation, abortController);\r\n\t});\r\n\r\n\tconst abortControllerReference = useRef<AbortController>();\r\n\tconst handleJumpScroll = useCallback(\r\n\t\tasync (abortController = new AbortController()) => {\r\n\t\t\tif (abortControllerReference.current) {\r\n\t\t\t\tabortControllerReference.current.abort();\r\n\t\t\t}\r\n\r\n\t\t\tif (!containerReference.current || !focusElementReference.current) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tabortControllerReference.current = abortController;\r\n\t\t\tisScrolling.current = true;\r\n\r\n\t\t\tif (hasMounted.current) {\r\n\t\t\t\tawait smoothScrolling(containerReference.current, focusElementReference.current, abortController);\r\n\t\t\t} else {\r\n\t\t\t\tfocusElementReference.current.scrollIntoView({ behavior: 'auto', block: 'center' });\r\n\t\t\t}\r\n\r\n\t\t\tisScrolling.current = false;\r\n\r\n\t\t\tcheckBounds();\r\n\t\t},\r\n\t\t[checkBounds, smoothScrolling],\r\n\t);\r\n\r\n\tconst onVisibleItemsChange = useVisibleFrame({\r\n\t\tgetKey,\r\n\t\titems,\r\n\t\tonVisibleFrameUpdated: checkBounds,\r\n\t});\r\n\tconst { observer, visibleItemKeys } = useVisibleItems(containerReference, onVisibleItemsChange);\r\n\tconst [scheduleJumpScroll, isJumpScheduled] = useScheduleOnNextRender(handleJumpScroll);\r\n\r\n\tconst lastScrolledItem = useRef<T | undefined>();\r\n\tconst handleScrollToFocusItem = useEvent(() => {\r\n\t\tif (focusedItem === lastScrolledItem.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlastScrolledItem.current = focusedItem;\r\n\t\tif (focusedItem && !isJumpScheduled()) {\r\n\t\t\thandleJumpScroll().catch(() => {\r\n\t\t\t\t/* Ignore aborted jump error */\r\n\t\t\t});\r\n\t\t}\r\n\t});\r\n\r\n\tconst itemsToRender = useEndlessList({\r\n\t\tgetKey,\r\n\t\tinitialItems,\r\n\t\titems,\r\n\t\tcompareItems,\r\n\t\thandleJump: scheduleJumpScroll,\r\n\t\tfocusedItem,\r\n\t\tvisibleItemKeys,\r\n\t\tlastScrolledItem,\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\thandleScrollToFocusItem();\r\n\t\thasMounted.current = true;\r\n\t}, [handleScrollToFocusItem, itemsToRender]);\r\n\r\n\tuseEffect(() => {\r\n\t\treturn () => {\r\n\t\t\thasMounted.current = false;\r\n\t\t};\r\n\t}, []);\r\n\r\n\tconst handleStickToBottom = useEvent(() => {\r\n\t\tconst container = containerReference.current;\r\n\t\tif (container && stickToBottomReached.current && !focusedItem) {\r\n\t\t\tcontainer.scrollTo({ top: container.scrollHeight });\r\n\t\t}\r\n\t});\r\n\r\n\tuseLayoutEffect(() => {\r\n\t\tif (canStickToBottom) {\r\n\t\t\thandleStickToBottom();\r\n\t\t}\r\n\t}, [itemsToRender, canStickToBottom, handleStickToBottom]);\r\n\r\n\treturn (\r\n\t\t<ContainerComponent ref={mergeReferences(containerReference, propsContainerReference)}>\r\n\t\t\t{itemsToRender.map((item) => (\r\n\t\t\t\t<EndlessListItemView\r\n\t\t\t\t\tkey={item.itemKey}\r\n\t\t\t\t\tfocusElementReference={focusElementReference}\r\n\t\t\t\t\tItemComponent={ItemComponent}\r\n\t\t\t\t\tPlaceholderComponent={PlaceholderComponent}\r\n\t\t\t\t\titemObserver={observer}\r\n\t\t\t\t\t{...item}\r\n\t\t\t\t/>\r\n\t\t\t))}\r\n\t\t</ContainerComponent>\r\n\t);\r\n};\r\n", "import { Ref, MutableRefObject } from 'react';\r\n\r\nexport const mergeReferences = <T>(\r\n\t...inputReferences: Array<Ref<T> | MutableRefObject<T> | undefined | false>\r\n): Ref<T> | undefined => {\r\n\tconst filteredInputReferences = inputReferences.filter(Boolean as unknown as (value: unknown) => value is Ref<T>);\r\n\r\n\tif (filteredInputReferences.length <= 1) {\r\n\t\treturn filteredInputReferences[0];\r\n\t}\r\n\treturn function mergedReferences(reference: T | null) {\r\n\t\tfor (const inputReference of filteredInputReferences) {\r\n\t\t\tif (typeof inputReference === 'function') {\r\n\t\t\t\tinputReference(reference);\r\n\t\t\t} else if (inputReference) {\r\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n\t\t\t\t(inputReference as any).current = reference;\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n};\r\n", "export type AnimationParameters = {\r\n\t/**\r\n\t * Easing function.\r\n\t * Takes an argument in range [0, 1] and returns value in range [0, 1].\r\n\t */\r\n\teasing: (t: number) => number;\r\n\r\n\t/**\r\n\t * Animation duration function.\r\n\t * Takes distance in pixels and returns duration in milliseconds.\r\n\t */\r\n\tduration: (distance: number) => number;\r\n};\r\n\r\nexport const smoothScrollToCenter = async (\r\n\tcontainer: HTMLElement,\r\n\telement: HTMLElement,\r\n\tparameters: AnimationParameters,\r\n\tcontroller?: AbortController,\r\n) => {\r\n\tconst elementRect = element.getBoundingClientRect();\r\n\tconst containerRect = container.getBoundingClientRect();\r\n\r\n\tconst top = elementRect.top - containerRect.top - containerRect.height / 2 + elementRect.height / 2;\r\n\r\n\tconst startPos = container.scrollTop;\r\n\tconst clientHeight = container.clientHeight;\r\n\tconst maxScroll = container.scrollHeight - clientHeight;\r\n\tconst scrollIntendedDestination = startPos + top;\r\n\tconst scrollEndValue = Math.min(Math.max(scrollIntendedDestination, 0), maxScroll);\r\n\tlet startTime = 0;\r\n\r\n\tconst duration = parameters.duration(scrollEndValue - startPos);\r\n\r\n\treturn new Promise<void>((resolve, reject) => {\r\n\t\tconst scroll = (timestamp: number) => {\r\n\t\t\tif (controller?.signal.aborted) {\r\n\t\t\t\treject(controller.signal.reason);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tstartTime = startTime || timestamp;\r\n\t\t\tconst elapsed = timestamp - startTime;\r\n\t\t\tcontainer.scrollTop = startPos + (scrollEndValue - startPos) * parameters.easing(elapsed / duration);\r\n\t\t\tif (elapsed <= duration) {\r\n\t\t\t\twindow.requestAnimationFrame(scroll);\r\n\t\t\t} else {\r\n\t\t\t\tresolve();\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tif (startPos !== scrollEndValue) {\r\n\t\t\twindow.requestAnimationFrame(scroll);\r\n\t\t} else {\r\n\t\t\tresolve();\r\n\t\t}\r\n\t});\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyFunction = (...arguments_: any[]) => any;\r\n\r\nexport const useEvent = <T extends AnyFunction>(handler: T): T => {\r\n\tconst handlerReference = useRef(handler);\r\n\thandlerReference.current = handler;\r\n\r\n\treturn useCallback((...parameters: Parameters<T>): ReturnType<T> => {\r\n\t\treturn handlerReference.current(...parameters);\r\n\t}, []) as T;\r\n};\r\n", "import { useCallback, useLayoutEffect, useRef } from 'react';\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype AnyAsyncFunction = (...arguments_: any[]) => Promise<any>;\r\n\r\nexport const useScheduleOnNextRender = <T extends AnyAsyncFunction>(\r\n\thandler: T,\r\n): [schedule: (...parameters: Parameters<T>) => ReturnType<T>, isScheduled: () => boolean] => {\r\n\ttype PromiseHandle = {\r\n\t\tparameters: Parameters<T>;\r\n\t\tresolve: (value: ReturnType<Awaited<T>>) => void;\r\n\t\treject: (reason: unknown) => void;\r\n\t};\r\n\tconst unresolvedHandle = useRef<PromiseHandle>();\r\n\r\n\tuseLayoutEffect(() => {\r\n\t\tconst currentHandle = unresolvedHandle.current;\r\n\t\tunresolvedHandle.current = undefined;\r\n\t\tif (currentHandle) {\r\n\t\t\thandler(...currentHandle.parameters)\r\n\t\t\t\t.then(currentHandle.resolve)\r\n\t\t\t\t.catch(currentHandle.reject);\r\n\t\t}\r\n\t});\r\n\r\n\tconst wrappedFunction = useCallback((...parameters: Parameters<T>): ReturnType<T> => {\r\n\t\treturn new Promise<Awaited<ReturnType<T>>>((resolve, reject) => {\r\n\t\t\tunresolvedHandle.current = {\r\n\t\t\t\tparameters,\r\n\t\t\t\tresolve,\r\n\t\t\t\treject,\r\n\t\t\t};\r\n\t\t}) as ReturnType<T>;\r\n\t}, []);\r\n\r\n\tconst isScheduled = useCallback(() => {\r\n\t\treturn unresolvedHandle.current !== undefined;\r\n\t}, []);\r\n\r\n\treturn [wrappedFunction, isScheduled];\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\nexport const useToggleEvent = (onTurnedOn: () => void): ((value: boolean) => void) => {\r\n\tconst value = useRef(false);\r\n\r\n\tconst toggle = useCallback(\r\n\t\t(newValue: boolean) => {\r\n\t\t\tif (!value.current && newValue) {\r\n\t\t\t\tonTurnedOn();\r\n\t\t\t}\r\n\r\n\t\t\tvalue.current = newValue;\r\n\t\t},\r\n\t\t[onTurnedOn],\r\n\t);\r\n\r\n\treturn toggle;\r\n};\r\n", "import { RefObject, useEffect, useRef } from 'react';\r\nimport { mergeReferences } from '../internal/mergeReferences';\r\nimport { ItemComponentType } from './ItemComponentType';\r\nimport { PlaceholderComponentType } from './PlaceholderComponentType';\r\nimport type { EndlessListItem } from './useEndlessList';\r\n\r\nexport type EndlessListItemViewProps<TMessageType> = EndlessListItem<TMessageType> & {\r\n\tItemComponent: ItemComponentType<TMessageType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\titemObserver: IntersectionObserver | undefined;\r\n\tfocusElementReference: RefObject<HTMLElement>;\r\n};\r\n\r\nexport const EndlessListItemView = <TMessageType,>({\r\n\tItemComponent,\r\n\tPlaceholderComponent,\r\n\titemObserver,\r\n\tfocusElementReference,\r\n\t...item\r\n}: EndlessListItemViewProps<TMessageType>) => {\r\n\tconst itemReference = useRef<HTMLElement>(null);\r\n\r\n\tuseEffect(() => {\r\n\t\tconst currentElement = itemReference.current;\r\n\t\tif (currentElement && itemObserver) {\r\n\t\t\titemObserver.observe(currentElement);\r\n\r\n\t\t\treturn () => itemObserver.unobserve(currentElement);\r\n\t\t}\r\n\t}, [itemObserver]);\r\n\r\n\tif (item.type === 'placeholder') {\r\n\t\treturn <PlaceholderComponent ref={itemReference} itemKey={item.itemKey} />;\r\n\t}\r\n\r\n\treturn <ItemComponent ref={mergeReferences(itemReference, item.focused && focusElementReference)} {...item} />;\r\n};\r\n", "import { Key, useMemo, useRef, useState, MutableRefObject, useEffect } from 'react';\r\nimport useIsomorphicLayoutEffect from 'use-isomorphic-layout-effect';\r\nimport { binarySearch } from '../internal/binarySearch';\r\nimport { useEvent } from '../internal/useEvent';\r\nimport { useIdGenerator } from '../internal/useIdGenerator';\r\n\r\nexport type UseEndlessListConfig<T> = {\r\n\tinitialItems: T[];\r\n\titems: T[];\r\n\tgetKey: (item: T) => string;\r\n\tcompareItems: (a: T, b: T) => number;\r\n\thandleJump: (abortController: AbortController) => Promise<void>;\r\n\tfocusedItem?: T;\r\n\tvisibleItemKeys: MutableRefObject<Set<string>>;\r\n\tlastScrolledItem: MutableRefObject<T | undefined>;\r\n};\r\n\r\nexport type EndlessListRealItem<TValue> = {\r\n\ttype: 'real';\r\n\tvalue: TValue;\r\n\tindex: number;\r\n\tarray: TValue[];\r\n\titemKey: string;\r\n\tfocused: boolean;\r\n};\r\n\r\nexport type EndlessListPlaceholderItem = {\r\n\ttype: 'placeholder';\r\n\titemKey: string;\r\n};\r\n\r\nexport type EndlessListItem<TValue> = EndlessListRealItem<TValue> | EndlessListPlaceholderItem;\r\n\r\nconst valueToEndlessListItem = <T,>(getKey: (value: T) => string, focusItemKey: string | undefined) => {\r\n\treturn (value: T, index: number, array: T[]): EndlessListRealItem<T> => {\r\n\t\tconst key = getKey(value);\r\n\r\n\t\treturn {\r\n\t\t\ttype: 'real',\r\n\t\t\tvalue,\r\n\t\t\tindex,\r\n\t\t\tarray,\r\n\t\t\tfocused: key === focusItemKey,\r\n\t\t\titemKey: key,\r\n\t\t};\r\n\t};\r\n};\r\n\r\nexport const useEndlessList = <T,>({\r\n\tinitialItems,\r\n\titems,\r\n\tgetKey,\r\n\tfocusedItem,\r\n\tcompareItems,\r\n\thandleJump,\r\n\tvisibleItemKeys,\r\n\tlastScrolledItem,\r\n}: UseEndlessListConfig<T>): Array<EndlessListItem<T>> => {\r\n\tconst focusedItemKey = focusedItem === undefined ? undefined : getKey(focusedItem);\r\n\tconst defaultConvertItem = useMemo(() => valueToEndlessListItem(getKey, focusedItemKey), [getKey, focusedItemKey]);\r\n\tconst [renderedItems, setRenderedItems] = useState<Array<EndlessListItem<T>>>(() => items.map(defaultConvertItem));\r\n\tconst jumpAbortController = useRef<AbortController>();\r\n\tconst initialItemsReference = useRef(initialItems);\r\n\tconst hasMounted = useRef(false);\r\n\r\n\tconst getUniquePlaceholderKey = useIdGenerator();\r\n\r\n\tconst performFixup = useEvent((): [items: Array<EndlessListItem<T>>, constructItems: boolean] => {\r\n\t\t/**\r\n\t\t * Visible items fixup algorithm.\r\n\t\t *\r\n\t\t * Firstly, take all items, which are displayed on the screen.\r\n\t\t */\r\n\r\n\t\tconst visibleItems = renderedItems\r\n\t\t\t.filter(({ itemKey, type }, index, array) => {\r\n\t\t\t\tif (visibleItemKeys.current.has(itemKey)) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (type === 'placeholder') {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst previousItem = array[index - 1];\r\n\t\t\t\tif (\r\n\t\t\t\t\tpreviousItem &&\r\n\t\t\t\t\tpreviousItem.type !== 'placeholder' &&\r\n\t\t\t\t\tvisibleItemKeys.current.has(previousItem.itemKey)\r\n\t\t\t\t) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconst nextItem = array[index + 1];\r\n\t\t\t\tif (nextItem && nextItem.type !== 'placeholder' && visibleItemKeys.current.has(nextItem.itemKey)) {\r\n\t\t\t\t\treturn true;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn false;\r\n\t\t\t})\r\n\t\t\t.map((item) => {\r\n\t\t\t\tif (item.type === 'real' && item.focused) {\r\n\t\t\t\t\titem.focused = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn item;\r\n\t\t\t});\r\n\r\n\t\tconst keys = new Set(items.map(getKey));\r\n\t\tif (visibleItems.every((item) => !keys.has(item.itemKey))) {\r\n\t\t\treturn [visibleItems, true];\r\n\t\t}\r\n\r\n\t\tconst comparator = (a: EndlessListRealItem<T>, b: { value: EndlessListItem<T>; index: number }): number => {\r\n\t\t\tif (b.value.type === 'placeholder') {\r\n\t\t\t\tconst nextValue = visibleItems[b.index + 1];\r\n\r\n\t\t\t\tif (nextValue !== undefined && nextValue.type !== 'placeholder') {\r\n\t\t\t\t\treturn compareItems(nextValue.value, a.value);\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn 1;\r\n\t\t\t}\r\n\r\n\t\t\treturn compareItems(a.value, b.value.value);\r\n\t\t};\r\n\r\n\t\tconst jumpKey = focusedItemKey ?? getKey(items[Math.floor(items.length / 2)]);\r\n\t\tconst convertedItems = [...items.map(valueToEndlessListItem(getKey, jumpKey))];\r\n\r\n\t\tlet pivotIndex = visibleItems.findIndex((item) => keys.has(item.itemKey));\r\n\r\n\t\tif (pivotIndex === -1) {\r\n\t\t\tpivotIndex = binarySearch(visibleItems, convertedItems.at(0)!, comparator);\r\n\t\t}\r\n\t\tvisibleItems.splice(pivotIndex, 1, ...convertedItems);\r\n\r\n\t\tconst dedupedKeys = new Set<Key>();\r\n\t\tconst filteredItems = visibleItems.filter((item) => {\r\n\t\t\tif (dedupedKeys.has(item.itemKey)) {\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tdedupedKeys.add(item.itemKey);\r\n\t\t\treturn true;\r\n\t\t});\r\n\r\n\t\treturn [filteredItems, false];\r\n\t});\r\n\r\n\tconst update = useEvent(async () => {\r\n\t\tif (jumpAbortController.current) {\r\n\t\t\tjumpAbortController.current.abort();\r\n\t\t\tjumpAbortController.current = undefined;\r\n\t\t}\r\n\r\n\t\tif (renderedItems.length === 0 || items.length === 0 || initialItemsReference.current !== initialItems) {\r\n\t\t\t/**\r\n\t\t\t * There is nothing to do:\r\n\t\t\t * 1. If renderedItems array is empty, it means that there is nothing on the screen - render all items.\r\n\t\t\t * 2. If items array is empty, it means that all items must disappear from the screen.\r\n\t\t\t * \t 3. If initial items has been changed\r\n\t\t\t */\r\n\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t\tinitialItemsReference.current = initialItems;\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Determine, if current update call has aborted previous jump.\r\n\t\t */\r\n\t\tconst isAbortedPreviousJump = renderedItems.some((item) => item.type === 'placeholder');\r\n\r\n\t\tlet oldItems: Array<EndlessListItem<T>>;\r\n\t\tlet constructItems = true;\r\n\t\tif (isAbortedPreviousJump) {\r\n\t\t\t/**\r\n\t\t\t * Previous jump was terminated by current state update.\r\n\t\t\t * Must perform one-time fixup.\r\n\t\t\t */\r\n\t\t\t[oldItems, constructItems] = performFixup();\r\n\r\n\t\t\tlet array = [];\r\n\t\t\tlet index = 0;\r\n\t\t\tfor (const item of oldItems) {\r\n\t\t\t\tif (item.type === 'placeholder') {\r\n\t\t\t\t\tindex = 0;\r\n\t\t\t\t\tarray = [];\r\n\t\t\t\t} else {\r\n\t\t\t\t\titem.index = index;\r\n\t\t\t\t\titem.array = array;\r\n\t\t\t\t\tarray.push(item.value);\r\n\t\t\t\t\t++index;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst keys = items.map(getKey);\r\n\t\t\tconst oldKeys = renderedItems.map((item) => item.itemKey);\r\n\r\n\t\t\tconst mustMoveForward = !oldKeys.includes(keys[0]) && !keys.includes(oldKeys.at(-1)!);\r\n\t\t\tconst mustMoveBack = !keys.includes(oldKeys[0]) && !oldKeys.includes(keys.at(-1)!);\r\n\r\n\t\t\tconst mustJump = mustMoveForward && mustMoveBack;\r\n\r\n\t\t\tif (!mustJump) {\r\n\t\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\toldItems = renderedItems.map((item) => {\r\n\t\t\t\tif (item.type === 'real' && item.focused) {\r\n\t\t\t\t\titem.focused = false;\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn item;\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tlet constructedItems: Array<EndlessListItem<T>>;\r\n\t\tif (constructItems) {\r\n\t\t\tconst firstItem = oldItems.find((item): item is EndlessListRealItem<T> => item.type === 'real');\r\n\t\t\tlet jumpDirection = 'forward';\r\n\t\t\tif (firstItem) {\r\n\t\t\t\tjumpDirection = compareItems(items[0], firstItem.value) < 0 ? 'forward' : 'back';\r\n\t\t\t}\r\n\r\n\t\t\tconst jumpKey = focusedItemKey ?? getKey(items[Math.floor(items.length / 2)]);\r\n\r\n\t\t\tlet nextItems: Array<EndlessListItem<T>> | undefined;\r\n\t\t\tlet previousItems: Array<EndlessListItem<T>> | undefined;\r\n\r\n\t\t\tconst convertItem = valueToEndlessListItem(getKey, jumpKey);\r\n\t\t\tif (jumpDirection === 'forward') {\r\n\t\t\t\tnextItems = items.map(convertItem);\r\n\t\t\t\tpreviousItems = oldItems;\r\n\t\t\t} else {\r\n\t\t\t\tnextItems = oldItems;\r\n\t\t\t\tpreviousItems = items.map(convertItem);\r\n\t\t\t}\r\n\r\n\t\t\tconst alreadyHasPlaceholder =\r\n\t\t\t\tnextItems.at(-1)?.type === 'placeholder' || previousItems.at(0)?.type === 'placeholder';\r\n\r\n\t\t\tconstructedItems = [\r\n\t\t\t\t...nextItems,\r\n\t\t\t\t...(alreadyHasPlaceholder\r\n\t\t\t\t\t? []\r\n\t\t\t\t\t: [{ type: 'placeholder' as const, itemKey: getUniquePlaceholderKey() }]),\r\n\t\t\t\t...previousItems,\r\n\t\t\t];\r\n\t\t} else {\r\n\t\t\tconstructedItems = oldItems;\r\n\t\t}\r\n\r\n\t\tlastScrolledItem.current = items[Math.floor(items.length / 2)];\r\n\r\n\t\tsetRenderedItems(constructedItems);\r\n\t\tconst newController = new AbortController();\r\n\t\tjumpAbortController.current = newController;\r\n\r\n\t\ttry {\r\n\t\t\tif (hasMounted.current) {\r\n\t\t\t\tawait handleJump(newController);\r\n\t\t\t}\r\n\r\n\t\t\tsetRenderedItems(items.map(defaultConvertItem));\r\n\t\t} catch {\r\n\t\t\t/* Noop */\r\n\t\t} finally {\r\n\t\t\tjumpAbortController.current = undefined;\r\n\t\t}\r\n\t});\r\n\r\n\tuseIsomorphicLayoutEffect(() => {\r\n\t\tupdate();\r\n\t\thasMounted.current = true;\r\n\t}, [update, items]);\r\n\r\n\tuseEffect(() => {\r\n\t\treturn () => {\r\n\t\t\thasMounted.current = false;\r\n\t\t};\r\n\t}, []);\r\n\r\n\treturn renderedItems;\r\n};\r\n", "export const binarySearch = <TItem, TValue extends TItem = TItem>(\r\n\tarray: TItem[],\r\n\tvalue: TValue,\r\n\tcomparator: (a: TValue, b: { value: TItem; index: number }) => number,\r\n): number => {\r\n\tlet low = 0;\r\n\tlet high = array.length;\r\n\r\n\tif (high === 0) {\r\n\t\treturn 0;\r\n\t}\r\n\r\n\twhile (low < high) {\r\n\t\tconst middle = Math.floor((low + high) / 2);\r\n\r\n\t\tif (comparator(value, { value: array[middle], index: middle }) > 0) {\r\n\t\t\tlow = middle + 1;\r\n\t\t} else {\r\n\t\t\thigh = middle;\r\n\t\t}\r\n\t}\r\n\r\n\treturn high;\r\n};\r\n", "import { useCallback, useRef } from 'react';\r\n\r\nexport const useIdGenerator = (): (() => string) => {\r\n\tconst counter = useRef(0);\r\n\r\n\treturn useCallback(() => `:rchat:-${++counter.current}`, []);\r\n};\r\n", "import { useEvent } from '../internal/useEvent';\r\n\r\nexport type UseVisibleFrameConfig<TValue> = {\r\n\titems: TValue[];\r\n\tgetKey: (item: TValue) => string;\r\n\tonVisibleFrameUpdated: (frame: Frame) => void;\r\n};\r\n\r\nexport type Frame = {\r\n\tbegin: number;\r\n\tend: number;\r\n};\r\n\r\nexport const useVisibleFrame = <TValue,>({\r\n\titems,\r\n\tgetKey,\r\n\tonVisibleFrameUpdated,\r\n}: UseVisibleFrameConfig<TValue>): ((keys: Set<string>) => void) => {\r\n\tconst updateVisibleFrame = useEvent((visibleItemKeys: Set<string>) => {\r\n\t\tlet begin = -1;\r\n\t\tfor (const [index, item] of items.entries()) {\r\n\t\t\tif (visibleItemKeys.has(getKey(item))) {\r\n\t\t\t\tbegin = index;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet end = -1;\r\n\t\tfor (let index = 0; index <= items.length; ++index) {\r\n\t\t\tconst item = items.at(-index - 1);\r\n\t\t\tif (item && visibleItemKeys.has(getKey(item))) {\r\n\t\t\t\tend = index;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tonVisibleFrameUpdated({ begin, end });\r\n\t});\r\n\r\n\treturn updateVisibleFrame;\r\n};\r\n", "import { RefObject, useEffect, useState, MutableRefObject, useRef } from 'react';\r\nimport { useEvent } from '../internal/useEvent';\r\n\r\nexport type VisibleItemsBag = {\r\n\tobserver: IntersectionObserver | undefined;\r\n\tvisibleItemKeys: MutableRefObject<Set<string>>;\r\n};\r\n\r\nexport const useVisibleItems = (\r\n\tcontainerReference: RefObject<HTMLElement>,\r\n\tonVisibleItemsChange?: (items: Set<string>) => void,\r\n): VisibleItemsBag => {\r\n\tconst [observer, setObserver] = useState<IntersectionObserver>();\r\n\tconst visibleItemKeysReference = useRef(new Set<string>());\r\n\r\n\tconst updateVisibleFrame = useEvent((entries: IntersectionObserverEntry[]) => {\r\n\t\tfor (const { target, isIntersecting } of entries) {\r\n\t\t\tconst key = (target as HTMLElement).dataset.key;\r\n\r\n\t\t\tif (!key) {\r\n\t\t\t\t// eslint-disable-next-line no-console\r\n\t\t\t\tconsole.warn('Item component doesn\\'t have \"data-key\" attribute.');\r\n\t\t\t} else if (isIntersecting) {\r\n\t\t\t\tvisibleItemKeysReference.current.add(key);\r\n\t\t\t} else {\r\n\t\t\t\tvisibleItemKeysReference.current.delete(key);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tonVisibleItemsChange?.(visibleItemKeysReference.current);\r\n\t});\r\n\r\n\tuseEffect(() => {\r\n\t\tconst containerElement = containerReference.current;\r\n\t\tif (containerElement) {\r\n\t\t\tconst observer = new IntersectionObserver(updateVisibleFrame, { root: containerElement, threshold: 0 });\r\n\r\n\t\t\tsetObserver(observer);\r\n\t\t}\r\n\t}, [containerReference, updateVisibleFrame]);\r\n\r\n\treturn { observer, visibleItemKeys: visibleItemKeysReference };\r\n};\r\n", "import { ChatClient } from '@rchat/client';\r\nimport { createSafeContext } from '@sirse-dev/safe-context';\r\nimport type { ContainerComponentProps, ItemComponentType, ItemKey, PlaceholderComponentType } from '../EndlessList';\r\nimport type { ComponentType } from 'react';\r\n\r\nexport type RChatContextType<TMessageType> = {\r\n\tclient: ChatClient<TMessageType>;\r\n\tMessageComponent: ItemComponentType<TMessageType>;\r\n\tPlaceholderComponent: PlaceholderComponentType;\r\n\tContainerComponent: ComponentType<ContainerComponentProps>;\r\n\ttriggerDistance: number;\r\n\titemKey: ItemKey<TMessageType>;\r\n\tcompareItems: (first: TMessageType, second: TMessageType) => number;\r\n};\r\n\r\nexport const RChatContext = createSafeContext<RChatContextType<unknown>>();\r\n", "import { PropsWithChildren } from 'react';\r\n\r\nimport { RChatContext, RChatContextType } from './internal/RChatContext';\r\n\r\nexport type ChatProps<TMessageType> = PropsWithChildren<RChatContextType<TMessageType>>;\r\n\r\nexport const Chat = <TMessageType,>({ children, ...context }: ChatProps<TMessageType>) => (\r\n\t<RChatContext.Provider value={{ ...(context as RChatContextType<unknown>) }}>{children}</RChatContext.Provider>\r\n);\r\n", "import { MessageFetchResult, MessageSearchResult } from '@rchat/client';\r\nimport { useSafeContext } from '@sirse-dev/safe-context';\r\nimport { EndlessList } from './EndlessList';\r\nimport { RChatContext } from './internal/RChatContext';\r\nimport { RoomContext } from './internal/RoomContext';\r\nimport { AnimationParameters } from './internal/smoothScrollToCenter';\r\nimport { useMessages } from './useMessages';\r\n\r\nexport type MessageListProps<TMessage> = {\r\n\tinitialMessagesState: MessageFetchResult<TMessage>;\r\n\tinitialSearchResult?: MessageSearchResult<TMessage>;\r\n\tjumpAnimation?: AnimationParameters;\r\n};\r\n\r\nexport const MessageList = <TMessage,>({\r\n\tjumpAnimation,\r\n\tinitialMessagesState,\r\n\tinitialSearchResult,\r\n}: MessageListProps<TMessage>) => {\r\n\tconst {\r\n\t\tclient,\r\n\t\tMessageComponent,\r\n\t\tPlaceholderComponent,\r\n\t\tContainerComponent,\r\n\t\ttriggerDistance,\r\n\t\tcompareItems,\r\n\t\titemKey,\r\n\t} = useSafeContext(RChatContext);\r\n\tconst { roomIdentifier } = useSafeContext(RoomContext);\r\n\r\n\tconst {\r\n\t\tmessages,\r\n\t\tonBottomReached,\r\n\t\tonTopReached,\r\n\t\tnoMessagesAfter,\r\n\t\tonVisibleFrameChange,\r\n\t\tcontainerReference,\r\n\t\tfocusedItem,\r\n\t} = useMessages({\r\n\t\tchatClient: client,\r\n\t\tadditionalChunkSize: 20,\r\n\t\tmaxChunkSize: 100,\r\n\t\troomIdentifier,\r\n\t\tcompareItems,\r\n\t\tinitialMessagesState,\r\n\t\tinitialSearchResult,\r\n\t});\r\n\r\n\treturn (\r\n\t\t<EndlessList\r\n\t\t\tinitialItems={initialMessagesState.messages}\r\n\t\t\titems={messages}\r\n\t\t\tonTopReached={onTopReached}\r\n\t\t\tonBottomReached={onBottomReached}\r\n\t\t\ttriggerDistance={triggerDistance}\r\n\t\t\tContainerComponent={ContainerComponent}\r\n\t\t\tItemComponent={MessageComponent}\r\n\t\t\tPlaceholderComponent={PlaceholderComponent}\r\n\t\t\tcompareItems={compareItems}\r\n\t\t\titemKey={itemKey}\r\n\t\t\tonVisibleFrameChange={onVisibleFrameChange}\r\n\t\t\tcanStickToBottom={noMessagesAfter}\r\n\t\t\tcontainerReference={containerReference}\r\n\t\t\tfocusedItem={focusedItem}\r\n\t\t\tjumpAnimation={jumpAnimation}\r\n\t\t/>\r\n\t);\r\n};\r\n", "import { createSafeContext } from '@sirse-dev/safe-context';\r\n\r\nexport type RoomContextType = {\r\n\troomIdentifier: string;\r\n};\r\n\r\nexport const RoomContext = createSafeContext<RoomContextType>();\r\n", "import { MessageFetchResult, MessageSearchResult } from '@rchat/client';\r\nimport { ChatClient } from '@rchat/client';\r\nimport { Ref, useCallback, useEffect, useRef } from 'react';\r\nimport { Frame } from './EndlessList/useVisibleFrame';\r\nimport { clamp } from './internal/clamp';\r\nimport { KeepDirection, useBoundedArray } from './internal/useBoundedArray';\r\nimport { useEvent } from './internal/useEvent';\r\n\r\nexport type UseMessagesBag<T> = {\r\n\tmessages: T[];\r\n\tonTopReached: () => void;\r\n\tonBottomReached: () => void;\r\n\tnoMessagesBefore: boolean;\r\n\tnoMessagesAfter: boolean;\r\n\tonVisibleFrameChange: (frame: Frame) => void;\r\n\tcontainerReference: Ref<HTMLElement>;\r\n\tfocusedItem?: T;\r\n};\r\n\r\nexport type UseMessagesConfig<T> = {\r\n\tinitialMessagesState: MessageFetchResult<T>;\r\n\tinitialSearchResult?: MessageSearchResult<T>;\r\n\tcompareItems: (a: T, b: T) => number;\r\n\tmaxChunkSize: number;\r\n\tadditionalChunkSize: number;\r\n\tchatClient: ChatClient<T>;\r\n\troomIdentifier: string;\r\n};\r\n\r\n// TODO: replace with binary search\r\nconst findNewElementIndex = <T,>(elements: readonly T[], element: T, compare: (a: T, b: T) => number): number => {\r\n\treturn (\r\n\t\telements.length -\r\n\t\t1 -\r\n\t\t[...elements].reverse().findIndex((a) => {\r\n\t\t\treturn compare(element, a) > 0;\r\n\t\t})\r\n\t);\r\n};\r\n\r\nexport const useMessages = <TMessage,>({\r\n\tmaxChunkSize,\r\n\tadditionalChunkSize,\r\n\tchatClient,\r\n\troomIdentifier,\r\n\tcompareItems,\r\n\tinitialMessagesState,\r\n\tinitialSearchResult,\r\n}: UseMessagesConfig<TMessage>): UseMessagesBag<TMessage> => {\r\n\tconst isFetching = useRef(false);\r\n\tconst visibleFrame = useRef<Frame>({ begin: -1, end: -1 });\r\n\tconst containerReference = useRef<HTMLElement>(null);\r\n\tconst searchResults = useRef<MessageSearchResult<TMessage> | undefined>(initialSearchResult);\r\n\tconst selectedSearchResult = useRef(0);\r\n\tconst focusedItem = useRef<TMessage | undefined>(initialSearchResult?.results[0]);\r\n\r\n\tconst [\r\n\t\tmessages,\r\n\t\t{\r\n\t\t\tpush: pushMessages,\r\n\t\t\tunshift: unshiftMessages,\r\n\t\t\tset: setMessages,\r\n\t\t\tinsert: insertMessage,\r\n\t\t\tat: getMessage,\r\n\t\t\tgetAll: getAllMessages,\r\n\t\t\trefresh,\r\n\t\t},\r\n\t] = useBoundedArray<TMessage>([...initialMessagesState.messages], maxChunkSize);\r\n\r\n\tconst messagesState = useRef<Omit<MessageFetchResult<TMessage>, 'messages'>>(initialMessagesState);\r\n\r\n\tconst handleIncomingMessage = useCallback(\r\n\t\t(message: TMessage, messageRoomIdentifier: string) => {\r\n\t\t\tif (messageRoomIdentifier === roomIdentifier && messagesState.current.noMessagesAfter) {\r\n\t\t\t\tconst incomingMessageIndex = findNewElementIndex(getAllMessages(), message, compareItems);\r\n\r\n\t\t\t\tconst keepDirection: KeepDirection =\r\n\t\t\t\t\tvisibleFrame.current.begin < visibleFrame.current.end ? 'beginning' : 'ending';\r\n\r\n\t\t\t\tconst clipped = insertMessage(message, incomingMessageIndex + 1, keepDirection);\r\n\r\n\t\t\t\tif (clipped) {\r\n\t\t\t\t\tif (keepDirection === 'beginning') {\r\n\t\t\t\t\t\tmessagesState.current.noMessagesAfter = false;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tmessagesState.current.noMessagesBefore = false;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t},\r\n\t\t[roomIdentifier, getAllMessages, compareItems, insertMessage],\r\n\t);\r\n\r\n\tconst focusItem = useCallback(\r\n\t\tasync (item: TMessage | undefined) => {\r\n\t\t\tif (!item) {\r\n\t\t\t\tif (focusedItem.current) {\r\n\t\t\t\t\trefresh();\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfocusedItem.current = item;\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tfocusedItem.current = item;\r\n\r\n\t\t\tconst [previousChunk, nextChunk] = await Promise.all([\r\n\t\t\t\tchatClient.fetchMessages(roomIdentifier, additionalChunkSize, item, undefined),\r\n\t\t\t\tchatClient.fetchMessages(roomIdentifier, additionalChunkSize, undefined, item),\r\n\t\t\t]);\r\n\r\n\t\t\tmessagesState.current = {\r\n\t\t\t\tnoMessagesBefore: previousChunk.noMessagesBefore,\r\n\t\t\t\tnoMessagesAfter: nextChunk.noMessagesAfter,\r\n\t\t\t};\r\n\r\n\t\t\tsetMessages([...previousChunk.messages, item, ...nextChunk.messages], 'beginning');\r\n\t\t},\r\n\t\t[additionalChunkSize, chatClient, roomIdentifier, setMessages, refresh],\r\n\t);\r\n\r\n\tconst handleSearch = useCallback(\r\n\t\t(searchRoomIdentifier: string, searchResult: MessageSearchResult<TMessage>, focusIndex: number) => {\r\n\t\t\tif (searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tsearchResults.current = searchResult;\r\n\t\t\t\tfocusIndex = Math.min(focusIndex, searchResult.results.length - 1);\r\n\t\t\t\tselectedSearchResult.current = focusIndex;\r\n\t\t\t\tfocusItem(searchResult.results[focusIndex]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tconst handlePreviousSearchResult = useCallback(\r\n\t\t(searchRoomIdentifier: string) => {\r\n\t\t\tif (searchResults.current && searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tselectedSearchResult.current = clamp(\r\n\t\t\t\t\tselectedSearchResult.current - 1,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tMath.max(searchResults.current.results.length - 1, 0),\r\n\t\t\t\t);\r\n\t\t\t\tfocusItem(searchResults.current.results[selectedSearchResult.current]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tconst handleNextSearchResult = useCallback(\r\n\t\t(searchRoomIdentifier: string) => {\r\n\t\t\tif (searchResults.current && searchRoomIdentifier === roomIdentifier) {\r\n\t\t\t\tselectedSearchResult.current = clamp(\r\n\t\t\t\t\tselectedSearchResult.current + 1,\r\n\t\t\t\t\t0,\r\n\t\t\t\t\tMath.max(searchResults.current.results.length - 1, 0),\r\n\t\t\t\t);\r\n\t\t\t\tfocusItem(searchResults.current.results[selectedSearchResult.current]);\r\n\t\t\t}\r\n\t\t},\r\n\t\t[focusItem, roomIdentifier],\r\n\t);\r\n\r\n\tuseEffect(() => {\r\n\t\tchatClient.addEventListener('receiveMessage', handleIncomingMessage);\r\n\t\tchatClient.addEventListener('receiveSearchResults', handleSearch);\r\n\t\tchatClient.addEventListener('nextSearchResult', handleNextSearchResult);\r\n\t\tchatClient.addEventListener('previousSearchResult', handlePreviousSearchResult);\r\n\r\n\t\treturn () => {\r\n\t\t\tchatClient.removeEventListener('receiveMessage', handleIncomingMessage);\r\n\t\t\tchatClient.removeEventListener('receiveSearchResults', handleSearch);\r\n\t\t\tchatClient.removeEventListener('nextSearchResult', handleNextSearchResult);\r\n\t\t\tchatClient.removeEventListener('previousSearchResult', handlePreviousSearchResult);\r\n\t\t};\r\n\t}, [chatClient, handleIncomingMessage, handleNextSearchResult, handlePreviousSearchResult, handleSearch]);\r\n\r\n\t// Scroll to bottom if there was no initial search\r\n\tuseEffect(() => {\r\n\t\tif (!initialSearchResult) {\r\n\t\t\tconst container = containerReference.current;\r\n\t\t\tif (container) {\r\n\t\t\t\tcontainer.scrollTo({ top: container.scrollHeight });\r\n\t\t\t} else {\r\n\t\t\t\t// eslint-disable-next-line no-console\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t\"RChat: container reference wasn't passed into EndlessList,\" +\r\n\t\t\t\t\t\t' so scrolling to the bottom after initial chat load failed.' +\r\n\t\t\t\t\t\t' This may cause inconsistent behavior',\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t}\r\n\t}, [initialSearchResult]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsetMessages([...initialMessagesState.messages], 'beginning');\r\n\t\tmessagesState.current = initialMessagesState;\r\n\t}, [initialMessagesState, setMessages]);\r\n\r\n\tuseEffect(() => {\r\n\t\tsearchResults.current = initialSearchResult;\r\n\t\tfocusedItem.current = initialSearchResult?.results[0];\r\n\t}, [initialSearchResult]);\r\n\r\n\tconst handleTopReached = useEvent(async () => {\r\n\t\tif (messagesState.current.noMessagesBefore || isFetching.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tisFetching.current = true;\r\n\t\tconst { messages: fetchedMessages, noMessagesBefore } = await chatClient.fetchMessages(\r\n\t\t\troomIdentifier,\r\n\t\t\tadditionalChunkSize,\r\n\t\t\tgetMessage(0),\r\n\t\t\tundefined,\r\n\t\t);\r\n\r\n\t\tconst clipped = unshiftMessages(fetchedMessages);\r\n\r\n\t\tconst newState = {\r\n\t\t\tnoMessagesBefore,\r\n\t\t\tnoMessagesAfter: !clipped && messagesState.current.noMessagesAfter,\r\n\t\t};\r\n\t\tmessagesState.current = newState;\r\n\t\tisFetching.current = false;\r\n\t});\r\n\r\n\tconst handleBottomReached = useEvent(async () => {\r\n\t\tif (messagesState.current.noMessagesAfter || isFetching.current) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tisFetching.current = true;\r\n\t\tconst { messages: fetchedMessages, noMessagesAfter } = await chatClient.fetchMessages(\r\n\t\t\troomIdentifier,\r\n\t\t\tadditionalChunkSize,\r\n\t\t\tundefined,\r\n\t\t\tgetMessage(-1),\r\n\t\t);\r\n\r\n\t\tconst clipped = pushMessages(fetchedMessages);\r\n\t\tconst newState = {\r\n\t\t\tnoMessagesAfter,\r\n\t\t\tnoMessagesBefore: !clipped && messagesState.current.noMessagesBefore,\r\n\t\t};\r\n\r\n\t\tmessagesState.current = newState;\r\n\t\tisFetching.current = false;\r\n\t});\r\n\r\n\tconst onVisibleFrameChange = (frame: Frame) => {\r\n\t\tvisibleFrame.current = frame;\r\n\t};\r\n\r\n\treturn {\r\n\t\tmessages,\r\n\t\tonTopReached: handleTopReached,\r\n\t\tonBottomReached: handleBottomReached,\r\n\t\tnoMessagesBefore: messagesState.current.noMessagesBefore,\r\n\t\tnoMessagesAfter: messagesState.current.noMessagesAfter,\r\n\t\tonVisibleFrameChange,\r\n\t\tcontainerReference,\r\n\t\tfocusedItem: focusedItem.current,\r\n\t};\r\n};\r\n", "export const clamp = (value: number, min: number, max: number) => Math.max(Math.min(value, max), min);\r\n", "import { useCallback, useRef, useState } from 'react';\r\n\r\nexport type KeepDirection = 'beginning' | 'ending';\r\n\r\nexport type BoundedArrayControl<T> = {\r\n\t/**\r\n\t * Add elements to the end of the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Ensures, that last item won't be clipped.\r\n\t */\r\n\tpush: (items: T[]) => boolean;\r\n\t/**\r\n\t * Add elements to the beginning of the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Ensures, that first item won't be clipped.\r\n\t */\r\n\tunshift: (items: T[]) => boolean;\r\n\t/**\r\n\t * Set all elements to the array.\r\n\t * Clips array by specified \"maxSize\".\r\n\t * Keeps elements according to \"keep\" argument's value:\r\n\t * beginning - array will be clipped from the end.\r\n\t * ending - array will be clipped from the beginning.\r\n\t */\r\n\tset: (items: T[], keep: KeepDirection) => boolean;\r\n\r\n\tinsert: (item: T, index: number, keep: KeepDirection) => boolean;\r\n\t/**\r\n\t * Works exactly like \"Array.prototype.at\".\r\n\t */\r\n\tat: (index: number) => T | undefined;\r\n\t/**\r\n\t * Returns reference to current array.\r\n\t */\r\n\tgetAll: () => readonly T[];\r\n\t/**\r\n\t * Sets state to the old one in order to rerender.\r\n\t */\r\n\trefresh: () => void;\r\n};\r\n\r\nconst getClippedArray = <T,>(items: T[], maxSize: number, keep: KeepDirection) => {\r\n\tif (items.length <= maxSize) {\r\n\t\treturn items;\r\n\t}\r\n\r\n\tif (keep === 'beginning') {\r\n\t\treturn items.slice(0, maxSize);\r\n\t}\r\n\r\n\tif (keep === 'ending') {\r\n\t\treturn items.slice(-maxSize);\r\n\t}\r\n\r\n\tthrow new Error(`Unrecognized \"keep\" option value: \"${keep}\"`);\r\n};\r\n\r\nexport const useBoundedArray = <T,>(\r\n\tinitial: T[],\r\n\tmaxChunkSize: number,\r\n): [items: T[], control: BoundedArrayControl<T>] => {\r\n\tconst [itemsState, setItemsState] = useState(initial);\r\n\tconst itemsReference = useRef(initial);\r\n\r\n\tconst setItems = useCallback(\r\n\t\t(items: T[], keep: KeepDirection) => {\r\n\t\t\tconst clippedItems = getClippedArray(items, maxChunkSize, keep);\r\n\t\t\tsetItemsState(clippedItems);\r\n\t\t\titemsReference.current = clippedItems;\r\n\r\n\t\t\treturn items.length > clippedItems.length;\r\n\t\t},\r\n\t\t[maxChunkSize],\r\n\t);\r\n\r\n\tconst unshift = useCallback(\r\n\t\t(items: T[]) => {\r\n\t\t\treturn setItems([...items, ...itemsReference.current], 'beginning');\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst push = useCallback(\r\n\t\t(items: T[]) => {\r\n\t\t\treturn setItems([...itemsReference.current, ...items], 'ending');\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst at = useCallback((index: number) => {\r\n\t\treturn itemsReference.current.at(index);\r\n\t}, []);\r\n\r\n\tconst insert = useCallback(\r\n\t\t(item: T, index: number, keep: KeepDirection) => {\r\n\t\t\titemsReference.current.splice(index, 0, item);\r\n\t\t\treturn setItems([...itemsReference.current], keep);\r\n\t\t},\r\n\t\t[setItems],\r\n\t);\r\n\r\n\tconst getAll = useCallback(() => itemsReference.current, []);\r\n\r\n\tconst refresh = useCallback(() => setItemsState((old) => [...old]), []);\r\n\r\n\treturn [itemsState, { push, unshift, set: setItems, at, getAll, insert, refresh }];\r\n};\r\n", "import { PropsWithChildren } from 'react';\r\nimport { RoomContext } from './internal/RoomContext';\r\n\r\nexport type RoomProps = PropsWithChildren<{\r\n\tidentifier: string;\r\n}>;\r\n\r\nexport const Room = ({ identifier, children }: RoomProps) => {\r\n\treturn <RoomContext.Provider value={{ roomIdentifier: identifier }}>{children}</RoomContext.Provider>;\r\n};\r\n"],
"mappings": "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",
"names": ["useCallback", "useEffect", "useLayoutEffect", "useMemo", "useRef", "useCallback", "useRef", "useRef", "useCallback", "useCallback", "useRef", "useRef", "useCallback", "useRef", "useRef", "useRef", "useEffect", "useCallback", "useRef", "useRef", "useCallback", "useRef", "useEffect", "useEffect", "useState", "useRef", "useState", "useRef", "useEffect", "observer", "useRef", "useMemo", "useEffect", "useCallback", "useLayoutEffect", "createSafeContext", "useCallback", "useEffect", "useRef", "useCallback", "useRef", "useState", "useState", "useRef", "useCallback", "useRef", "useCallback", "useEffect"]
}