Outlook_Addin_LLM/node_modules/@fluentui/priority-overflow/lib-commonjs/overflowManager.js

293 lines
12 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "createOverflowManager", {
enumerable: true,
get: function() {
return createOverflowManager;
}
});
const _consts = require("./consts");
const _createResizeObserver = require("./createResizeObserver");
const _debounce = require("./debounce");
const _priorityQueue = require("./priorityQueue");
function createOverflowManager() {
// calls to `offsetWidth or offsetHeight` can happen multiple times in an update
// Use a cache to avoid causing too many recalcs and avoid scripting time to meausure sizes
const sizeCache = new Map();
let container;
let overflowMenu;
// Set as true when resize observer is observing
let observing = false;
// If true, next update will dispatch to onUpdateOverflow even if queue top states don't change
// Initially true to force dispatch on first mount
let forceDispatch = true;
const options = {
padding: 10,
overflowAxis: 'horizontal',
overflowDirection: 'end',
minimumVisible: 0,
onUpdateItemVisibility: ()=>undefined,
onUpdateOverflow: ()=>undefined
};
const overflowItems = {};
const overflowDividers = {};
let disposeResizeObserver = ()=>null;
const getNextItem = (queueToDequeue, queueToEnqueue)=>{
const nextItem = queueToDequeue.dequeue();
queueToEnqueue.enqueue(nextItem);
return overflowItems[nextItem];
};
const groupManager = createGroupManager();
function compareItems(lt, rt) {
if (!lt || !rt) {
return 0;
}
const lte = overflowItems[lt];
const rte = overflowItems[rt];
if (lte.priority !== rte.priority) {
return lte.priority > rte.priority ? 1 : -1;
}
const positionStatusBit = options.overflowDirection === 'end' ? Node.DOCUMENT_POSITION_FOLLOWING : Node.DOCUMENT_POSITION_PRECEDING;
// eslint-disable-next-line no-bitwise
return lte.element.compareDocumentPosition(rte.element) & positionStatusBit ? 1 : -1;
}
function getElementAxisSize(horizontal, vertical, el) {
if (!sizeCache.has(el)) {
sizeCache.set(el, options.overflowAxis === 'horizontal' ? el[horizontal] : el[vertical]);
}
return sizeCache.get(el);
}
const getOffsetSize = getElementAxisSize.bind(null, 'offsetWidth', 'offsetHeight');
const getClientSize = getElementAxisSize.bind(null, 'clientWidth', 'clientHeight');
const invisibleItemQueue = (0, _priorityQueue.createPriorityQueue)((a, b)=>-1 * compareItems(a, b));
const visibleItemQueue = (0, _priorityQueue.createPriorityQueue)(compareItems);
function occupiedSize() {
const totalItemSize = visibleItemQueue.all().map((id)=>overflowItems[id].element).map(getOffsetSize).reduce((prev, current)=>prev + current, 0);
const totalDividerSize = Object.entries(groupManager.groupVisibility()).reduce((acc, [id, state])=>acc + (state !== 'hidden' && overflowDividers[id] ? getOffsetSize(overflowDividers[id].element) : 0), 0);
const overflowMenuSize = invisibleItemQueue.size() > 0 && overflowMenu ? getOffsetSize(overflowMenu) : 0;
return totalItemSize + totalDividerSize + overflowMenuSize;
}
const showItem = ()=>{
const item = getNextItem(invisibleItemQueue, visibleItemQueue);
options.onUpdateItemVisibility({
item,
visible: true
});
if (item.groupId) {
groupManager.showItem(item.id, item.groupId);
if (groupManager.isSingleItemVisible(item.id, item.groupId)) {
var _overflowDividers_item_groupId;
(_overflowDividers_item_groupId = overflowDividers[item.groupId]) === null || _overflowDividers_item_groupId === void 0 ? void 0 : _overflowDividers_item_groupId.element.removeAttribute(_consts.DATA_OVERFLOWING);
}
}
};
const hideItem = ()=>{
const item = getNextItem(visibleItemQueue, invisibleItemQueue);
options.onUpdateItemVisibility({
item,
visible: false
});
if (item.groupId) {
if (groupManager.isSingleItemVisible(item.id, item.groupId)) {
var _overflowDividers_item_groupId;
(_overflowDividers_item_groupId = overflowDividers[item.groupId]) === null || _overflowDividers_item_groupId === void 0 ? void 0 : _overflowDividers_item_groupId.element.setAttribute(_consts.DATA_OVERFLOWING, '');
}
groupManager.hideItem(item.id, item.groupId);
}
};
const dispatchOverflowUpdate = ()=>{
const visibleItemIds = visibleItemQueue.all();
const invisibleItemIds = invisibleItemQueue.all();
const visibleItems = visibleItemIds.map((itemId)=>overflowItems[itemId]);
const invisibleItems = invisibleItemIds.map((itemId)=>overflowItems[itemId]);
options.onUpdateOverflow({
visibleItems,
invisibleItems,
groupVisibility: groupManager.groupVisibility()
});
};
const processOverflowItems = ()=>{
if (!container) {
return false;
}
sizeCache.clear();
const availableSize = getClientSize(container) - options.padding;
// Snapshot of the visible/invisible state to compare for updates
const visibleTop = visibleItemQueue.peek();
const invisibleTop = invisibleItemQueue.peek();
while(compareItems(invisibleItemQueue.peek(), visibleItemQueue.peek()) > 0){
hideItem(); // hide elements whose priority become smaller than the highest priority of the hidden one
}
// Run the show/hide step twice - the first step might not be correct if
// it was triggered by a new item being added - new items are always visible by default.
for(let i = 0; i < 2; i++){
// Add items until available width is filled - can result in overflow
while(occupiedSize() < availableSize && invisibleItemQueue.size() > 0 || invisibleItemQueue.size() === 1 // attempt to show the last invisible item hoping it's size does not exceed overflow menu size
){
showItem();
}
// Remove items until there's no more overflow
while(occupiedSize() > availableSize && visibleItemQueue.size() > options.minimumVisible){
hideItem();
}
}
// only update when the state of visible/invisible items has changed
return visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop;
};
const forceUpdate = ()=>{
if (processOverflowItems() || forceDispatch) {
forceDispatch = false;
dispatchOverflowUpdate();
}
};
const update = (0, _debounce.debounce)(forceUpdate);
const observe = (observedContainer, userOptions)=>{
Object.assign(options, userOptions);
observing = true;
Object.values(overflowItems).forEach((item)=>visibleItemQueue.enqueue(item.id));
container = observedContainer;
disposeResizeObserver = (0, _createResizeObserver.observeResize)(container, (entries)=>{
if (!entries[0] || !container) {
return;
}
update();
});
};
const addItem = (item)=>{
if (overflowItems[item.id]) {
return;
}
overflowItems[item.id] = item;
// some options can affect priority which are only set on `observe`
if (observing) {
// Updates to elements might not change the queue tops
// i.e. new element is enqueued but the top of the queue stays the same
// force a dispatch on the next batched update
forceDispatch = true;
visibleItemQueue.enqueue(item.id);
}
if (item.groupId) {
groupManager.addItem(item.id, item.groupId);
item.element.setAttribute(_consts.DATA_OVERFLOW_GROUP, item.groupId);
}
update();
};
const addOverflowMenu = (el)=>{
overflowMenu = el;
};
const addDivider = (divider)=>{
if (!divider.groupId || overflowDividers[divider.groupId]) {
return;
}
divider.element.setAttribute(_consts.DATA_OVERFLOW_GROUP, divider.groupId);
overflowDividers[divider.groupId] = divider;
};
const removeOverflowMenu = ()=>{
overflowMenu = undefined;
};
const removeDivider = (groupId)=>{
if (!overflowDividers[groupId]) {
return;
}
const divider = overflowDividers[groupId];
if (divider.groupId) {
delete overflowDividers[groupId];
divider.element.removeAttribute(_consts.DATA_OVERFLOW_GROUP);
}
};
const removeItem = (itemId)=>{
if (!overflowItems[itemId]) {
return;
}
if (observing) {
// We might be removing an item in an overflow which would not affect the tops,
// but we need to update anyway to update the overflow menu state
forceDispatch = true;
}
const item = overflowItems[itemId];
visibleItemQueue.remove(itemId);
invisibleItemQueue.remove(itemId);
if (item.groupId) {
groupManager.removeItem(item.id, item.groupId);
item.element.removeAttribute(_consts.DATA_OVERFLOW_GROUP);
}
sizeCache.delete(item.element);
delete overflowItems[itemId];
update();
};
const disconnect = ()=>{
disposeResizeObserver();
// reset flags
container = undefined;
observing = false;
forceDispatch = true;
// clear all entries
Object.keys(overflowItems).forEach((itemId)=>removeItem(itemId));
Object.keys(overflowDividers).forEach((dividerId)=>removeDivider(dividerId));
removeOverflowMenu();
sizeCache.clear();
};
return {
addItem,
disconnect,
forceUpdate,
observe,
removeItem,
update,
addOverflowMenu,
removeOverflowMenu,
addDivider,
removeDivider
};
}
const createGroupManager = ()=>{
const groupVisibility = {};
const groups = {};
function updateGroupVisibility(groupId) {
const group = groups[groupId];
if (group.invisibleItemIds.size && group.visibleItemIds.size) {
groupVisibility[groupId] = 'overflow';
} else if (group.visibleItemIds.size === 0) {
groupVisibility[groupId] = 'hidden';
} else {
groupVisibility[groupId] = 'visible';
}
}
function isGroupVisible(groupId) {
return groupVisibility[groupId] === 'visible' || groupVisibility[groupId] === 'overflow';
}
return {
groupVisibility: ()=>groupVisibility,
isSingleItemVisible (itemId, groupId) {
return isGroupVisible(groupId) && groups[groupId].visibleItemIds.has(itemId) && groups[groupId].visibleItemIds.size === 1;
},
addItem (itemId, groupId) {
var _groups, _groupId;
var _;
(_ = (_groups = groups)[_groupId = groupId]) !== null && _ !== void 0 ? _ : _groups[_groupId] = {
visibleItemIds: new Set(),
invisibleItemIds: new Set()
};
groups[groupId].visibleItemIds.add(itemId);
updateGroupVisibility(groupId);
},
removeItem (itemId, groupId) {
groups[groupId].invisibleItemIds.delete(itemId);
groups[groupId].visibleItemIds.delete(itemId);
updateGroupVisibility(groupId);
},
showItem (itemId, groupId) {
groups[groupId].invisibleItemIds.delete(itemId);
groups[groupId].visibleItemIds.add(itemId);
updateGroupVisibility(groupId);
},
hideItem (itemId, groupId) {
groups[groupId].invisibleItemIds.add(itemId);
groups[groupId].visibleItemIds.delete(itemId);
updateGroupVisibility(groupId);
}
};
};