Some checks are pending
E2E / Playwright e2e (push) Waiting to run
- Replaced suite page metadata with drive-specific metadata for document and drawing editors. - Introduced new `driveEditorPageMetadata` function to manage titles and favicons based on editor type. - Updated layout components for document and drawing editors to utilize the new metadata structure. - Enhanced document title handling in various editor components to reflect the current editing context. - Added new SVG icons for UltiDocs, UltiSheets, UltiSlides, and UltiDraw to improve visual consistency across editors. - Improved print styles and layout handling for better document rendering in print and PDF formats.
76 lines
2.0 KiB
TypeScript
76 lines
2.0 KiB
TypeScript
"use client"
|
|
|
|
import { useLayoutEffect, useRef, useState } from "react"
|
|
|
|
const OVERFLOW_BUTTON_WIDTH = 36
|
|
|
|
export function useToolbarOverflow(itemCount: number, reservedTrailingPx = 0) {
|
|
const containerRef = useRef<HTMLDivElement>(null)
|
|
const measureRef = useRef<HTMLDivElement>(null)
|
|
const [visibleCount, setVisibleCount] = useState(itemCount)
|
|
|
|
useLayoutEffect(() => {
|
|
setVisibleCount(itemCount)
|
|
}, [itemCount])
|
|
|
|
useLayoutEffect(() => {
|
|
const container = containerRef.current
|
|
const measure = measureRef.current
|
|
if (!container || !measure) return
|
|
|
|
const recalculate = () => {
|
|
const children = Array.from(measure.children) as HTMLElement[]
|
|
if (children.length === 0) {
|
|
setVisibleCount(0)
|
|
return
|
|
}
|
|
|
|
const containerWidth = container.clientWidth
|
|
if (containerWidth <= 0) return
|
|
|
|
const totalWidth = children.reduce((sum, child) => sum + child.offsetWidth, 0)
|
|
const trailingReserve = reservedTrailingPx
|
|
const maxWithoutOverflow = containerWidth - trailingReserve
|
|
|
|
if (totalWidth <= maxWithoutOverflow) {
|
|
setVisibleCount(children.length)
|
|
return
|
|
}
|
|
|
|
const available = containerWidth - OVERFLOW_BUTTON_WIDTH - trailingReserve
|
|
let used = 0
|
|
let fit = 0
|
|
|
|
for (const child of children) {
|
|
const width = child.offsetWidth
|
|
if (used + width > available) break
|
|
used += width
|
|
fit += 1
|
|
}
|
|
|
|
setVisibleCount(Math.max(1, fit))
|
|
}
|
|
|
|
recalculate()
|
|
|
|
const ro = new ResizeObserver(recalculate)
|
|
ro.observe(container)
|
|
ro.observe(measure)
|
|
for (const child of measure.children) {
|
|
ro.observe(child)
|
|
}
|
|
|
|
const mo = new MutationObserver(recalculate)
|
|
mo.observe(measure, { childList: true })
|
|
|
|
return () => {
|
|
ro.disconnect()
|
|
mo.disconnect()
|
|
}
|
|
}, [itemCount, reservedTrailingPx])
|
|
|
|
const hasOverflow = visibleCount < itemCount
|
|
|
|
return { containerRef, measureRef, visibleCount, hasOverflow }
|
|
}
|