@fluentui/priority-overflow 9.3.0 → 9.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -2
- package/dist/index.d.ts +136 -39
- package/lib/consts.js +8 -0
- package/lib/consts.js.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/overflowManager.js +120 -40
- package/lib/overflowManager.js.map +1 -1
- package/lib/priorityQueue.js +9 -5
- package/lib/priorityQueue.js.map +1 -1
- package/lib/types.js +4 -0
- package/lib/types.js.map +1 -1
- package/lib-commonjs/consts.js +8 -0
- package/lib-commonjs/consts.js.map +1 -1
- package/lib-commonjs/index.js +12 -3
- package/lib-commonjs/index.js.map +1 -1
- package/lib-commonjs/overflowManager.js +116 -39
- package/lib-commonjs/overflowManager.js.map +1 -1
- package/lib-commonjs/priorityQueue.js +9 -5
- package/lib-commonjs/priorityQueue.js.map +1 -1
- package/lib-commonjs/types.js +3 -1
- package/lib-commonjs/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/overflowManager.ts"],"sourcesContent":["import { DATA_OVERFLOWING, DATA_OVERFLOW_GROUP } from './consts';\nimport { observeResize } from './createResizeObserver';\nimport { debounce } from './debounce';\nimport { createPriorityQueue, PriorityQueue } from './priorityQueue';\nimport type {\n OverflowGroupState,\n OverflowItemEntry,\n OverflowManager,\n ObserveOptions,\n OverflowDividerEntry,\n} from './types';\n\n/**\n * @internal\n * @returns overflow manager instance\n */\nexport function createOverflowManager(): OverflowManager {\n // calls to `offsetWidth or offsetHeight` can happen multiple times in an update\n // Use a cache to avoid causing too many recalcs and avoid scripting time to meausure sizes\n const sizeCache = new Map<HTMLElement, number>();\n let container: HTMLElement | undefined;\n let overflowMenu: HTMLElement | undefined;\n // Set as true when resize observer is observing\n let observing = false;\n // If true, next update will dispatch to onUpdateOverflow even if queue top states don't change\n // Initially true to force dispatch on first mount\n let forceDispatch = true;\n const options: Required<ObserveOptions> = {\n padding: 10,\n overflowAxis: 'horizontal',\n overflowDirection: 'end',\n minimumVisible: 0,\n onUpdateItemVisibility: () => undefined,\n onUpdateOverflow: () => undefined,\n hasHiddenItems: false,\n };\n\n const overflowItems: Record<string, OverflowItemEntry> = {};\n const overflowDividers: Record<string, OverflowDividerEntry> = {};\n let disposeResizeObserver: () => void = () => null;\n\n const getNextItem = (queueToDequeue: PriorityQueue<string>, queueToEnqueue: PriorityQueue<string>) => {\n const nextItem = queueToDequeue.dequeue();\n queueToEnqueue.enqueue(nextItem);\n return overflowItems[nextItem];\n };\n\n const groupManager = createGroupManager();\n\n function compareItems(lt: string | null, rt: string | null): number {\n if (!lt || !rt) {\n return 0;\n }\n\n const lte = overflowItems[lt];\n const rte = overflowItems[rt];\n\n // TODO this should not happen but there have been reports of one of these items being undefined\n // Try to find a consistent repro for this\n if (!lte || !rte) {\n return lte ? 1 : -1;\n }\n\n // Pinned items have \"infinite\" priority - they should never be hidden\n if (lte.pinned !== rte.pinned) {\n return lte.pinned ? 1 : -1;\n }\n\n if (lte.priority !== rte.priority) {\n return lte.priority > rte.priority ? 1 : -1;\n }\n\n // Node.DOCUMENT_POSITION_FOLLOWING = 4, Node.DOCUMENT_POSITION_PRECEDING = 2\n const positionStatusBit = options.overflowDirection === 'end' ? 4 : 2;\n\n // eslint-disable-next-line no-bitwise\n return lte.element.compareDocumentPosition(rte.element) & positionStatusBit ? 1 : -1;\n }\n\n function getElementAxisSize(\n horizontal: 'clientWidth' | 'offsetWidth',\n vertical: 'clientHeight' | 'offsetHeight',\n el: HTMLElement,\n ): number {\n if (!sizeCache.has(el)) {\n sizeCache.set(el, options.overflowAxis === 'horizontal' ? el[horizontal] : el[vertical]);\n }\n\n return sizeCache.get(el)!;\n }\n\n const getOffsetSize = getElementAxisSize.bind(null, 'offsetWidth', 'offsetHeight');\n const getClientSize = getElementAxisSize.bind(null, 'clientWidth', 'clientHeight');\n\n const invisibleItemQueue = createPriorityQueue<string>((a, b) => -1 * compareItems(a, b));\n\n const visibleItemQueue = createPriorityQueue<string>(compareItems);\n\n function occupiedSize(): number {\n const totalItemSize = visibleItemQueue\n .all()\n .map(id => overflowItems[id].element)\n .map(getOffsetSize)\n .reduce((prev, current) => prev + current, 0);\n\n const totalDividerSize = Object.entries(groupManager.groupVisibility()).reduce(\n (acc, [id, state]) =>\n acc + (state !== 'hidden' && overflowDividers[id] ? getOffsetSize(overflowDividers[id].element) : 0),\n 0,\n );\n\n const overflowMenuSize =\n (invisibleItemQueue.size() > 0 || options.hasHiddenItems) && overflowMenu ? getOffsetSize(overflowMenu) : 0;\n\n return totalItemSize + totalDividerSize + overflowMenuSize;\n }\n\n const showItem = () => {\n const item = getNextItem(invisibleItemQueue, visibleItemQueue);\n options.onUpdateItemVisibility({ item, visible: true });\n\n if (item.groupId) {\n groupManager.showItem(item.id, item.groupId);\n\n if (groupManager.isSingleItemVisible(item.id, item.groupId)) {\n overflowDividers[item.groupId]?.element.removeAttribute(DATA_OVERFLOWING);\n }\n }\n };\n\n const hideItem = () => {\n const item = getNextItem(visibleItemQueue, invisibleItemQueue);\n options.onUpdateItemVisibility({ item, visible: false });\n\n if (item.groupId) {\n if (groupManager.isSingleItemVisible(item.id, item.groupId)) {\n overflowDividers[item.groupId]?.element.setAttribute(DATA_OVERFLOWING, '');\n }\n\n groupManager.hideItem(item.id, item.groupId);\n }\n };\n\n const dispatchOverflowUpdate = () => {\n const visibleItemIds = visibleItemQueue.all();\n const invisibleItemIds = invisibleItemQueue.all();\n\n const visibleItems = visibleItemIds.map(itemId => overflowItems[itemId]);\n const invisibleItems = invisibleItemIds.map(itemId => overflowItems[itemId]);\n\n options.onUpdateOverflow({ visibleItems, invisibleItems, groupVisibility: groupManager.groupVisibility() });\n };\n\n const processOverflowItems = (): boolean => {\n if (!container) {\n return false;\n }\n sizeCache.clear();\n\n const availableSize = getClientSize(container) - options.padding;\n\n // Snapshot of the visible/invisible state to compare for updates\n const visibleTop = visibleItemQueue.peek();\n const invisibleTop = invisibleItemQueue.peek();\n\n while (compareItems(invisibleItemQueue.peek(), visibleItemQueue.peek()) > 0) {\n hideItem(); // hide elements whose priority become smaller than the highest priority of the hidden one\n }\n\n // Run the show/hide step twice - the first step might not be correct if\n // it was triggered by a new item being added - new items are always visible by default.\n for (let i = 0; i < 2; i++) {\n // Add items until available width is filled - can result in overflow\n while (\n (occupiedSize() < availableSize && invisibleItemQueue.size() > 0) ||\n invisibleItemQueue.size() === 1 // attempt to show the last invisible item hoping it's size does not exceed overflow menu size\n ) {\n showItem();\n }\n\n // Remove items until there's no more overflow\n while (occupiedSize() > availableSize && visibleItemQueue.size() > options.minimumVisible) {\n const nextItemId = visibleItemQueue.peek();\n\n // Never hide pinned items - they should always remain visible\n if (nextItemId && overflowItems[nextItemId]?.pinned) {\n break;\n }\n\n hideItem();\n }\n }\n\n // only update when the state of visible/invisible items has changed\n return visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop;\n };\n\n const forceUpdate: OverflowManager['forceUpdate'] = () => {\n if (processOverflowItems() || forceDispatch) {\n forceDispatch = false;\n dispatchOverflowUpdate();\n }\n };\n\n const update: OverflowManager['update'] = debounce(forceUpdate);\n\n const observe: OverflowManager['observe'] = (observedContainer, userOptions) => {\n Object.assign(options, userOptions);\n observing = true;\n Object.values(overflowItems).forEach(item => visibleItemQueue.enqueue(item.id));\n\n container = observedContainer;\n disposeResizeObserver = observeResize(container, entries => {\n if (!entries[0] || !container) {\n return;\n }\n\n update();\n });\n };\n\n const addItem: OverflowManager['addItem'] = item => {\n if (overflowItems[item.id]) {\n return;\n }\n\n overflowItems[item.id] = item;\n\n // some options can affect priority which are only set on `observe`\n if (observing) {\n // Updates to elements might not change the queue tops\n // i.e. new element is enqueued but the top of the queue stays the same\n // force a dispatch on the next batched update\n forceDispatch = true;\n visibleItemQueue.enqueue(item.id);\n }\n\n if (item.groupId) {\n groupManager.addItem(item.id, item.groupId);\n item.element.setAttribute(DATA_OVERFLOW_GROUP, item.groupId);\n }\n\n update();\n };\n\n const addOverflowMenu: OverflowManager['addOverflowMenu'] = el => {\n overflowMenu = el;\n };\n\n const addDivider: OverflowManager['addDivider'] = divider => {\n if (!divider.groupId || overflowDividers[divider.groupId]) {\n return;\n }\n\n divider.element.setAttribute(DATA_OVERFLOW_GROUP, divider.groupId);\n overflowDividers[divider.groupId] = divider;\n };\n\n const removeOverflowMenu: OverflowManager['removeOverflowMenu'] = () => {\n overflowMenu = undefined;\n };\n\n const removeDivider: OverflowManager['removeDivider'] = groupId => {\n if (!overflowDividers[groupId]) {\n return;\n }\n const divider = overflowDividers[groupId];\n if (divider.groupId) {\n delete overflowDividers[groupId];\n divider.element.removeAttribute(DATA_OVERFLOW_GROUP);\n }\n };\n\n const removeItem: OverflowManager['removeItem'] = itemId => {\n if (!overflowItems[itemId]) {\n return;\n }\n\n if (observing) {\n // We might be removing an item in an overflow which would not affect the tops,\n // but we need to update anyway to update the overflow menu state\n forceDispatch = true;\n }\n\n const item = overflowItems[itemId];\n visibleItemQueue.remove(itemId);\n invisibleItemQueue.remove(itemId);\n\n if (item.groupId) {\n groupManager.removeItem(item.id, item.groupId);\n item.element.removeAttribute(DATA_OVERFLOW_GROUP);\n }\n\n sizeCache.delete(item.element);\n delete overflowItems[itemId];\n update();\n };\n\n const disconnect: OverflowManager['disconnect'] = () => {\n disposeResizeObserver();\n\n // reset flags\n container = undefined;\n observing = false;\n forceDispatch = true;\n\n // clear all entries\n Object.keys(overflowItems).forEach(itemId => removeItem(itemId));\n Object.keys(overflowDividers).forEach(dividerId => removeDivider(dividerId));\n removeOverflowMenu();\n sizeCache.clear();\n };\n\n return {\n addItem,\n disconnect,\n forceUpdate,\n observe,\n removeItem,\n update,\n addOverflowMenu,\n removeOverflowMenu,\n addDivider,\n removeDivider,\n };\n}\n\nconst createGroupManager = () => {\n const groupVisibility: Record<string, OverflowGroupState> = {};\n const groups: Record<string, { visibleItemIds: Set<string>; invisibleItemIds: Set<string> }> = {};\n function updateGroupVisibility(groupId: string) {\n const group = groups[groupId];\n if (group.invisibleItemIds.size && group.visibleItemIds.size) {\n groupVisibility[groupId] = 'overflow';\n } else if (group.visibleItemIds.size === 0) {\n groupVisibility[groupId] = 'hidden';\n } else {\n groupVisibility[groupId] = 'visible';\n }\n }\n function isGroupVisible(groupId: string) {\n return groupVisibility[groupId] === 'visible' || groupVisibility[groupId] === 'overflow';\n }\n return {\n groupVisibility: () => groupVisibility,\n isSingleItemVisible(itemId: string, groupId: string) {\n return (\n isGroupVisible(groupId) &&\n groups[groupId].visibleItemIds.has(itemId) &&\n groups[groupId].visibleItemIds.size === 1\n );\n },\n addItem(itemId: string, groupId: string) {\n groups[groupId] ??= {\n visibleItemIds: new Set<string>(),\n invisibleItemIds: new Set<string>(),\n };\n\n groups[groupId].visibleItemIds.add(itemId);\n updateGroupVisibility(groupId);\n },\n removeItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.delete(itemId);\n groups[groupId].visibleItemIds.delete(itemId);\n updateGroupVisibility(groupId);\n },\n showItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.delete(itemId);\n groups[groupId].visibleItemIds.add(itemId);\n updateGroupVisibility(groupId);\n },\n hideItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.add(itemId);\n groups[groupId].visibleItemIds.delete(itemId);\n updateGroupVisibility(groupId);\n },\n };\n};\n"],"names":["DATA_OVERFLOWING","DATA_OVERFLOW_GROUP","observeResize","debounce","createPriorityQueue","createOverflowManager","sizeCache","Map","container","overflowMenu","observing","forceDispatch","options","padding","overflowAxis","overflowDirection","minimumVisible","onUpdateItemVisibility","undefined","onUpdateOverflow","hasHiddenItems","overflowItems","overflowDividers","disposeResizeObserver","getNextItem","queueToDequeue","queueToEnqueue","nextItem","dequeue","enqueue","groupManager","createGroupManager","compareItems","lt","rt","lte","rte","pinned","priority","positionStatusBit","element","compareDocumentPosition","getElementAxisSize","horizontal","vertical","el","has","set","get","getOffsetSize","bind","getClientSize","invisibleItemQueue","a","b","visibleItemQueue","occupiedSize","totalItemSize","all","map","id","reduce","prev","current","totalDividerSize","Object","entries","groupVisibility","acc","state","overflowMenuSize","size","showItem","item","visible","groupId","isSingleItemVisible","removeAttribute","hideItem","setAttribute","dispatchOverflowUpdate","visibleItemIds","invisibleItemIds","visibleItems","itemId","invisibleItems","processOverflowItems","clear","availableSize","visibleTop","peek","invisibleTop","i","nextItemId","forceUpdate","update","observe","observedContainer","userOptions","assign","values","forEach","addItem","addOverflowMenu","addDivider","divider","removeOverflowMenu","removeDivider","removeItem","remove","delete","disconnect","keys","dividerId","groups","updateGroupVisibility","group","isGroupVisible","Set","add"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../src/overflowManager.ts"],"sourcesContent":["import { DATA_OVERFLOWING, DATA_OVERFLOW_GROUP, EMPTY_SNAPSHOT } from './consts';\nimport { observeResize } from './createResizeObserver';\nimport { debounce } from './debounce';\nimport type { PriorityQueue } from './priorityQueue';\nimport { createPriorityQueue } from './priorityQueue';\nimport type {\n OverflowGroupState,\n OverflowItemEntry,\n OverflowManager,\n OverflowOptions,\n OverflowDividerEntry,\n OverflowSnapshot,\n} from './types';\n\nconst DEFAULT_OPTIONS: Required<OverflowOptions> = {\n overflowAxis: 'horizontal',\n overflowDirection: 'end',\n padding: 10,\n minimumVisible: 0,\n hasHiddenItems: false,\n onUpdateItemVisibility: () => {\n /* noop */\n },\n onUpdateOverflow: () => {\n /* noop */\n },\n};\n\n/**\n * Creates an overflow manager instance for a single container.\n *\n * @internal\n * @param initialOptions - Initial observe options. Missing values are filled with defaults.\n * @returns overflow manager instance\n */\nexport function createOverflowManager(initialOptions: Partial<OverflowOptions> = {}): OverflowManager {\n // calls to `offsetWidth or offsetHeight` can happen multiple times in an update\n // Use a cache to avoid causing too many recalcs and avoid scripting time to meausure sizes\n const sizeCache = new Map<HTMLElement, number>();\n let container: HTMLElement | undefined;\n let overflowMenu: HTMLElement | undefined;\n // Set as true when resize observer is observing\n let observing = false;\n // If true, next update will dispatch to onUpdateOverflow even if queue top states don't change\n // Initially true to force dispatch on first mount\n let forceDispatch = true;\n const options: Required<OverflowOptions> = { ...DEFAULT_OPTIONS, ...initialOptions };\n const overflowItems: Record<string, OverflowItemEntry> = {};\n const overflowDividers: Record<string, OverflowDividerEntry> = {};\n const listeners = new Set<() => void>();\n let disposeResizeObserver: () => void = () => {\n /* noop */\n };\n\n let snapshot: OverflowSnapshot = EMPTY_SNAPSHOT;\n const takeSnapshot = (nextSnapshot: OverflowSnapshot) => {\n snapshot = nextSnapshot;\n listeners.forEach(listener => listener());\n };\n\n const getNextItem = (queueToDequeue: PriorityQueue<string>, queueToEnqueue: PriorityQueue<string>) => {\n const nextItem = queueToDequeue.dequeue();\n queueToEnqueue.enqueue(nextItem);\n return overflowItems[nextItem];\n };\n\n const groupManager = createGroupManager();\n\n function compareItems(lt: string | null, rt: string | null): number {\n if (!lt || !rt) {\n return 0;\n }\n\n const lte = overflowItems[lt];\n const rte = overflowItems[rt];\n\n // TODO this should not happen but there have been reports of one of these items being undefined\n // Try to find a consistent repro for this\n if (!lte || !rte) {\n return lte ? 1 : -1;\n }\n\n // Pinned items have \"infinite\" priority - they should never be hidden\n if (lte.pinned !== rte.pinned) {\n return lte.pinned ? 1 : -1;\n }\n\n if (lte.priority !== rte.priority) {\n return lte.priority > rte.priority ? 1 : -1;\n }\n\n // Node.DOCUMENT_POSITION_FOLLOWING = 4, Node.DOCUMENT_POSITION_PRECEDING = 2\n const positionStatusBit = options.overflowDirection === 'end' ? 4 : 2;\n\n // eslint-disable-next-line no-bitwise\n return lte.element.compareDocumentPosition(rte.element) & positionStatusBit ? 1 : -1;\n }\n\n function getElementAxisSize(\n horizontal: 'clientWidth' | 'offsetWidth',\n vertical: 'clientHeight' | 'offsetHeight',\n el: HTMLElement,\n ): number {\n if (!sizeCache.has(el)) {\n sizeCache.set(el, options.overflowAxis === 'horizontal' ? el[horizontal] : el[vertical]);\n }\n\n return sizeCache.get(el)!;\n }\n\n const getOffsetSize = getElementAxisSize.bind(null, 'offsetWidth', 'offsetHeight');\n const getClientSize = getElementAxisSize.bind(null, 'clientWidth', 'clientHeight');\n\n const invisibleItemQueue = createPriorityQueue<string>((a, b) => -1 * compareItems(a, b));\n\n const visibleItemQueue = createPriorityQueue<string>(compareItems);\n\n function occupiedSize(): number {\n let totalItemSize = 0;\n for (const id of visibleItemQueue) {\n totalItemSize += getOffsetSize(overflowItems[id].element);\n }\n\n const totalDividerSize = Object.entries(groupManager.groupVisibility()).reduce(\n (acc, [id, state]) =>\n acc + (state !== 'hidden' && overflowDividers[id] ? getOffsetSize(overflowDividers[id].element) : 0),\n 0,\n );\n\n const overflowMenuSize =\n (invisibleItemQueue.size() > 0 || options.hasHiddenItems) && overflowMenu ? getOffsetSize(overflowMenu) : 0;\n\n return totalItemSize + totalDividerSize + overflowMenuSize;\n }\n\n const showItem = () => {\n const item = getNextItem(invisibleItemQueue, visibleItemQueue);\n options.onUpdateItemVisibility({ item, visible: true });\n\n if (item.groupId) {\n groupManager.showItem(item.id, item.groupId);\n\n if (groupManager.isSingleItemVisible(item.id, item.groupId)) {\n overflowDividers[item.groupId]?.element.removeAttribute(DATA_OVERFLOWING);\n }\n }\n };\n\n const hideItem = () => {\n const item = getNextItem(visibleItemQueue, invisibleItemQueue);\n options.onUpdateItemVisibility({ item, visible: false });\n\n if (item.groupId) {\n if (groupManager.isSingleItemVisible(item.id, item.groupId)) {\n overflowDividers[item.groupId]?.element.setAttribute(DATA_OVERFLOWING, '');\n }\n\n groupManager.hideItem(item.id, item.groupId);\n }\n };\n\n const dispatchOverflowUpdate = () => {\n const groupVisibility = groupManager.groupVisibility();\n\n // Build the legacy ordered-entry arrays and the snapshot's id -> visible map in a single pass\n // over each queue.\n const itemVisibility: Record<string, boolean> = {};\n const visibleItems: OverflowItemEntry[] = [];\n const invisibleItems: OverflowItemEntry[] = [];\n\n for (const itemId of visibleItemQueue) {\n itemVisibility[itemId] = true;\n visibleItems.push(overflowItems[itemId]);\n }\n for (const itemId of invisibleItemQueue) {\n itemVisibility[itemId] = false;\n invisibleItems.push(overflowItems[itemId]);\n }\n\n // Set the snapshot first so `getSnapshot()` is current for both subscribers and any\n // `onUpdateOverflow` consumer that reads it.\n takeSnapshot({\n itemVisibility,\n groupVisibility,\n invisibleItemCount: invisibleItems.length,\n });\n\n // Legacy event payload: ordered item entries for `onUpdateOverflow` consumers.\n options.onUpdateOverflow({ visibleItems, invisibleItems, groupVisibility });\n };\n\n const getSnapshot: OverflowManager['getSnapshot'] = () => snapshot;\n\n const processOverflowItems = (): boolean => {\n if (!container) {\n return false;\n }\n sizeCache.clear();\n\n const availableSize = getClientSize(container) - options.padding;\n\n // Snapshot of the visible/invisible state to compare for updates\n const visibleTop = visibleItemQueue.peek();\n const invisibleTop = invisibleItemQueue.peek();\n\n while (compareItems(invisibleItemQueue.peek(), visibleItemQueue.peek()) > 0) {\n hideItem(); // hide elements whose priority become smaller than the highest priority of the hidden one\n }\n\n // Run the show/hide step twice - the first step might not be correct if\n // it was triggered by a new item being added - new items are always visible by default.\n for (let i = 0; i < 2; i++) {\n // Add items until available width is filled - can result in overflow\n while (\n (occupiedSize() < availableSize && invisibleItemQueue.size() > 0) ||\n invisibleItemQueue.size() === 1 // attempt to show the last invisible item hoping it's size does not exceed overflow menu size\n ) {\n showItem();\n }\n\n // Remove items until there's no more overflow\n while (occupiedSize() > availableSize && visibleItemQueue.size() > options.minimumVisible) {\n const nextItemId = visibleItemQueue.peek();\n\n // Never hide pinned items - they should always remain visible\n if (nextItemId && overflowItems[nextItemId]?.pinned) {\n break;\n }\n\n hideItem();\n }\n }\n\n // only update when the state of visible/invisible items has changed\n return visibleItemQueue.peek() !== visibleTop || invisibleItemQueue.peek() !== invisibleTop;\n };\n\n const forceUpdate: OverflowManager['forceUpdate'] = () => {\n if (processOverflowItems() || forceDispatch) {\n forceDispatch = false;\n dispatchOverflowUpdate();\n }\n };\n\n const update: OverflowManager['update'] = debounce(forceUpdate);\n\n const setOptions: OverflowManager['setOptions'] = nextOptions => {\n if (options === nextOptions) {\n return;\n }\n\n const shouldTriggerUpdate =\n (nextOptions.overflowAxis && options.overflowAxis !== nextOptions.overflowAxis) ||\n (nextOptions.overflowDirection && options.overflowDirection !== nextOptions.overflowDirection) ||\n (nextOptions.padding && options.padding !== nextOptions.padding) ||\n (nextOptions.minimumVisible && options.minimumVisible !== nextOptions.minimumVisible) ||\n (nextOptions.hasHiddenItems && options.hasHiddenItems !== nextOptions.hasHiddenItems);\n\n Object.assign(options, nextOptions);\n\n if (shouldTriggerUpdate) {\n forceDispatch = true;\n update();\n }\n };\n\n const observe: OverflowManager['observe'] = (observedContainer, observeOptions) => {\n const { forceUpdate: shouldForceUpdate, ...userOptions } = observeOptions ?? {};\n Object.assign(options, userOptions);\n\n Object.values(overflowItems).forEach(item => {\n if (!visibleItemQueue.contains(item.id) && !invisibleItemQueue.contains(item.id)) {\n visibleItemQueue.enqueue(item.id);\n }\n });\n\n container = observedContainer;\n observing = true;\n disposeResizeObserver = observeResize(container, entries => {\n if (!entries[0] || !container) {\n return;\n }\n update();\n });\n\n if (shouldForceUpdate && getClientSize(observedContainer) > 0) {\n forceUpdate();\n }\n };\n\n const disconnect: OverflowManager['disconnect'] = () => {\n disposeResizeObserver();\n disposeResizeObserver = () => {\n /* noop */\n };\n\n // reset flags\n container = undefined;\n observing = false;\n forceDispatch = true;\n\n // clear all entries\n Object.keys(overflowItems).forEach(itemId => removeItem(itemId));\n Object.keys(overflowDividers).forEach(dividerId => removeDivider(dividerId));\n removeOverflowMenu();\n sizeCache.clear();\n\n // notify subscribers that the manager is no longer tracking anything\n takeSnapshot(EMPTY_SNAPSHOT);\n };\n\n const addItem: OverflowManager['addItem'] = items => {\n if (overflowItems[items.id]) {\n return;\n }\n\n overflowItems[items.id] = items;\n\n // some options can affect priority which are only set on `observe`\n if (observing) {\n // Updates to elements might not change the queue tops\n // i.e. new element is enqueued but the top of the queue stays the same\n // force a dispatch on the next batched update\n forceDispatch = true;\n visibleItemQueue.enqueue(items.id);\n update();\n }\n\n if (items.groupId) {\n groupManager.addItem(items.id, items.groupId);\n items.element.setAttribute(DATA_OVERFLOW_GROUP, items.groupId);\n }\n };\n\n const addOverflowMenu: OverflowManager['addOverflowMenu'] = el => {\n overflowMenu = el;\n\n if (observing) {\n forceDispatch = true;\n update();\n }\n };\n\n const addDivider: OverflowManager['addDivider'] = divider => {\n if (!divider.groupId || overflowDividers[divider.groupId]) {\n return;\n }\n\n divider.element.setAttribute(DATA_OVERFLOW_GROUP, divider.groupId);\n overflowDividers[divider.groupId] = divider;\n };\n\n const removeOverflowMenu: OverflowManager['removeOverflowMenu'] = () => {\n overflowMenu = undefined;\n\n if (observing) {\n forceDispatch = true;\n update();\n }\n };\n\n const removeDivider: OverflowManager['removeDivider'] = groupId => {\n if (!overflowDividers[groupId]) {\n return;\n }\n const divider = overflowDividers[groupId];\n if (divider.groupId) {\n delete overflowDividers[groupId];\n divider.element.removeAttribute(DATA_OVERFLOW_GROUP);\n }\n };\n\n const removeItem: OverflowManager['removeItem'] = itemId => {\n if (!overflowItems[itemId]) {\n return;\n }\n\n if (observing) {\n // We might be removing an item in an overflow which would not affect the tops,\n // but we need to update anyway to update the overflow menu state\n forceDispatch = true;\n }\n\n const item = overflowItems[itemId];\n visibleItemQueue.remove(itemId);\n invisibleItemQueue.remove(itemId);\n\n if (item.groupId) {\n groupManager.removeItem(item.id, item.groupId);\n item.element.removeAttribute(DATA_OVERFLOW_GROUP);\n }\n\n sizeCache.delete(item.element);\n delete overflowItems[itemId];\n if (observing) {\n update();\n }\n };\n\n const subscribe: OverflowManager['subscribe'] = listener => {\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n };\n };\n\n return {\n addItem,\n disconnect,\n forceUpdate,\n observe,\n removeItem,\n update,\n addOverflowMenu,\n removeOverflowMenu,\n addDivider,\n removeDivider,\n setOptions,\n getSnapshot,\n subscribe,\n };\n}\n\nconst createGroupManager = () => {\n const groupVisibility: Record<string, OverflowGroupState> = {};\n const groups: Record<string, { visibleItemIds: Set<string>; invisibleItemIds: Set<string> }> = {};\n function updateGroupVisibility(groupId: string) {\n const group = groups[groupId];\n if (group.invisibleItemIds.size && group.visibleItemIds.size) {\n groupVisibility[groupId] = 'overflow';\n } else if (group.visibleItemIds.size === 0) {\n groupVisibility[groupId] = 'hidden';\n } else {\n groupVisibility[groupId] = 'visible';\n }\n }\n function isGroupVisible(groupId: string) {\n return groupVisibility[groupId] === 'visible' || groupVisibility[groupId] === 'overflow';\n }\n return {\n groupVisibility: () => groupVisibility,\n isSingleItemVisible(itemId: string, groupId: string) {\n return (\n isGroupVisible(groupId) &&\n groups[groupId].visibleItemIds.has(itemId) &&\n groups[groupId].visibleItemIds.size === 1\n );\n },\n addItem(itemId: string, groupId: string) {\n groups[groupId] ??= {\n visibleItemIds: new Set<string>(),\n invisibleItemIds: new Set<string>(),\n };\n\n groups[groupId].visibleItemIds.add(itemId);\n updateGroupVisibility(groupId);\n },\n removeItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.delete(itemId);\n groups[groupId].visibleItemIds.delete(itemId);\n updateGroupVisibility(groupId);\n },\n showItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.delete(itemId);\n groups[groupId].visibleItemIds.add(itemId);\n updateGroupVisibility(groupId);\n },\n hideItem(itemId: string, groupId: string) {\n groups[groupId].invisibleItemIds.add(itemId);\n groups[groupId].visibleItemIds.delete(itemId);\n updateGroupVisibility(groupId);\n },\n };\n};\n"],"names":["DATA_OVERFLOWING","DATA_OVERFLOW_GROUP","EMPTY_SNAPSHOT","observeResize","debounce","createPriorityQueue","DEFAULT_OPTIONS","overflowAxis","overflowDirection","padding","minimumVisible","hasHiddenItems","onUpdateItemVisibility","onUpdateOverflow","createOverflowManager","initialOptions","sizeCache","Map","container","overflowMenu","observing","forceDispatch","options","overflowItems","overflowDividers","listeners","Set","disposeResizeObserver","snapshot","takeSnapshot","nextSnapshot","forEach","listener","getNextItem","queueToDequeue","queueToEnqueue","nextItem","dequeue","enqueue","groupManager","createGroupManager","compareItems","lt","rt","lte","rte","pinned","priority","positionStatusBit","element","compareDocumentPosition","getElementAxisSize","horizontal","vertical","el","has","set","get","getOffsetSize","bind","getClientSize","invisibleItemQueue","a","b","visibleItemQueue","occupiedSize","totalItemSize","id","totalDividerSize","Object","entries","groupVisibility","reduce","acc","state","overflowMenuSize","size","showItem","item","visible","groupId","isSingleItemVisible","removeAttribute","hideItem","setAttribute","dispatchOverflowUpdate","itemVisibility","visibleItems","invisibleItems","itemId","push","invisibleItemCount","length","getSnapshot","processOverflowItems","clear","availableSize","visibleTop","peek","invisibleTop","i","nextItemId","forceUpdate","update","setOptions","nextOptions","shouldTriggerUpdate","assign","observe","observedContainer","observeOptions","shouldForceUpdate","userOptions","values","contains","disconnect","undefined","keys","removeItem","dividerId","removeDivider","removeOverflowMenu","addItem","items","addOverflowMenu","addDivider","divider","remove","delete","subscribe","add","groups","updateGroupVisibility","group","invisibleItemIds","visibleItemIds","isGroupVisible"],"mappings":"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"}
|
package/lib/priorityQueue.js
CHANGED
|
@@ -73,17 +73,21 @@
|
|
|
73
73
|
const clear = ()=>{
|
|
74
74
|
size = 0;
|
|
75
75
|
};
|
|
76
|
-
const all = ()=>{
|
|
77
|
-
return arr.slice(0, size);
|
|
78
|
-
};
|
|
79
76
|
return {
|
|
80
|
-
all,
|
|
81
77
|
clear,
|
|
82
78
|
contains,
|
|
83
79
|
dequeue,
|
|
84
80
|
enqueue,
|
|
85
81
|
peek,
|
|
86
82
|
remove,
|
|
87
|
-
size: ()=>size
|
|
83
|
+
size: ()=>size,
|
|
84
|
+
// Iterates items in heap order, without allocating an intermediate array. Bounded by `size`:
|
|
85
|
+
// `arr` keeps stale entries past `size` (dequeue/remove/clear shrink `size`, not `arr`), so the
|
|
86
|
+
// array's own iterator would yield removed items.
|
|
87
|
+
*[Symbol.iterator] () {
|
|
88
|
+
for(let index = 0; index < size; index++){
|
|
89
|
+
yield arr[index];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
88
92
|
};
|
|
89
93
|
}
|
package/lib/priorityQueue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/priorityQueue.ts"],"sourcesContent":["export type PriorityQueueCompareFn<T> = (a: T, b: T) => number;\n\nexport interface PriorityQueue<T> {\n
|
|
1
|
+
{"version":3,"sources":["../src/priorityQueue.ts"],"sourcesContent":["export type PriorityQueueCompareFn<T> = (a: T, b: T) => number;\n\nexport interface PriorityQueue<T> extends Iterable<T> {\n clear: () => void;\n contains: (item: T) => boolean;\n dequeue: () => T;\n enqueue: (item: T) => void;\n peek: () => T | null;\n remove: (item: T) => void;\n size: () => number;\n}\n\n/**\n * @param compare - comparison function for items\n * @returns Priority queue implemented with a min heap\n */\nexport function createPriorityQueue<T>(compare: PriorityQueueCompareFn<T>): PriorityQueue<T> {\n const arr: T[] = [];\n let size = 0;\n\n const left = (i: number) => {\n return 2 * i + 1;\n };\n\n const right = (i: number) => {\n return 2 * i + 2;\n };\n\n const parent = (i: number) => {\n return Math.floor((i - 1) / 2);\n };\n\n const swap = (a: number, b: number) => {\n const tmp = arr[a];\n arr[a] = arr[b];\n arr[b] = tmp;\n };\n\n const heapify = (i: number) => {\n let smallest = i;\n const l = left(i);\n const r = right(i);\n\n if (l < size && compare(arr[l], arr[smallest]) < 0) {\n smallest = l;\n }\n\n if (r < size && compare(arr[r], arr[smallest]) < 0) {\n smallest = r;\n }\n\n if (smallest !== i) {\n swap(smallest, i);\n heapify(smallest);\n }\n };\n\n const dequeue = () => {\n if (size === 0) {\n throw new Error('Priority queue empty');\n }\n\n const res = arr[0];\n arr[0] = arr[--size];\n heapify(0);\n\n return res;\n };\n\n const peek = () => {\n if (size === 0) {\n return null;\n }\n\n return arr[0];\n };\n\n const enqueue = (item: T) => {\n arr[size++] = item;\n let i = size - 1;\n let p = parent(i);\n while (i > 0 && compare(arr[p], arr[i]) > 0) {\n swap(p, i);\n i = p;\n p = parent(i);\n }\n };\n\n const contains = (item: T) => {\n const index = arr.indexOf(item);\n return index >= 0 && index < size;\n };\n\n const remove = (item: T) => {\n const i = arr.indexOf(item);\n\n if (i === -1 || i >= size) {\n return;\n }\n\n arr[i] = arr[--size];\n heapify(i);\n };\n\n const clear = () => {\n size = 0;\n };\n\n return {\n clear,\n contains,\n dequeue,\n enqueue,\n peek,\n remove,\n size: () => size,\n // Iterates items in heap order, without allocating an intermediate array. Bounded by `size`:\n // `arr` keeps stale entries past `size` (dequeue/remove/clear shrink `size`, not `arr`), so the\n // array's own iterator would yield removed items.\n *[Symbol.iterator]() {\n for (let index = 0; index < size; index++) {\n yield arr[index];\n }\n },\n };\n}\n"],"names":["createPriorityQueue","compare","arr","size","left","i","right","parent","Math","floor","swap","a","b","tmp","heapify","smallest","l","r","dequeue","Error","res","peek","enqueue","item","p","contains","index","indexOf","remove","clear","Symbol","iterator"],"mappings":"AAYA;;;CAGC,GACD,OAAO,SAASA,oBAAuBC,OAAkC;IACvE,MAAMC,MAAW,EAAE;IACnB,IAAIC,OAAO;IAEX,MAAMC,OAAO,CAACC;QACZ,OAAO,IAAIA,IAAI;IACjB;IAEA,MAAMC,QAAQ,CAACD;QACb,OAAO,IAAIA,IAAI;IACjB;IAEA,MAAME,SAAS,CAACF;QACd,OAAOG,KAAKC,KAAK,CAAC,AAACJ,CAAAA,IAAI,CAAA,IAAK;IAC9B;IAEA,MAAMK,OAAO,CAACC,GAAWC;QACvB,MAAMC,MAAMX,GAAG,CAACS,EAAE;QAClBT,GAAG,CAACS,EAAE,GAAGT,GAAG,CAACU,EAAE;QACfV,GAAG,CAACU,EAAE,GAAGC;IACX;IAEA,MAAMC,UAAU,CAACT;QACf,IAAIU,WAAWV;QACf,MAAMW,IAAIZ,KAAKC;QACf,MAAMY,IAAIX,MAAMD;QAEhB,IAAIW,IAAIb,QAAQF,QAAQC,GAAG,CAACc,EAAE,EAAEd,GAAG,CAACa,SAAS,IAAI,GAAG;YAClDA,WAAWC;QACb;QAEA,IAAIC,IAAId,QAAQF,QAAQC,GAAG,CAACe,EAAE,EAAEf,GAAG,CAACa,SAAS,IAAI,GAAG;YAClDA,WAAWE;QACb;QAEA,IAAIF,aAAaV,GAAG;YAClBK,KAAKK,UAAUV;YACfS,QAAQC;QACV;IACF;IAEA,MAAMG,UAAU;QACd,IAAIf,SAAS,GAAG;YACd,MAAM,IAAIgB,MAAM;QAClB;QAEA,MAAMC,MAAMlB,GAAG,CAAC,EAAE;QAClBA,GAAG,CAAC,EAAE,GAAGA,GAAG,CAAC,EAAEC,KAAK;QACpBW,QAAQ;QAER,OAAOM;IACT;IAEA,MAAMC,OAAO;QACX,IAAIlB,SAAS,GAAG;YACd,OAAO;QACT;QAEA,OAAOD,GAAG,CAAC,EAAE;IACf;IAEA,MAAMoB,UAAU,CAACC;QACfrB,GAAG,CAACC,OAAO,GAAGoB;QACd,IAAIlB,IAAIF,OAAO;QACf,IAAIqB,IAAIjB,OAAOF;QACf,MAAOA,IAAI,KAAKJ,QAAQC,GAAG,CAACsB,EAAE,EAAEtB,GAAG,CAACG,EAAE,IAAI,EAAG;YAC3CK,KAAKc,GAAGnB;YACRA,IAAImB;YACJA,IAAIjB,OAAOF;QACb;IACF;IAEA,MAAMoB,WAAW,CAACF;QAChB,MAAMG,QAAQxB,IAAIyB,OAAO,CAACJ;QAC1B,OAAOG,SAAS,KAAKA,QAAQvB;IAC/B;IAEA,MAAMyB,SAAS,CAACL;QACd,MAAMlB,IAAIH,IAAIyB,OAAO,CAACJ;QAEtB,IAAIlB,MAAM,CAAC,KAAKA,KAAKF,MAAM;YACzB;QACF;QAEAD,GAAG,CAACG,EAAE,GAAGH,GAAG,CAAC,EAAEC,KAAK;QACpBW,QAAQT;IACV;IAEA,MAAMwB,QAAQ;QACZ1B,OAAO;IACT;IAEA,OAAO;QACL0B;QACAJ;QACAP;QACAI;QACAD;QACAO;QACAzB,MAAM,IAAMA;QACZ,6FAA6F;QAC7F,gGAAgG;QAChG,kDAAkD;QAClD,CAAC,CAAC2B,OAAOC,QAAQ,CAAC;YAChB,IAAK,IAAIL,QAAQ,GAAGA,QAAQvB,MAAMuB,QAAS;gBACzC,MAAMxB,GAAG,CAACwB,MAAM;YAClB;QACF;IACF;AACF"}
|
package/lib/types.js
CHANGED
package/lib/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Direction where items are removed when overflow occurs.\n */\nexport type OverflowDirection = 'start' | 'end';\n\n/**\n * Axis used to measure overflow.\n */\nexport type OverflowAxis = 'horizontal' | 'vertical';\n\n/**\n * Visibility state for an overflow group.\n */\nexport type OverflowGroupState = 'visible' | 'hidden' | 'overflow';\n\n/**\n * Tracked item in the overflow manager.\n */\nexport interface OverflowItemEntry {\n /**\n * HTML element that disappears when the item overflows.\n */\n element: HTMLElement;\n /**\n * Lower-priority items become invisible first when the container overflows.\n * @default 0\n */\n priority: number;\n /**\n * Stable item id used to track visibility and emit updates.\n */\n id: string;\n\n /**\n * Optional group id used to coordinate divider and grouped visibility states.\n */\n groupId?: string;\n\n /**\n * If true, the item will never overflow and will always be visible.\n * Pinned items are excluded from the overflow count.\n * @default false\n */\n pinned?: boolean;\n}\n\n/**\n * Tracked divider in the overflow manager.\n */\nexport interface OverflowDividerEntry {\n /**\n * HTML element that disappears when its group overflows.\n */\n element: HTMLElement;\n\n /**\n * Id of the group controlled by this divider.\n */\n groupId: string;\n}\n\n/**\n * Signature similar to standard event listeners, typed for overflow updates.\n */\nexport type OnUpdateOverflow = (data: OverflowEventPayload) => void;\n\n/**\n * Callback invoked when a single item's visibility changes.\n */\nexport type OnUpdateItemVisibility = (data: OnUpdateItemVisibilityPayload) => void;\n\n/**\n * Payload of the custom DOM event for overflow updates\n */\nexport interface OverflowEventPayload {\n /**\n * Items currently visible in the container.\n */\n visibleItems: OverflowItemEntry[];\n\n /**\n * Items currently moved to overflow.\n */\n invisibleItems: OverflowItemEntry[];\n\n /**\n * Current visibility state by group id.\n */\n groupVisibility: Record<string, OverflowGroupState>;\n}\n\n/**\n * Indexed, immutable overflow state returned by `OverflowManager.getSnapshot`.\n *\n * Unlike {@link OverflowEventPayload}, this is shaped for O(1) consumer lookups (item/group\n * visibility by id, item count) rather than ordered item entries.\n */\nexport interface OverflowSnapshot {\n /**\n * Visibility of each registered item, keyed by item id.\n */\n itemVisibility: Record<string, boolean>;\n\n /**\n * Current visibility state by group id.\n */\n groupVisibility: Record<string, OverflowGroupState>;\n\n /**\n * Number of items currently moved to overflow (invisible).\n */\n invisibleItemCount: number;\n}\n\n/**\n * Payload for item-level visibility updates.\n */\nexport interface OnUpdateItemVisibilityPayload {\n /**\n * Item whose visibility changed.\n */\n item: OverflowItemEntry;\n\n /**\n * Whether the item is now visible.\n */\n visible: boolean;\n}\n\n/**\n * Options used to initialize or reconfigure overflow observation.\n */\nexport interface OverflowOptions {\n /**\n * Padding in pixels reserved at the end of the container before overflow occurs.\n * Useful for accounting for extra elements (for example an overflow menu button)\n * or margins between items that are difficult to measure in JavaScript.\n * @default 10\n */\n padding?: number;\n /**\n * Direction where items are removed when overflow occurs.\n * @default end\n */\n overflowDirection?: OverflowDirection;\n\n /**\n * Overflow axis used for size measurement.\n * @default horizontal\n */\n overflowAxis?: OverflowAxis;\n\n /**\n * Minimum number of items that must remain visible.\n */\n minimumVisible?: number;\n\n /**\n * Callback invoked when an individual item's visibility changes.\n */\n onUpdateItemVisibility: OnUpdateItemVisibility;\n\n /**\n * Callback invoked after overflow state is recomputed.\n */\n onUpdateOverflow: OnUpdateOverflow;\n\n /**\n * When true, reserve space as if the overflow menu were visible even with no overflowing items.\n * @default false\n */\n hasHiddenItems?: boolean;\n}\n\nexport interface ObserveOptions extends Partial<OverflowOptions> {\n /**\n * forces update when observation begins, ensuring initial overflow state is correct. This is useful when the container starts with items that should be overflowed, or when the container resizes immediately after mounting.\n * @default false\n */\n forceUpdate?: boolean;\n}\n\n/**\n * Internal manager contract used to observe and compute priority overflow.\n *\n * @internal\n */\nexport interface OverflowManager {\n /**\n * Starts observing the container and managing the overflow state\n */\n observe: (container: HTMLElement, options?: ObserveOptions) => void;\n /**\n * Stops observing the container\n */\n disconnect: () => void;\n /**\n * Updates engine options without restarting observation.\n */\n setOptions: (options: Partial<OverflowOptions>) => void;\n /**\n * Add overflow items\n */\n addItem: (items: OverflowItemEntry) => void;\n /**\n * Remove overflow item\n */\n removeItem: (itemId: string) => void;\n /**\n * Manually update the overflow, updates are batched and async\n */\n update: () => void;\n /**\n * Manually update the overflow sync\n */\n forceUpdate: () => void;\n\n /**\n * Adds an element that opens an overflow menu. This is used to calculate\n * available space and check if additional items need to overflow\n */\n addOverflowMenu: (element: HTMLElement) => void;\n\n /**\n * Add overflow divider\n */\n addDivider: (divider: OverflowDividerEntry) => void;\n\n /**\n * Remove overflow divider\n */\n removeDivider: (groupId: string) => void;\n\n /**\n * Unsets the overflow menu element\n */\n removeOverflowMenu: () => void;\n\n /**\n * Returns the current overflow snapshot.\n */\n getSnapshot: () => OverflowSnapshot;\n\n /**\n * Subscribes to snapshot changes.\n */\n subscribe: (listener: () => void) => () => void;\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GAoLD;;;;CAIC,GACD,WA4DC"}
|
package/lib-commonjs/consts.js
CHANGED
|
@@ -14,7 +14,15 @@ _export(exports, {
|
|
|
14
14
|
},
|
|
15
15
|
DATA_OVERFLOW_GROUP: function() {
|
|
16
16
|
return DATA_OVERFLOW_GROUP;
|
|
17
|
+
},
|
|
18
|
+
EMPTY_SNAPSHOT: function() {
|
|
19
|
+
return EMPTY_SNAPSHOT;
|
|
17
20
|
}
|
|
18
21
|
});
|
|
19
22
|
const DATA_OVERFLOWING = 'data-overflowing';
|
|
20
23
|
const DATA_OVERFLOW_GROUP = 'data-overflow-group';
|
|
24
|
+
const EMPTY_SNAPSHOT = Object.freeze({
|
|
25
|
+
itemVisibility: {},
|
|
26
|
+
groupVisibility: {},
|
|
27
|
+
invisibleItemCount: 0
|
|
28
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/consts.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/consts.ts"],"sourcesContent":["import type { OverflowSnapshot } from './types';\n\nexport const DATA_OVERFLOWING = 'data-overflowing';\nexport const DATA_OVERFLOW_GROUP = 'data-overflow-group';\n\n/**\n * An empty, frozen overflow snapshot used as the default before anything has been measured.\n * @internal\n */\nexport const EMPTY_SNAPSHOT: OverflowSnapshot = Object.freeze({\n itemVisibility: {},\n groupVisibility: {},\n invisibleItemCount: 0,\n});\n"],"names":["DATA_OVERFLOWING","DATA_OVERFLOW_GROUP","EMPTY_SNAPSHOT","Object","freeze","itemVisibility","groupVisibility","invisibleItemCount"],"mappings":";;;;;;;;;;;IAEaA,gBAAgB;eAAhBA;;IACAC,mBAAmB;eAAnBA;;IAMAC,cAAc;eAAdA;;;AAPN,MAAMF,mBAAmB;AACzB,MAAMC,sBAAsB;AAM5B,MAAMC,iBAAmCC,OAAOC,MAAM,CAAC;IAC5DC,gBAAgB,CAAC;IACjBC,iBAAiB,CAAC;IAClBC,oBAAoB;AACtB"}
|
package/lib-commonjs/index.js
CHANGED
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
EMPTY_SNAPSHOT: function() {
|
|
13
|
+
return _consts.EMPTY_SNAPSHOT;
|
|
14
|
+
},
|
|
15
|
+
createOverflowManager: function() {
|
|
8
16
|
return _overflowManager.createOverflowManager;
|
|
9
17
|
}
|
|
10
18
|
});
|
|
11
19
|
const _overflowManager = require("./overflowManager");
|
|
20
|
+
const _consts = require("./consts");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createOverflowManager } from './overflowManager';\nexport type {\n ObserveOptions,\n OnUpdateItemVisibility,\n OnUpdateItemVisibilityPayload,\n OnUpdateOverflow,\n OverflowAxis,\n OverflowDirection,\n OverflowEventPayload,\n OverflowGroupState,\n OverflowItemEntry,\n OverflowDividerEntry,\n OverflowManager,\n} from './types';\n"],"names":["createOverflowManager"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createOverflowManager } from './overflowManager';\nexport { EMPTY_SNAPSHOT } from './consts';\nexport type {\n ObserveOptions,\n OverflowOptions,\n OnUpdateItemVisibility,\n OnUpdateItemVisibilityPayload,\n OnUpdateOverflow,\n OverflowAxis,\n OverflowDirection,\n OverflowEventPayload,\n OverflowGroupState,\n OverflowItemEntry,\n OverflowDividerEntry,\n OverflowManager,\n OverflowSnapshot,\n} from './types';\n"],"names":["EMPTY_SNAPSHOT","createOverflowManager"],"mappings":";;;;;;;;;;;IACSA,cAAc;eAAdA,sBAAc;;IADdC,qBAAqB;eAArBA,sCAAqB;;;iCAAQ;wBACP"}
|
|
@@ -12,7 +12,18 @@ const _consts = require("./consts");
|
|
|
12
12
|
const _createResizeObserver = require("./createResizeObserver");
|
|
13
13
|
const _debounce = require("./debounce");
|
|
14
14
|
const _priorityQueue = require("./priorityQueue");
|
|
15
|
-
|
|
15
|
+
const DEFAULT_OPTIONS = {
|
|
16
|
+
overflowAxis: 'horizontal',
|
|
17
|
+
overflowDirection: 'end',
|
|
18
|
+
padding: 10,
|
|
19
|
+
minimumVisible: 0,
|
|
20
|
+
hasHiddenItems: false,
|
|
21
|
+
onUpdateItemVisibility: ()=>{
|
|
22
|
+
/* noop */ },
|
|
23
|
+
onUpdateOverflow: ()=>{
|
|
24
|
+
/* noop */ }
|
|
25
|
+
};
|
|
26
|
+
function createOverflowManager(initialOptions = {}) {
|
|
16
27
|
// calls to `offsetWidth or offsetHeight` can happen multiple times in an update
|
|
17
28
|
// Use a cache to avoid causing too many recalcs and avoid scripting time to meausure sizes
|
|
18
29
|
const sizeCache = new Map();
|
|
@@ -24,17 +35,19 @@ function createOverflowManager() {
|
|
|
24
35
|
// Initially true to force dispatch on first mount
|
|
25
36
|
let forceDispatch = true;
|
|
26
37
|
const options = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
overflowDirection: 'end',
|
|
30
|
-
minimumVisible: 0,
|
|
31
|
-
onUpdateItemVisibility: ()=>undefined,
|
|
32
|
-
onUpdateOverflow: ()=>undefined,
|
|
33
|
-
hasHiddenItems: false
|
|
38
|
+
...DEFAULT_OPTIONS,
|
|
39
|
+
...initialOptions
|
|
34
40
|
};
|
|
35
41
|
const overflowItems = {};
|
|
36
42
|
const overflowDividers = {};
|
|
37
|
-
|
|
43
|
+
const listeners = new Set();
|
|
44
|
+
let disposeResizeObserver = ()=>{
|
|
45
|
+
/* noop */ };
|
|
46
|
+
let snapshot = _consts.EMPTY_SNAPSHOT;
|
|
47
|
+
const takeSnapshot = (nextSnapshot)=>{
|
|
48
|
+
snapshot = nextSnapshot;
|
|
49
|
+
listeners.forEach((listener)=>listener());
|
|
50
|
+
};
|
|
38
51
|
const getNextItem = (queueToDequeue, queueToEnqueue)=>{
|
|
39
52
|
const nextItem = queueToDequeue.dequeue();
|
|
40
53
|
queueToEnqueue.enqueue(nextItem);
|
|
@@ -75,7 +88,10 @@ function createOverflowManager() {
|
|
|
75
88
|
const invisibleItemQueue = (0, _priorityQueue.createPriorityQueue)((a, b)=>-1 * compareItems(a, b));
|
|
76
89
|
const visibleItemQueue = (0, _priorityQueue.createPriorityQueue)(compareItems);
|
|
77
90
|
function occupiedSize() {
|
|
78
|
-
|
|
91
|
+
let totalItemSize = 0;
|
|
92
|
+
for (const id of visibleItemQueue){
|
|
93
|
+
totalItemSize += getOffsetSize(overflowItems[id].element);
|
|
94
|
+
}
|
|
79
95
|
const totalDividerSize = Object.entries(groupManager.groupVisibility()).reduce((acc, [id, state])=>acc + (state !== 'hidden' && overflowDividers[id] ? getOffsetSize(overflowDividers[id].element) : 0), 0);
|
|
80
96
|
const overflowMenuSize = (invisibleItemQueue.size() > 0 || options.hasHiddenItems) && overflowMenu ? getOffsetSize(overflowMenu) : 0;
|
|
81
97
|
return totalItemSize + totalDividerSize + overflowMenuSize;
|
|
@@ -109,16 +125,35 @@ function createOverflowManager() {
|
|
|
109
125
|
}
|
|
110
126
|
};
|
|
111
127
|
const dispatchOverflowUpdate = ()=>{
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const
|
|
128
|
+
const groupVisibility = groupManager.groupVisibility();
|
|
129
|
+
// Build the legacy ordered-entry arrays and the snapshot's id -> visible map in a single pass
|
|
130
|
+
// over each queue.
|
|
131
|
+
const itemVisibility = {};
|
|
132
|
+
const visibleItems = [];
|
|
133
|
+
const invisibleItems = [];
|
|
134
|
+
for (const itemId of visibleItemQueue){
|
|
135
|
+
itemVisibility[itemId] = true;
|
|
136
|
+
visibleItems.push(overflowItems[itemId]);
|
|
137
|
+
}
|
|
138
|
+
for (const itemId of invisibleItemQueue){
|
|
139
|
+
itemVisibility[itemId] = false;
|
|
140
|
+
invisibleItems.push(overflowItems[itemId]);
|
|
141
|
+
}
|
|
142
|
+
// Set the snapshot first so `getSnapshot()` is current for both subscribers and any
|
|
143
|
+
// `onUpdateOverflow` consumer that reads it.
|
|
144
|
+
takeSnapshot({
|
|
145
|
+
itemVisibility,
|
|
146
|
+
groupVisibility,
|
|
147
|
+
invisibleItemCount: invisibleItems.length
|
|
148
|
+
});
|
|
149
|
+
// Legacy event payload: ordered item entries for `onUpdateOverflow` consumers.
|
|
116
150
|
options.onUpdateOverflow({
|
|
117
151
|
visibleItems,
|
|
118
152
|
invisibleItems,
|
|
119
|
-
groupVisibility
|
|
153
|
+
groupVisibility
|
|
120
154
|
});
|
|
121
155
|
};
|
|
156
|
+
const getSnapshot = ()=>snapshot;
|
|
122
157
|
const processOverflowItems = ()=>{
|
|
123
158
|
if (!container) {
|
|
124
159
|
return false;
|
|
@@ -160,39 +195,78 @@ function createOverflowManager() {
|
|
|
160
195
|
}
|
|
161
196
|
};
|
|
162
197
|
const update = (0, _debounce.debounce)(forceUpdate);
|
|
163
|
-
const
|
|
198
|
+
const setOptions = (nextOptions)=>{
|
|
199
|
+
if (options === nextOptions) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const shouldTriggerUpdate = nextOptions.overflowAxis && options.overflowAxis !== nextOptions.overflowAxis || nextOptions.overflowDirection && options.overflowDirection !== nextOptions.overflowDirection || nextOptions.padding && options.padding !== nextOptions.padding || nextOptions.minimumVisible && options.minimumVisible !== nextOptions.minimumVisible || nextOptions.hasHiddenItems && options.hasHiddenItems !== nextOptions.hasHiddenItems;
|
|
203
|
+
Object.assign(options, nextOptions);
|
|
204
|
+
if (shouldTriggerUpdate) {
|
|
205
|
+
forceDispatch = true;
|
|
206
|
+
update();
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const observe = (observedContainer, observeOptions)=>{
|
|
210
|
+
const { forceUpdate: shouldForceUpdate, ...userOptions } = observeOptions !== null && observeOptions !== void 0 ? observeOptions : {};
|
|
164
211
|
Object.assign(options, userOptions);
|
|
165
|
-
|
|
166
|
-
|
|
212
|
+
Object.values(overflowItems).forEach((item)=>{
|
|
213
|
+
if (!visibleItemQueue.contains(item.id) && !invisibleItemQueue.contains(item.id)) {
|
|
214
|
+
visibleItemQueue.enqueue(item.id);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
167
217
|
container = observedContainer;
|
|
218
|
+
observing = true;
|
|
168
219
|
disposeResizeObserver = (0, _createResizeObserver.observeResize)(container, (entries)=>{
|
|
169
220
|
if (!entries[0] || !container) {
|
|
170
221
|
return;
|
|
171
222
|
}
|
|
172
223
|
update();
|
|
173
224
|
});
|
|
225
|
+
if (shouldForceUpdate && getClientSize(observedContainer) > 0) {
|
|
226
|
+
forceUpdate();
|
|
227
|
+
}
|
|
174
228
|
};
|
|
175
|
-
const
|
|
176
|
-
|
|
229
|
+
const disconnect = ()=>{
|
|
230
|
+
disposeResizeObserver();
|
|
231
|
+
disposeResizeObserver = ()=>{
|
|
232
|
+
/* noop */ };
|
|
233
|
+
// reset flags
|
|
234
|
+
container = undefined;
|
|
235
|
+
observing = false;
|
|
236
|
+
forceDispatch = true;
|
|
237
|
+
// clear all entries
|
|
238
|
+
Object.keys(overflowItems).forEach((itemId)=>removeItem(itemId));
|
|
239
|
+
Object.keys(overflowDividers).forEach((dividerId)=>removeDivider(dividerId));
|
|
240
|
+
removeOverflowMenu();
|
|
241
|
+
sizeCache.clear();
|
|
242
|
+
// notify subscribers that the manager is no longer tracking anything
|
|
243
|
+
takeSnapshot(_consts.EMPTY_SNAPSHOT);
|
|
244
|
+
};
|
|
245
|
+
const addItem = (items)=>{
|
|
246
|
+
if (overflowItems[items.id]) {
|
|
177
247
|
return;
|
|
178
248
|
}
|
|
179
|
-
overflowItems[
|
|
249
|
+
overflowItems[items.id] = items;
|
|
180
250
|
// some options can affect priority which are only set on `observe`
|
|
181
251
|
if (observing) {
|
|
182
252
|
// Updates to elements might not change the queue tops
|
|
183
253
|
// i.e. new element is enqueued but the top of the queue stays the same
|
|
184
254
|
// force a dispatch on the next batched update
|
|
185
255
|
forceDispatch = true;
|
|
186
|
-
visibleItemQueue.enqueue(
|
|
256
|
+
visibleItemQueue.enqueue(items.id);
|
|
257
|
+
update();
|
|
187
258
|
}
|
|
188
|
-
if (
|
|
189
|
-
groupManager.addItem(
|
|
190
|
-
|
|
259
|
+
if (items.groupId) {
|
|
260
|
+
groupManager.addItem(items.id, items.groupId);
|
|
261
|
+
items.element.setAttribute(_consts.DATA_OVERFLOW_GROUP, items.groupId);
|
|
191
262
|
}
|
|
192
|
-
update();
|
|
193
263
|
};
|
|
194
264
|
const addOverflowMenu = (el)=>{
|
|
195
265
|
overflowMenu = el;
|
|
266
|
+
if (observing) {
|
|
267
|
+
forceDispatch = true;
|
|
268
|
+
update();
|
|
269
|
+
}
|
|
196
270
|
};
|
|
197
271
|
const addDivider = (divider)=>{
|
|
198
272
|
if (!divider.groupId || overflowDividers[divider.groupId]) {
|
|
@@ -203,6 +277,10 @@ function createOverflowManager() {
|
|
|
203
277
|
};
|
|
204
278
|
const removeOverflowMenu = ()=>{
|
|
205
279
|
overflowMenu = undefined;
|
|
280
|
+
if (observing) {
|
|
281
|
+
forceDispatch = true;
|
|
282
|
+
update();
|
|
283
|
+
}
|
|
206
284
|
};
|
|
207
285
|
const removeDivider = (groupId)=>{
|
|
208
286
|
if (!overflowDividers[groupId]) {
|
|
@@ -232,19 +310,15 @@ function createOverflowManager() {
|
|
|
232
310
|
}
|
|
233
311
|
sizeCache.delete(item.element);
|
|
234
312
|
delete overflowItems[itemId];
|
|
235
|
-
|
|
313
|
+
if (observing) {
|
|
314
|
+
update();
|
|
315
|
+
}
|
|
236
316
|
};
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
forceDispatch = true;
|
|
243
|
-
// clear all entries
|
|
244
|
-
Object.keys(overflowItems).forEach((itemId)=>removeItem(itemId));
|
|
245
|
-
Object.keys(overflowDividers).forEach((dividerId)=>removeDivider(dividerId));
|
|
246
|
-
removeOverflowMenu();
|
|
247
|
-
sizeCache.clear();
|
|
317
|
+
const subscribe = (listener)=>{
|
|
318
|
+
listeners.add(listener);
|
|
319
|
+
return ()=>{
|
|
320
|
+
listeners.delete(listener);
|
|
321
|
+
};
|
|
248
322
|
};
|
|
249
323
|
return {
|
|
250
324
|
addItem,
|
|
@@ -256,7 +330,10 @@ function createOverflowManager() {
|
|
|
256
330
|
addOverflowMenu,
|
|
257
331
|
removeOverflowMenu,
|
|
258
332
|
addDivider,
|
|
259
|
-
removeDivider
|
|
333
|
+
removeDivider,
|
|
334
|
+
setOptions,
|
|
335
|
+
getSnapshot,
|
|
336
|
+
subscribe
|
|
260
337
|
};
|
|
261
338
|
}
|
|
262
339
|
const createGroupManager = ()=>{
|