@mortenbrudvik/waveui 0.13.0 → 0.14.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/README.md +302 -49
- package/dist/components/data-display/Avatar.context.cjs.map +1 -1
- package/dist/components/data-display/Avatar.context.mjs.map +1 -1
- package/dist/components/data-display/List.cjs +1 -1
- package/dist/components/data-display/List.cjs.map +1 -1
- package/dist/components/data-display/List.mjs +245 -195
- package/dist/components/data-display/List.mjs.map +1 -1
- package/dist/components/data-display/List.registry.cjs.map +1 -1
- package/dist/components/data-display/List.registry.mjs.map +1 -1
- package/dist/components/layout/Overflow.cjs +1 -1
- package/dist/components/layout/Overflow.cjs.map +1 -1
- package/dist/components/layout/Overflow.mjs +240 -192
- package/dist/components/layout/Overflow.mjs.map +1 -1
- package/dist/components/layout/Overflow.store.cjs +2 -0
- package/dist/components/layout/Overflow.store.cjs.map +1 -0
- package/dist/components/layout/Overflow.store.mjs +209 -0
- package/dist/components/layout/Overflow.store.mjs.map +1 -0
- package/dist/components/navigation/Breadcrumb.cjs +1 -1
- package/dist/components/navigation/Breadcrumb.cjs.map +1 -1
- package/dist/components/navigation/Breadcrumb.mjs +239 -84
- package/dist/components/navigation/Breadcrumb.mjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.cjs +1 -1
- package/dist/components/overlays/Dialog.slots.cjs.map +1 -1
- package/dist/components/overlays/Dialog.slots.mjs +19 -15
- package/dist/components/overlays/Dialog.slots.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.cjs +1 -1
- package/dist/components/overlays/TeachingPopover.cjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.context.cjs +2 -0
- package/dist/components/overlays/TeachingPopover.context.cjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.context.mjs +51 -0
- package/dist/components/overlays/TeachingPopover.context.mjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.mjs +15 -185
- package/dist/components/overlays/TeachingPopover.mjs.map +1 -1
- package/dist/components/overlays/TeachingPopover.parts.cjs +2 -0
- package/dist/components/overlays/TeachingPopover.parts.cjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.parts.mjs +398 -0
- package/dist/components/overlays/TeachingPopover.parts.mjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.root.cjs +2 -0
- package/dist/components/overlays/TeachingPopover.root.cjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.root.mjs +150 -0
- package/dist/components/overlays/TeachingPopover.root.mjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.stack.cjs +2 -0
- package/dist/components/overlays/TeachingPopover.stack.cjs.map +1 -0
- package/dist/components/overlays/TeachingPopover.stack.mjs +86 -0
- package/dist/components/overlays/TeachingPopover.stack.mjs.map +1 -0
- package/dist/components/table/DataGrid.cjs +1 -1
- package/dist/components/table/DataGrid.cjs.map +1 -1
- package/dist/components/table/DataGrid.mjs +540 -311
- package/dist/components/table/DataGrid.mjs.map +1 -1
- package/dist/components/table/Table.cjs +1 -1
- package/dist/components/table/Table.cjs.map +1 -1
- package/dist/components/table/Table.mjs +183 -60
- package/dist/components/table/Table.mjs.map +1 -1
- package/dist/components/table/Table.shared.cjs +2 -0
- package/dist/components/table/Table.shared.cjs.map +1 -0
- package/dist/components/table/Table.shared.mjs +65 -0
- package/dist/components/table/Table.shared.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1742 -158
- package/dist/index.d.ts +1742 -158
- package/dist/index.mjs +135 -132
- package/dist/lib/breadcrumb.cjs +2 -0
- package/dist/lib/breadcrumb.cjs.map +1 -0
- package/dist/lib/breadcrumb.mjs +26 -0
- package/dist/lib/breadcrumb.mjs.map +1 -0
- package/dist/lib/classNames.cjs +1 -1
- package/dist/lib/classNames.cjs.map +1 -1
- package/dist/lib/classNames.mjs +66 -38
- package/dist/lib/classNames.mjs.map +1 -1
- package/dist/lib/events.cjs +1 -1
- package/dist/lib/events.cjs.map +1 -1
- package/dist/lib/events.mjs +35 -8
- package/dist/lib/events.mjs.map +1 -1
- package/dist/lib/icons.cjs +1 -1
- package/dist/lib/icons.cjs.map +1 -1
- package/dist/lib/icons.mjs +34 -20
- package/dist/lib/icons.mjs.map +1 -1
- package/dist/lib/table.cjs +2 -0
- package/dist/lib/table.cjs.map +1 -0
- package/dist/lib/table.mjs +16 -0
- package/dist/lib/table.mjs.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Overflow.mjs","names":["React","NO_IDS","useForceRender","n","hasResizeObserver","documentOrder","a","b","REORDER_OBSERVER_OPTIONS","sameIds","id","i","warnDuplicateItemId","itemId","noop","readContainer","paddingInline","gap","view","container","style","OverflowStore","listener","el","onResize","node","order","isDev","counts","count","remaining","elements","entries","widths","total","sum","width","next","pinned","available","limit","used","cut","end","hiddenChanged","OverflowContext","INERT_CONTEXT","useOverflowContext","reportMissingContext","componentName","useOverflowMenu","hiddenIds","useIsOverflowItemVisible","hiddenSet","isElement","followDirectChildren","record","records","parent","observer","OverflowingStore","element","check","cleanups","resizeObserver","child","mutationObserver","cleanup","isRefObject","target","useIsOverflowing","store","isOverflowing","forceRender","unsubscribe","OverflowRoot","rest","setContainer","setButton","containerRef","useMergedRefs","ref","disconnect","buttonIds","ctx","hiddenCount","cn","overflowClassNames","className","children","overflowButton","OverflowItem","ariaHidden","isHidden","registerRef","mergedRef","overflowItemClassNames","inert","Overflow"],"sources":["../../../src/components/layout/Overflow.tsx"],"sourcesContent":["import * as React from 'react';\nimport { overflowClassNames, overflowItemClassNames } from '../../lib/classNames';\nimport { cn } from '../../lib/cn';\nimport { isDev, reportMissingContext, warnOnce } from '../../lib/dev';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\n\n/** Properties for the Overflow component. */\nexport interface OverflowProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Renders the overflow button (for example a \"+3\" menu trigger) while at least one item is\n * hidden. Receives the number of hidden items and their `itemId`s in DOM order, so the button\n * can open a menu of the hidden items. `hiddenIds` is the button's own array (sorting it in\n * place affects nobody else). Its width is measured and reserved when items overflow.\n * Components rendered by it can also read the hidden items with {@link useOverflowMenu}.\n */\n overflowButton?: (count: number, hiddenIds: string[]) => React.ReactNode;\n /**\n * The {@link OverflowItem}s to lay out in one row. Only items and the overflow button are\n * measured: the container's whole content box is the room for them, so other content placed in\n * the row is not accounted for and could clip items that still count as visible. Keep fixed\n * content outside the Overflow (for example in a surrounding flex row), or wrap it in an\n * `OverflowItem` (the first item is never hidden).\n */\n children: React.ReactNode;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the OverflowItem sub-component. */\nexport interface OverflowItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Identifier for tracking this item's overflow visibility, unique within the Overflow (a\n * duplicate warns in development: items that share one are hidden and shown together).\n */\n itemId: string;\n /** Content of the overflow item. */\n children: React.ReactNode;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Result of {@link useOverflowMenu}. */\nexport interface UseOverflowMenuResult {\n /** `itemId`s of the hidden items, in DOM order (the caller's own array). */\n hiddenIds: string[];\n /** Number of hidden items. */\n count: number;\n}\n\n// ---------------------------------------------------------------------------\n// Measurement store\n// ---------------------------------------------------------------------------\n\n/**\n * The empty snapshot. Snapshots are internal: they are compared by identity and never handed to\n * consumers, who receive their own copies (see `useOverflowMenu` and `overflowButton`).\n */\nconst NO_IDS: string[] = [];\n\n/** A stable function that re-renders the calling component. */\nfunction useForceRender(): () => void {\n return React.useReducer((n: number) => n + 1, 0)[1];\n}\n\nfunction hasResizeObserver(): boolean {\n return typeof ResizeObserver !== 'undefined';\n}\n\nfunction documentOrder(a: Element, b: Element): number {\n if (a === b) return 0;\n return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;\n}\n\n/** Moves anywhere in the row: items reordered directly or inside wrappers. */\nconst REORDER_OBSERVER_OPTIONS: MutationObserverInit = { childList: true, subtree: true };\n\nfunction sameIds(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((id, i) => id === b[i]);\n}\n\nfunction warnDuplicateItemId(itemId: string): void {\n warnOnce(\n `Overflow:duplicate:${itemId}`,\n `Overflow: several items share the itemId \"${itemId}\". Item ids must be unique within an ` +\n 'Overflow; items with the same itemId are hidden and shown together.',\n );\n}\n\nconst noop = () => {};\n\n/** Width available to items: the content box of the container, and the flex gap between items. */\nfunction readContainer(container: HTMLElement): { available: number; gap: number } {\n let paddingInline = 0;\n let gap = 0;\n const view = container.ownerDocument.defaultView;\n if (view) {\n const style = view.getComputedStyle(container);\n paddingInline = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);\n gap = parseFloat(style.columnGap) || 0;\n }\n return { available: container.clientWidth - paddingInline, gap };\n}\n\n/**\n * Tracks the container, the items and the overflow button of one `Overflow` and publishes the ids\n * of the hidden items (DOM order), and whether the button covers the first item, to\n * `useSyncExternalStore`.\n *\n * - **Measurement never writes styles.** An item's width is read (`offsetWidth`) only while it is\n * visible and cached; a hidden item (`data-overflow-hidden` and an inline `display: none`, both\n * rendered by React) keeps its last visible width. All reads happen before React applies the\n * result.\n * - **Membership-only updates.** A new snapshot is published only when the hidden set (or whether\n * the button covers the first item) changes, so a resize that hides the same items renders\n * nothing.\n * - **One observer.** A single `ResizeObserver` (created when the root mounts) watches the\n * container, every item and the overflow button. Without `ResizeObserver` the store measures\n * whenever something registers and on window `resize`.\n * - **Reorders.** A keyed reorder moves item elements without registering them again or changing\n * a size. The order of the last measurement is re-checked (n − 1 `compareDocumentPosition`\n * calls, no layout reads) after every commit of the root and, through a `MutationObserver`\n * (`childList`, `subtree`) on the container, after moves that do not render the root (a list\n * component inside the row that owns its order); only an inversion re-measures.\n */\nclass OverflowStore {\n private container: HTMLElement | null = null;\n private button: HTMLElement | null = null;\n private buttonWidth = 0;\n private readonly items = new Map<HTMLElement, string>();\n /** How many mounted items use each `itemId` (development only: a repeated one warns). */\n private readonly itemIdCounts = new Map<string, number>();\n private readonly widths = new WeakMap<HTMLElement, number>();\n private readonly listeners = new Set<() => void>();\n private hidden: string[] = NO_IDS;\n /** The first item is wider than the room beside the button, so the button covers its end. */\n private pinned = false;\n /** The item elements of the last measurement, in the DOM order they had then. */\n private order: HTMLElement[] = [];\n private connected = false;\n private observer: ResizeObserver | null = null;\n private reorderObserver: MutationObserver | null = null;\n private removeResizeListener: (() => void) | null = null;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): string[] => this.hidden;\n\n getServerSnapshot = (): string[] => NO_IDS;\n\n getPinned = (): boolean => this.pinned;\n\n getServerPinned = (): boolean => false;\n\n /** Starts observing (root layout effect); returns the teardown. */\n connect = (): (() => void) => {\n this.connected = true;\n if (hasResizeObserver()) {\n this.observer = new ResizeObserver(() => this.measure());\n for (const el of this.observedElements()) this.observer.observe(el);\n } else if (typeof window !== 'undefined') {\n const onResize = () => this.measure();\n window.addEventListener('resize', onResize);\n this.removeResizeListener = () => window.removeEventListener('resize', onResize);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.reorderObserver = new MutationObserver(() => this.checkOrder());\n if (this.container) this.reorderObserver.observe(this.container, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n return () => {\n this.connected = false;\n this.observer?.disconnect();\n this.observer = null;\n this.reorderObserver?.disconnect();\n this.reorderObserver = null;\n this.removeResizeListener?.();\n this.removeResizeListener = null;\n };\n };\n\n /** Ref callback of the container. */\n setContainer = (node: HTMLDivElement | null): void => {\n if (node === this.container) return;\n if (this.container) this.observer?.unobserve(this.container);\n this.container = node;\n if (node) this.observer?.observe(node);\n if (this.reorderObserver) {\n this.reorderObserver.disconnect();\n if (node) this.reorderObserver.observe(node, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n };\n\n /**\n * Re-measures when the items of the last measurement are no longer in DOM order (a keyed\n * reorder). Cheap: neighbour comparisons only, no layout reads.\n */\n checkOrder = (): void => {\n const order = this.order;\n for (let i = 1; i < order.length; i++) {\n if (documentOrder(order[i - 1], order[i]) > 0) {\n this.measure();\n return;\n }\n }\n };\n\n /** Ref callback of the overflow button wrapper. The last measured width outlives it. */\n setButton = (node: HTMLDivElement | null): void => {\n if (node === this.button) return;\n if (this.button) this.observer?.unobserve(this.button);\n this.button = node;\n if (node) this.observer?.observe(node);\n this.measure();\n };\n\n /** Registers an item element; returns its unregistration. */\n registerItem(el: HTMLElement, id: string): () => void {\n this.items.set(el, id);\n this.observer?.observe(el);\n this.measure();\n return () => {\n if (this.items.get(el) !== id) return;\n this.items.delete(el);\n this.observer?.unobserve(el);\n this.measure();\n };\n }\n\n /**\n * Counts the `itemId` of a mounted item (called from the item's effect, C-DEV); a second item\n * with an id already in use warns once per id. Returns the cleanup.\n */\n registerItemId = (itemId: string): (() => void) => {\n if (!isDev) return noop;\n const counts = this.itemIdCounts;\n const count = (counts.get(itemId) ?? 0) + 1;\n counts.set(itemId, count);\n if (count > 1) warnDuplicateItemId(itemId);\n return () => {\n const remaining = (counts.get(itemId) ?? 1) - 1;\n if (remaining > 0) counts.set(itemId, remaining);\n else counts.delete(itemId);\n };\n };\n\n private observedElements(): HTMLElement[] {\n const elements = Array.from(this.items.keys());\n if (this.container) elements.push(this.container);\n if (this.button) elements.push(this.button);\n return elements;\n }\n\n private measure(): void {\n const container = this.container;\n if (!this.connected || !container) return;\n\n // Reads first: widths of the visible items, the button and the container.\n const entries = Array.from(this.items)\n .filter(([el]) => el.isConnected && container.contains(el))\n .sort(([a], [b]) => documentOrder(a, b));\n this.order = entries.map(([el]) => el);\n for (const [el] of entries) {\n if (!el.hasAttribute('data-overflow-hidden')) this.widths.set(el, el.offsetWidth);\n }\n if (this.button?.isConnected) this.buttonWidth = this.button.offsetWidth;\n const { available, gap } = readContainer(container);\n\n const widths = entries.map(([el]) => this.widths.get(el) ?? 0);\n const total = widths.reduce((sum, width, i) => sum + width + (i > 0 ? gap : 0), 0);\n\n let next: string[] = NO_IDS;\n let pinned = false;\n if (total > available) {\n // Items that fit next to the overflow button stay; the first item always stays.\n const limit = available - (this.buttonWidth > 0 ? this.buttonWidth + gap : 0);\n let used = 0;\n let cut = entries.length;\n for (let i = 0; i < entries.length; i++) {\n const end = used + widths[i] + (i > 0 ? gap : 0);\n if (i > 0 && end > limit) {\n cut = i;\n break;\n }\n used = end;\n }\n next = entries.slice(cut).map(([, id]) => id);\n // The sticky button eats the gap before it first; it covers the first item only when the\n // two do not fit side by side.\n pinned = next.length > 0 && widths[0] + this.buttonWidth > available;\n }\n\n const hiddenChanged = !sameIds(next, this.hidden);\n if (!hiddenChanged && pinned === this.pinned) return;\n // The same hidden set keeps its array, so the items and useOverflowMenu() do not update.\n if (hiddenChanged) this.hidden = next.length > 0 ? next : NO_IDS;\n this.pinned = pinned;\n for (const listener of Array.from(this.listeners)) listener();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Context (C-CONTEXT)\n// ---------------------------------------------------------------------------\n\ninterface OverflowContextValue {\n store: OverflowStore;\n hiddenIds: string[];\n hiddenSet: ReadonlySet<string>;\n}\n\nconst OverflowContext = React.createContext<OverflowContextValue | null>(null);\n\n/** Production fallback for a misplaced sub-component: a store that is never connected. */\nconst INERT_CONTEXT: OverflowContextValue = {\n store: /* @__PURE__ */ new OverflowStore(),\n hiddenIds: NO_IDS,\n hiddenSet: /* @__PURE__ */ new Set<string>(),\n};\n\n/**\n * The enclosing Overflow's context. Outside an Overflow it throws in development and, in\n * production, logs an error once and returns an inert value (C-CONTEXT).\n */\nfunction useOverflowContext(componentName: string): OverflowContextValue {\n const ctx = React.useContext(OverflowContext);\n if (ctx) return ctx;\n reportMissingContext(componentName, 'Overflow');\n return INERT_CONTEXT;\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * The items an {@link Overflow} currently hides: their `itemId`s in DOM order and their count. Use\n * it in the component that `overflowButton` renders to list the hidden items in a menu. Must be\n * called inside `Overflow`.\n */\nexport function useOverflowMenu(): UseOverflowMenuResult {\n const { hiddenIds } = useOverflowContext('useOverflowMenu');\n // A copy per caller and snapshot: sorting or reversing it cannot affect other consumers.\n return React.useMemo(() => ({ hiddenIds: [...hiddenIds], count: hiddenIds.length }), [hiddenIds]);\n}\n\n/**\n * Whether the {@link OverflowItem} with `itemId` is currently shown (`false` while it overflows).\n * Must be called inside `Overflow`.\n */\nexport function useIsOverflowItemVisible(itemId: string): boolean {\n const { hiddenSet } = useOverflowContext('useIsOverflowItemVisible');\n return !hiddenSet.has(itemId);\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === Node.ELEMENT_NODE;\n}\n\n/**\n * Keeps `observer` on the element children of `parent`: unobserves the removed ones and observes\n * the added ones that are still attached to `parent` (records are replayed in order, so a child\n * moved or re-added within one batch ends up observed exactly when it is present).\n */\nfunction followDirectChildren(\n observer: ResizeObserver,\n parent: Element,\n records: readonly MutationRecord[],\n): void {\n for (const record of records) {\n if (record.type !== 'childList' || record.target !== parent) continue;\n record.removedNodes.forEach((node) => {\n if (isElement(node)) observer.unobserve(node);\n });\n record.addedNodes.forEach((node) => {\n if (isElement(node) && node.parentNode === parent) observer.observe(node);\n });\n }\n}\n\n/** Tracks `scrollWidth > clientWidth` of one element. */\nclass OverflowingStore {\n private element: HTMLElement | null = null;\n private value = false;\n private readonly listeners = new Set<() => void>();\n private teardown: (() => void) | null = null;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): boolean => this.value;\n\n getServerSnapshot = (): boolean => false;\n\n /** Follows `element` (layout effect of every render); re-subscribes when it changes. */\n setElement(element: HTMLElement | null): void {\n if (element === this.element) return;\n this.disconnect();\n this.element = element;\n if (element) this.teardown = this.observe(element);\n this.check();\n }\n\n disconnect(): void {\n this.teardown?.();\n this.teardown = null;\n this.element = null;\n }\n\n private observe(element: HTMLElement): () => void {\n const check = () => this.check();\n const cleanups: Array<() => void> = [];\n\n // Resizes of the element and of its direct children (content that grows or shrinks).\n const resizeObserver = hasResizeObserver() ? new ResizeObserver(check) : null;\n if (resizeObserver) {\n resizeObserver.observe(element);\n for (const child of Array.from(element.children)) resizeObserver.observe(child);\n cleanups.push(() => resizeObserver.disconnect());\n } else if (typeof window !== 'undefined') {\n window.addEventListener('resize', check);\n cleanups.push(() => window.removeEventListener('resize', check));\n }\n\n // Content added, removed or edited. Only a change of the direct children changes what the\n // ResizeObserver watches, and only those children are (un)observed; text edits and deeper\n // changes just re-check.\n if (typeof MutationObserver !== 'undefined') {\n const mutationObserver = new MutationObserver((records) => {\n if (resizeObserver) followDirectChildren(resizeObserver, element, records);\n check();\n });\n mutationObserver.observe(element, { childList: true, subtree: true, characterData: true });\n cleanups.push(() => mutationObserver.disconnect());\n }\n\n return () => cleanups.forEach((cleanup) => cleanup());\n }\n\n private check(): void {\n const el = this.element;\n const next = el !== null && el.scrollWidth > el.clientWidth;\n if (next === this.value) return;\n this.value = next;\n for (const listener of Array.from(this.listeners)) listener();\n }\n}\n\nfunction isRefObject(\n target: React.RefObject<HTMLElement | null> | HTMLElement | null | undefined,\n): target is React.RefObject<HTMLElement | null> {\n return target != null && typeof target === 'object' && 'current' in target;\n}\n\n/**\n * Whether `target`'s content is wider than the element (`scrollWidth > clientWidth`).\n *\n * `target` is a ref object or the element itself (for example from callback-ref state:\n * `const [el, setEl] = useState(null)` + `ref={setEl}`). The hook re-checks when the element\n * resizes, when its direct children resize, and when content is added, removed or edited; an\n * element that mounts later (a ref attached conditionally) is picked up after the render that\n * mounts it. Without `ResizeObserver` it re-checks on window `resize` and content changes. Returns\n * `false` on the server.\n */\nexport function useIsOverflowing(\n target: React.RefObject<HTMLElement | null> | HTMLElement | null,\n): boolean {\n const [store] = React.useState(() => new OverflowingStore());\n const isOverflowing = React.useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getServerSnapshot,\n );\n const forceRender = useForceRender();\n\n // Every render: follow the element the ref points to now (cheap identity check). A change found\n // here re-renders from the layout phase, before paint: useSyncExternalStore only subscribes in a\n // passive effect, so on mount it would pick the first value up after the browser painted.\n React.useLayoutEffect(() => {\n const unsubscribe = store.subscribe(forceRender);\n store.setElement(isRefObject(target) ? target.current : target);\n unsubscribe();\n });\n\n React.useLayoutEffect(() => () => store.disconnect(), [store]);\n\n return isOverflowing;\n}\n\n// ---------------------------------------------------------------------------\n// Components\n// ---------------------------------------------------------------------------\n\nconst OverflowRoot = ({ overflowButton, children, className, ref, ...rest }: OverflowProps) => {\n const [store] = React.useState(() => new OverflowStore());\n const hiddenIds = React.useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getServerSnapshot,\n );\n const pinned = React.useSyncExternalStore(\n store.subscribe,\n store.getPinned,\n store.getServerPinned,\n );\n const setContainer = React.useCallback(\n (node: HTMLDivElement | null) => store.setContainer(node),\n [store],\n );\n const setButton = React.useCallback(\n (node: HTMLDivElement | null) => store.setButton(node),\n [store],\n );\n const containerRef = useMergedRefs<HTMLDivElement>(ref, setContainer);\n const forceRender = useForceRender();\n\n // Observers are created once per instance (not per render or per children change). The first\n // measurement (in connect) re-renders from this layout effect, before paint: useSyncExternalStore\n // only subscribes in a passive effect, which can run after the browser painted every item.\n React.useLayoutEffect(() => {\n const unsubscribe = store.subscribe(forceRender);\n const disconnect = store.connect();\n unsubscribe();\n return disconnect;\n }, [store, forceRender]);\n\n // After every commit of the root (new children, a keyed reorder): items moved without any size\n // change or registration are re-measured before paint. Cheap when nothing moved.\n React.useLayoutEffect(() => {\n store.checkOrder();\n });\n\n const hiddenSet = React.useMemo(() => new Set(hiddenIds), [hiddenIds]);\n // The overflowButton's own copy (consumers may sort it in place).\n const buttonIds = React.useMemo(() => [...hiddenIds], [hiddenIds]);\n const ctx = React.useMemo<OverflowContextValue>(\n () => ({ store, hiddenIds, hiddenSet }),\n [store, hiddenIds, hiddenSet],\n );\n\n const hiddenCount = hiddenIds.length;\n\n return (\n <OverflowContext.Provider value={ctx}>\n <div\n ref={containerRef}\n // The row clips its content at its padding edge: the 4px padding leaves room for the focus\n // indicator a focused item draws 4px around itself. No negative margin offsets it: the\n // row's box would then reach past its container, which a scroll container around an\n // edge-to-edge row (or the page) counts as overflow. The store measures the room without\n // the padding.\n className={cn(overflowClassNames.root, 'flex items-center overflow-hidden p-1', className)}\n {...rest}\n >\n {children}\n {hiddenCount > 0 && overflowButton && (\n // In the row's flow (it adds to the row height and follows justify-*), sticking to the\n // inline end when the first item is wider than the room beside it. Browsers stop a\n // sticky element at the scroll container's padding, so -end-1 lets it reach the\n // clipping edge, and while pinned it keeps 4px inside for its own focus indicator.\n // (WebKit stops a sticky element short of the inline end of a right-to-left row; it\n // stays in the row.)\n <div\n ref={setButton}\n data-overflow-button=\"\"\n data-overflow-pinned={pinned ? '' : undefined}\n className={cn(\n overflowClassNames.overflowButton,\n 'sticky -end-1 flex shrink-0 items-center self-stretch ps-1 data-[overflow-pinned]:bg-background data-[overflow-pinned]:pe-1',\n )}\n >\n {overflowButton(hiddenCount, buttonIds)}\n </div>\n )}\n </div>\n </OverflowContext.Provider>\n );\n};\nOverflowRoot.displayName = 'Overflow';\n\n/**\n * One entry of an {@link Overflow}. While it does not fit it stays mounted but is hidden\n * (`data-overflow-hidden` and an inline `display: none` placed after the consumer's own `style`),\n * `aria-hidden` and `inert`. The inline style wins over the consumer's `style.display` and over\n * display utilities in any cascade layer (a prefixed Tailwind app's `tw:flex` included), so a\n * hidden item is never shown while it is counted in \"+N\". Must be rendered inside `Overflow`.\n */\nexport const OverflowItem = ({\n itemId,\n children,\n className,\n style,\n ref,\n 'aria-hidden': ariaHidden,\n inert,\n ...rest\n}: OverflowItemProps) => {\n const { store, hiddenSet } = useOverflowContext('OverflowItem');\n const isHidden = hiddenSet.has(itemId);\n React.useEffect(() => store.registerItemId(itemId), [store, itemId]);\n\n const registerRef = React.useCallback(\n (node: HTMLDivElement | null) => (node ? store.registerItem(node, itemId) : undefined),\n [store, itemId],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, registerRef);\n\n return (\n <div\n ref={mergedRef}\n className={cn(overflowItemClassNames.root, 'shrink-0', className)}\n {...rest}\n style={isHidden ? { ...style, display: 'none' } : style}\n aria-hidden={isHidden ? true : ariaHidden}\n inert={isHidden ? true : inert}\n data-overflow-hidden={isHidden ? '' : undefined}\n >\n {children}\n </div>\n );\n};\nOverflowItem.displayName = 'OverflowItem';\n\n/**\n * A single row that hides the items which do not fit and shows an overflow button instead.\n *\n * Wrap each entry in {@link OverflowItem} with a unique `itemId`; the row holds only items (other\n * content is not measured, see `children`). Items are measured while visible, hidden from the end\n * (in DOM order; the first item always stays) and hidden items get `data-overflow-hidden`, an\n * inline `display: none`, `aria-hidden` and `inert`. Reordered items (for example a keyed sort) are\n * re-measured in their new order. `overflowButton(count, hiddenIds)` renders the button after the\n * visible items (its measured width is reserved); components inside it can use\n * {@link useOverflowMenu} to list the hidden items (e.g. in a Menu), and\n * {@link useIsOverflowItemVisible} reports a single item. The button sticks to the inline end of\n * the row, so a first item wider than the room beside it cannot push it out of view: it then covers\n * the end of that item and gets `data-overflow-pinned`, with the `background` token behind it. (In\n * a right-to-left row, WebKit stops the pinned button short of the end, still inside the row.)\n *\n * The row clips what does not fit. So that the focus indicators of its items are not cut off, it\n * has a 4px padding: the items sit 4px in from its edges, and the row is 8px taller than they are.\n * An explicit width (such as `w-full` or a style width) includes that padding. The row never\n * reaches past its own box, so an edge-to-edge row adds no scrollbar to the page or to a scroll\n * container around it. A negative margin of 4px lines the items up with the content around the\n * row; add it only where nothing within 4px of the row scrolls (the row's box then reaches 4px past\n * its container on every side). `p-0` removes the room (focus indicators at the row's edges are\n * then clipped).\n *\n * Works without `ResizeObserver` (jsdom, old browsers): it then re-measures on window resize and\n * when items mount, unmount or move.\n *\n * The item is also `Overflow.Item`. The same component is exported as `OverflowItem`; React Server\n * Components import that flat name (dotted access needs a client file).\n */\nexport const Overflow = /* @__PURE__ */ Object.assign(OverflowRoot, {\n Item: OverflowItem,\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Overflow.mjs","names":["React","useForceRender","n","OverflowContext","INERT_CONTEXT","OverflowStore","NO_IDS","NO_GROUPS","useOverflowContext","reportMissingContext","componentName","useOverflowMenu","hiddenIds","useIsOverflowItemVisible","hiddenSet","itemId","useIsOverflowGroupVisible","groupVisibility","groupId","useHasHiddenItems","isElement","node","followDirectChildren","record","records","parent","observer","OverflowingStore","listener","element","check","cleanups","resizeObserver","hasResizeObserver","child","mutationObserver","cleanup","el","next","isRefObject","target","useIsOverflowing","store","isOverflowing","forceRender","unsubscribe","ROOT_ORIENTATION_CLASSES","DIVIDER_ORIENTATION_CLASSES","BUTTON_CLASSES","BUTTON_KEY","focusTargetIn","isFocusable","item","getFirstTabbable","FOCUSABLE_SELECTOR","overflowFocusFallback","hidden","wereHidden","first","items","id","candidates","OverflowButtonSlot","rest","elementRef","ref","useMergedRefs","buttonRef","wereHiddenRef","usePreserveFocus","placeButtonBeforeHidden","nodes","flattenChildren","children","button","index","firstHiddenId","isElementOfType","OverflowItem","OverflowRoot","measured","buttonCovers","setContainer","setButton","containerRef","overflowDirection","orientation","minimumVisible","hasHiddenItems","disconnect","buttonIds","hiddenCount","ctx","emitOverflowChange","useEventCallback","onOverflowChange","reported","hasButton","overflowButton","current","sameIds","cn","overflowClassNames","buttonPosition","placed","unplaced","warnOnce","className","ariaHidden","isHidden","asChild","unwrapFragment","childElement","isCloneableElement","childRef","ownChildProps","wrapsChildren","registerRef","mergedRef","priority","pinned","itemClassName","overflowItemClassNames","hiddenProps","inert","merged","mergeProps","mergedStyle","style","OverflowDivider","overflowDividerClassNames","Overflow"],"sources":["../../../src/components/layout/Overflow.tsx"],"sourcesContent":["import * as React from 'react';\nimport {\n overflowClassNames,\n overflowDividerClassNames,\n overflowItemClassNames,\n} from '../../lib/classNames';\nimport { flattenChildren, isElementOfType } from '../../lib/children';\nimport { cn } from '../../lib/cn';\nimport { reportMissingContext, warnOnce } from '../../lib/dev';\nimport { FOCUSABLE_SELECTOR, getFirstTabbable, isFocusable } from '../../lib/focus';\nimport { mergeProps } from '../../lib/mergeProps';\nimport { isCloneableElement, unwrapFragment } from '../../lib/renderTrigger';\nimport { useEventCallback } from '../../hooks/useEventCallback';\nimport { useMergedRefs } from '../../hooks/useMergedRefs';\nimport { usePreserveFocus } from '../../hooks/usePreserveFocus';\nimport type { Orientation } from '../../lib/types';\nimport { NO_GROUPS, NO_IDS, OverflowStore, hasResizeObserver, sameIds } from './Overflow.store';\nimport type {\n GroupVisibilityRecord,\n OverflowDirection,\n OverflowGroupVisibility,\n} from './Overflow.store';\n\nexport type { OverflowDirection, OverflowGroupVisibility };\n\n/** What {@link OverflowProps.onOverflowChange} reports besides the hidden ids. */\nexport interface OverflowChangeDetails {\n /** `itemId`s of the shown items, in DOM order. */\n visibleItems: string[];\n /**\n * The visibility of each item group, by `groupId` (only groups with an item; a record without a\n * prototype): `'visible'` when every member is shown, `'hidden'` when none is, `'overflow'` for\n * a mix.\n */\n groupVisibility: Record<string, OverflowGroupVisibility>;\n}\n\n/** Properties for the Overflow component. */\nexport interface OverflowProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Renders the overflow button (for example a \"+3\" menu trigger) while at least one item is\n * hidden. Receives the number of hidden items and their `itemId`s in DOM order, so the button\n * can open a menu of the hidden items. `hiddenIds` is the button's own array (sorting it in\n * place affects nobody else). Its size on the row's axis (width, or height for a vertical row)\n * is measured and reserved when items overflow. In a list row (`role=\"list\"`, with `asChild`\n * `<li>` items) the button's wrapper is a list item (`role=\"listitem\"`).\n * Components rendered by it can also read the hidden items with {@link useOverflowMenu}.\n */\n overflowButton?: (count: number, hiddenIds: string[]) => React.ReactNode;\n /**\n * The {@link OverflowItem}s (and {@link OverflowDivider}s) to lay out in one row or column.\n * Only items, dividers and the overflow button are measured: the container's whole content box\n * is the room for them, so other content placed in the row is not accounted for and could clip\n * items that still count as visible. Keep fixed content outside the Overflow (for example in a\n * surrounding flex row), or wrap it in an `OverflowItem` and pin it with `pinned`.\n */\n children: React.ReactNode;\n /**\n * Which end of the row overflows first (`start` is the start of the DOM order, so the right side\n * of a right-to-left row). While no item sets `priority` or `pinned` (`pinned={false}` does not\n * count) the first item (`end`) or the last one (`start`) is never hidden, as in 0.13; once any\n * item pins itself or sets a priority, only `pinned` items are protected, the first one included.\n * @default 'end'\n */\n overflowDirection?: OverflowDirection;\n /**\n * Where the overflow button goes while items are hidden: `'end'` after every item, sticking to\n * the end of the axis; `'before-hidden'` just before the first hidden item in DOM order, so it\n * stands in for the hidden items (a breadcrumb trail), and takes the row's gap as the items do.\n * With `'before-hidden'` the items must be children of the Overflow (Fragments and arrays are\n * opened): when the first hidden item is rendered by another component the button stays at the\n * end, with a development warning. The button moves without remounting. While nothing is\n * hidden there is no button, except the one `hasHiddenItems` reserves, at the end.\n * @default 'end'\n */\n buttonPosition?: 'end' | 'before-hidden';\n /**\n * The axis items are laid out on. `'vertical'` stacks them in a column and measures heights\n * (Fluent's `overflowAxis`); the column needs a definite height (a `height`, or a flex or grid\n * cell with one), since it has no room to measure otherwise.\n * @default 'horizontal'\n */\n orientation?: Orientation;\n /**\n * The number of items that stay visible however little room there is (pinned items count).\n * @default 0\n */\n minimumVisible?: number;\n /**\n * Renders the overflow button before the first measurement (for example in the server HTML) so\n * the row reserves its room; `overflowButton` then receives `0` and `[]`. It goes away after the\n * first measurement when every item fits.\n * @default false\n */\n hasHiddenItems?: boolean;\n /**\n * Called, from an effect, when the set of hidden items changes (not for the initial, empty set),\n * with the hidden `itemId`s in DOM order and the {@link OverflowChangeDetails}. Called once per\n * change in StrictMode, and only for a set that has been rendered. The Overflow always passes\n * `details`; it is typed optional until 1.0, as the second argument of every callback is, so a\n * handler of the hidden ids alone fits.\n */\n onOverflowChange?: (hiddenItems: string[], details?: OverflowChangeDetails) => void;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/**\n * An item hides in ascending `priority` (higher overflows later, default 0), or it is `pinned` and\n * never hides: `priority` or `pinned`, never both.\n */\nexport type OverflowItemPriorityProps =\n | {\n /**\n * Items with a lower priority overflow first; equal priorities follow the direction.\n * @default 0\n */\n priority?: number;\n pinned?: never;\n }\n | {\n /**\n * The item never overflows. Pinning any item drops the 0.13 protection of the first item for\n * the whole row; `pinned={false}` alone keeps it.\n * @default false\n */\n pinned?: boolean;\n priority?: never;\n };\n\n/** Properties for the OverflowItem sub-component. */\nexport type OverflowItemProps = OverflowItemBaseProps & OverflowItemPriorityProps;\n\n/** The props of an {@link OverflowItem} besides `priority` and `pinned`. */\nexport interface OverflowItemBaseProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Identifier for tracking this item's overflow visibility, unique within the Overflow (a\n * duplicate warns in development: items that share one are hidden and shown together).\n */\n itemId: string;\n /**\n * The group the item belongs to. A group is `'visible'`, `'hidden'` or `'overflow'` (some members\n * hidden); an {@link OverflowDivider} with the same `groupId` hides with a hidden group, and\n * {@link useIsOverflowGroupVisible} reads it.\n */\n groupId?: string;\n /**\n * Puts the item's props on its single element child (an `<li>`, a Toolbar button) instead of on\n * a wrapper `<div>`: handlers and refs are composed with the child's, classes and styles merged,\n * and the hidden state (`data-overflow-hidden`, `display: none`, `aria-hidden`, `inert`) wins\n * over the child's own. A child that is not a single element (text, several elements) renders in\n * the wrapper `<div>` and warns in development.\n * @default false\n */\n asChild?: boolean;\n /** Content of the overflow item: with `asChild`, the single element that takes its props. */\n children: React.ReactNode;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Properties for the OverflowDivider sub-component. */\nexport interface OverflowDividerProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The group the divider belongs to: it is hidden while that group is `'hidden'` and takes room\n * in the row otherwise. A group without items counts as visible.\n */\n groupId: string;\n ref?: React.Ref<HTMLDivElement>;\n}\n\n/** Result of {@link useOverflowMenu}. */\nexport interface UseOverflowMenuResult {\n /** `itemId`s of the hidden items, in DOM order (the caller's own array). */\n hiddenIds: string[];\n /** Number of hidden items. */\n count: number;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** A stable function that re-renders the calling component. */\nfunction useForceRender(): () => void {\n return React.useReducer((n: number) => n + 1, 0)[1];\n}\n\n// ---------------------------------------------------------------------------\n// Context (C-CONTEXT)\n// ---------------------------------------------------------------------------\n\ninterface OverflowContextValue {\n store: OverflowStore;\n hiddenIds: string[];\n hiddenSet: ReadonlySet<string>;\n groupVisibility: GroupVisibilityRecord;\n direction: OverflowDirection;\n orientation: Orientation;\n /** At least one item is hidden (not the button that `hasHiddenItems` reserves). */\n hasHiddenItems: boolean;\n}\n\nconst OverflowContext = React.createContext<OverflowContextValue | null>(null);\n\n/** Production fallback for a misplaced sub-component: a store that is never connected. */\nconst INERT_CONTEXT: OverflowContextValue = {\n store: /* @__PURE__ */ new OverflowStore(),\n hiddenIds: NO_IDS,\n hiddenSet: /* @__PURE__ */ new Set<string>(),\n groupVisibility: NO_GROUPS,\n direction: 'end',\n orientation: 'horizontal',\n hasHiddenItems: false,\n};\n\n/**\n * The enclosing Overflow's context. Outside an Overflow it throws in development and, in\n * production, logs an error once and returns an inert value (C-CONTEXT).\n */\nfunction useOverflowContext(componentName: string): OverflowContextValue {\n const ctx = React.useContext(OverflowContext);\n if (ctx) return ctx;\n reportMissingContext(componentName, 'Overflow');\n return INERT_CONTEXT;\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * The items an {@link Overflow} currently hides: their `itemId`s in DOM order and their count. Use\n * it in the component that `overflowButton` renders to list the hidden items in a menu. Must be\n * called inside `Overflow`.\n */\nexport function useOverflowMenu(): UseOverflowMenuResult {\n const { hiddenIds } = useOverflowContext('useOverflowMenu');\n // A copy per caller and snapshot: sorting or reversing it cannot affect other consumers.\n return React.useMemo(() => ({ hiddenIds: [...hiddenIds], count: hiddenIds.length }), [hiddenIds]);\n}\n\n/**\n * Whether the {@link OverflowItem} with `itemId` is currently shown (`false` while it overflows).\n * Must be called inside `Overflow`.\n */\nexport function useIsOverflowItemVisible(itemId: string): boolean {\n const { hiddenSet } = useOverflowContext('useIsOverflowItemVisible');\n return !hiddenSet.has(itemId);\n}\n\n/**\n * How much of the item group `groupId` is shown: `'visible'` (every member, and also a group\n * without items), `'hidden'` (none) or `'overflow'` (some). Must be called inside `Overflow`.\n */\nexport function useIsOverflowGroupVisible(groupId: string): OverflowGroupVisibility {\n const { groupVisibility } = useOverflowContext('useIsOverflowGroupVisible');\n return groupVisibility[groupId] ?? 'visible';\n}\n\n/**\n * Whether the enclosing {@link Overflow} currently hides at least one item (the button that the\n * `hasHiddenItems` prop reserves does not count). Must be called inside `Overflow`.\n */\nexport function useHasHiddenItems(): boolean {\n return useOverflowContext('useHasHiddenItems').hasHiddenItems;\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === Node.ELEMENT_NODE;\n}\n\n/**\n * Keeps `observer` on the element children of `parent`: unobserves the removed ones and observes\n * the added ones that are still attached to `parent` (records are replayed in order, so a child\n * moved or re-added within one batch ends up observed exactly when it is present).\n */\nfunction followDirectChildren(\n observer: ResizeObserver,\n parent: Element,\n records: readonly MutationRecord[],\n): void {\n for (const record of records) {\n if (record.type !== 'childList' || record.target !== parent) continue;\n record.removedNodes.forEach((node) => {\n if (isElement(node)) observer.unobserve(node);\n });\n record.addedNodes.forEach((node) => {\n if (isElement(node) && node.parentNode === parent) observer.observe(node);\n });\n }\n}\n\n/** Tracks `scrollWidth > clientWidth` of one element. */\nclass OverflowingStore {\n private element: HTMLElement | null = null;\n private value = false;\n private readonly listeners = new Set<() => void>();\n private teardown: (() => void) | null = null;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): boolean => this.value;\n\n getServerSnapshot = (): boolean => false;\n\n /** Follows `element` (layout effect of every render); re-subscribes when it changes. */\n setElement(element: HTMLElement | null): void {\n if (element === this.element) return;\n this.disconnect();\n this.element = element;\n if (element) this.teardown = this.observe(element);\n this.check();\n }\n\n disconnect(): void {\n this.teardown?.();\n this.teardown = null;\n this.element = null;\n }\n\n private observe(element: HTMLElement): () => void {\n const check = () => this.check();\n const cleanups: Array<() => void> = [];\n\n // Resizes of the element and of its direct children (content that grows or shrinks).\n const resizeObserver = hasResizeObserver() ? new ResizeObserver(check) : null;\n if (resizeObserver) {\n resizeObserver.observe(element);\n for (const child of Array.from(element.children)) resizeObserver.observe(child);\n cleanups.push(() => resizeObserver.disconnect());\n } else if (typeof window !== 'undefined') {\n window.addEventListener('resize', check);\n cleanups.push(() => window.removeEventListener('resize', check));\n }\n\n // Content added, removed or edited. Only a change of the direct children changes what the\n // ResizeObserver watches, and only those children are (un)observed; text edits and deeper\n // changes just re-check.\n if (typeof MutationObserver !== 'undefined') {\n const mutationObserver = new MutationObserver((records) => {\n if (resizeObserver) followDirectChildren(resizeObserver, element, records);\n check();\n });\n mutationObserver.observe(element, { childList: true, subtree: true, characterData: true });\n cleanups.push(() => mutationObserver.disconnect());\n }\n\n return () => cleanups.forEach((cleanup) => cleanup());\n }\n\n private check(): void {\n const el = this.element;\n const next = el !== null && el.scrollWidth > el.clientWidth;\n if (next === this.value) return;\n this.value = next;\n for (const listener of Array.from(this.listeners)) listener();\n }\n}\n\nfunction isRefObject(\n target: React.RefObject<HTMLElement | null> | HTMLElement | null | undefined,\n): target is React.RefObject<HTMLElement | null> {\n return target != null && typeof target === 'object' && 'current' in target;\n}\n\n/**\n * Whether `target`'s content is wider than the element (`scrollWidth > clientWidth`).\n *\n * `target` is a ref object or the element itself (for example from callback-ref state:\n * `const [el, setEl] = useState(null)` + `ref={setEl}`). The hook re-checks when the element\n * resizes, when its direct children resize, and when content is added, removed or edited; an\n * element that mounts later (a ref attached conditionally) is picked up after the render that\n * mounts it. Without `ResizeObserver` it re-checks on window `resize` and content changes. Returns\n * `false` on the server.\n */\nexport function useIsOverflowing(\n target: React.RefObject<HTMLElement | null> | HTMLElement | null,\n): boolean {\n const [store] = React.useState(() => new OverflowingStore());\n const isOverflowing = React.useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getServerSnapshot,\n );\n const forceRender = useForceRender();\n\n // Every render: follow the element the ref points to now (cheap identity check). A change found\n // here re-renders from the layout phase, before paint: useSyncExternalStore only subscribes in a\n // passive effect, so on mount it would pick the first value up after the browser painted.\n React.useLayoutEffect(() => {\n const unsubscribe = store.subscribe(forceRender);\n store.setElement(isRefObject(target) ? target.current : target);\n unsubscribe();\n });\n\n React.useLayoutEffect(() => () => store.disconnect(), [store]);\n\n return isOverflowing;\n}\n\n// ---------------------------------------------------------------------------\n// Components\n// ---------------------------------------------------------------------------\n\nconst ROOT_ORIENTATION_CLASSES: Record<Orientation, string> = {\n horizontal: 'items-center',\n vertical: 'flex-col items-start',\n};\n\n// The divider stretches across the row (to its height, or to a column's width) and lays its child\n// out on the row's cross axis: a child that stretches itself (Toolbar.Divider) spans the row, and\n// an explicitly sized child is centred in a row and kept at the start of a column.\nconst DIVIDER_ORIENTATION_CLASSES: Record<Orientation, string> = {\n horizontal: 'flex shrink-0 items-center self-stretch',\n vertical: 'flex shrink-0 flex-col items-start self-stretch',\n};\n\n// The button sticks to the end of the axis and keeps room inside for its own focus indicator while\n// it covers an item. After the items it keeps 4px from the last one; between items it takes the\n// row's gap, as they do (its size never depends on where it stands).\nconst BUTTON_CLASSES = {\n end: {\n horizontal:\n 'sticky -end-1 flex shrink-0 items-center self-stretch ps-1 ' +\n 'data-[overflow-pinned]:bg-background data-[overflow-pinned]:pe-1',\n vertical:\n 'sticky -bottom-1 flex shrink-0 items-center self-stretch pt-1 ' +\n 'data-[overflow-pinned]:bg-background data-[overflow-pinned]:pb-1',\n },\n 'before-hidden': {\n horizontal:\n 'sticky -end-1 flex shrink-0 items-center self-stretch ' +\n 'data-[overflow-pinned]:bg-background data-[overflow-pinned]:pe-1',\n vertical:\n 'sticky -bottom-1 flex shrink-0 items-center self-stretch ' +\n 'data-[overflow-pinned]:bg-background data-[overflow-pinned]:pb-1',\n },\n} as const satisfies Record<\n NonNullable<OverflowProps['buttonPosition']>,\n Record<Orientation, string>\n>;\n\n/**\n * The key of the button among the children of a `before-hidden` row; the keys of flattened\n * children start with a dot.\n */\nconst BUTTON_KEY = 'wave-overflow-button';\n\n/** The element of an item that takes focus: the item itself, else a Tab stop or a focusable element in it. */\nfunction focusTargetIn(item: HTMLElement): HTMLElement | null {\n if (isFocusable(item)) return item;\n return (\n getFirstTabbable(item) ??\n Array.from(item.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).find(isFocusable) ??\n null\n );\n}\n\n/**\n * Where focus goes when the overflow button held it and went away (C-DISABLED): the first item\n * the button stood for (`wereHidden`, in DOM order) that can take focus; else the nearest item\n * before them, then the items after them. Without such items, the nearest item to the end.\n */\nfunction overflowFocusFallback(\n items: ReadonlyArray<{ element: HTMLElement; id: string }>,\n wereHidden: readonly string[],\n): HTMLElement | null {\n const hidden = new Set(wereHidden);\n const first = items.findIndex(({ id }) => hidden.has(id));\n const candidates =\n first < 0\n ? [...items].reverse()\n : [\n ...items.filter(({ id }) => hidden.has(id)),\n ...items.slice(0, first).reverse(),\n ...items.slice(first).filter(({ id }) => !hidden.has(id)),\n ];\n for (const { element } of candidates) {\n const target = focusTargetIn(element);\n if (target) return target;\n }\n return null;\n}\n\ninterface OverflowButtonSlotProps extends React.HTMLAttributes<HTMLDivElement> {\n store: OverflowStore;\n /** The items the button stands for. */\n hiddenIds: string[];\n /** The store's ref callback for the wrapper. */\n buttonRef: (node: HTMLDivElement | null) => void;\n}\n\n/**\n * The overflow button's wrapper (internal). When every item fits again it unmounts; focus that it\n * held then moves to the first item it stood for (the items hidden at its last commit), so it\n * never falls to the body (`usePreserveFocus`). Focus inside the button's menu is not inside the\n * wrapper, so an open menu keeps its own focus return.\n */\nfunction OverflowButtonSlot({ store, hiddenIds, buttonRef, ...rest }: OverflowButtonSlotProps) {\n const elementRef = React.useRef<HTMLDivElement>(null);\n const ref = useMergedRefs<HTMLDivElement>(buttonRef, elementRef);\n const wereHiddenRef = React.useRef<readonly string[]>(NO_IDS);\n React.useLayoutEffect(() => {\n wereHiddenRef.current = hiddenIds;\n });\n usePreserveFocus(elementRef, () =>\n overflowFocusFallback(store.getItemElements(), wereHiddenRef.current),\n );\n return <div ref={ref} {...rest} />;\n}\nOverflowButtonSlot.displayName = 'OverflowButtonSlot';\n\n/**\n * The children of a `before-hidden` row with the button just before the item `firstHiddenId`\n * (Fragments and arrays opened, every child keyed, so the button moves without remounting), and\n * whether that item could not be found (the button is then last).\n */\nfunction placeButtonBeforeHidden(\n children: React.ReactNode,\n button: React.ReactElement | null,\n firstHiddenId: string | undefined,\n): { nodes: React.ReactNode[]; missing: boolean } {\n const nodes = flattenChildren(children).map(({ key, node }) =>\n React.isValidElement(node) ? React.cloneElement(node, { key }) : node,\n );\n if (!button) return { nodes, missing: false };\n const index =\n firstHiddenId === undefined\n ? -1\n : nodes.findIndex(\n (node) =>\n isElementOfType<{ itemId?: string }>(node, OverflowItem) &&\n node.props.itemId === firstHiddenId,\n );\n nodes.splice(index < 0 ? nodes.length : index, 0, button);\n return { nodes, missing: firstHiddenId !== undefined && index < 0 };\n}\n\nconst OverflowRoot = ({\n overflowButton,\n buttonPosition = 'end',\n overflowDirection = 'end',\n orientation = 'horizontal',\n minimumVisible = 0,\n hasHiddenItems = false,\n onOverflowChange,\n children,\n className,\n ref,\n ...rest\n}: OverflowProps) => {\n const [store] = React.useState(() => new OverflowStore());\n const hiddenIds = React.useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getServerSnapshot,\n );\n const measured = React.useSyncExternalStore(\n store.subscribe,\n store.getMeasured,\n store.getServerFlag,\n );\n const buttonCovers = React.useSyncExternalStore(\n store.subscribe,\n store.getButtonCovers,\n store.getServerFlag,\n );\n const groupVisibility = React.useSyncExternalStore(\n store.subscribe,\n store.getGroups,\n store.getServerGroups,\n );\n const setContainer = React.useCallback(\n (node: HTMLDivElement | null) => store.setContainer(node),\n [store],\n );\n const setButton = React.useCallback(\n (node: HTMLDivElement | null) => store.setButton(node),\n [store],\n );\n const containerRef = useMergedRefs<HTMLDivElement>(ref, setContainer);\n const forceRender = useForceRender();\n\n // The props the measurement depends on, before the observers connect (the effects of one\n // component run in order), so the first measurement already uses them.\n React.useLayoutEffect(() => {\n store.setConfig({ direction: overflowDirection, orientation, minimumVisible, hasHiddenItems });\n }, [store, overflowDirection, orientation, minimumVisible, hasHiddenItems]);\n\n // Observers are created once per instance (not per render or per children change). The first\n // measurement (in connect) re-renders from this layout effect, before paint: useSyncExternalStore\n // only subscribes in a passive effect, which can run after the browser painted every item.\n React.useLayoutEffect(() => {\n const unsubscribe = store.subscribe(forceRender);\n const disconnect = store.connect();\n unsubscribe();\n return disconnect;\n }, [store, forceRender]);\n\n // After every commit of the root (new children, a keyed reorder): items moved without any size\n // change or registration are re-measured before paint. Cheap when nothing moved.\n React.useLayoutEffect(() => {\n store.checkOrder();\n });\n\n const hiddenSet = React.useMemo(() => new Set(hiddenIds), [hiddenIds]);\n // The overflowButton's own copy (consumers may sort it in place).\n const buttonIds = React.useMemo(() => [...hiddenIds], [hiddenIds]);\n const hiddenCount = hiddenIds.length;\n const ctx = React.useMemo<OverflowContextValue>(\n () => ({\n store,\n hiddenIds,\n hiddenSet,\n groupVisibility,\n direction: overflowDirection,\n orientation,\n hasHiddenItems: hiddenCount > 0,\n }),\n [store, hiddenIds, hiddenSet, groupVisibility, overflowDirection, orientation, hiddenCount],\n );\n\n // Reported from an effect, once per change of the hidden set (the initial, empty set is no\n // change). The last reported set outlives the StrictMode effect replay, so it reports once.\n const emitOverflowChange = useEventCallback(onOverflowChange);\n const reported = React.useRef<string[]>(NO_IDS);\n const hasButton = overflowButton !== undefined;\n React.useEffect(() => {\n // The store's current set, and only once this render shows it: measuring the button that the\n // first hidden items bring in can hide more before the browser paints, and a re-render with\n // the final set always follows.\n const current = store.getSnapshot();\n if (!sameIds(current, hiddenIds) || !store.isSettled(hasButton)) return;\n if (sameIds(current, reported.current)) return;\n reported.current = current;\n emitOverflowChange([...current], {\n visibleItems: store.getVisibleIds(),\n // The consumer's own copy, without a prototype as the store's record: a group id such as\n // `constructor` or `__proto__` is an entry like any other, and an absent one reads nothing.\n groupVisibility: Object.assign(\n Object.create(null) as Record<string, OverflowGroupVisibility>,\n store.getGroups(),\n ),\n });\n }, [store, hiddenIds, hasButton, emitOverflowChange]);\n\n const button =\n (hiddenCount > 0 || (hasHiddenItems && !measured)) && overflowButton ? (\n // In the row's flow (it adds to the row height and follows justify-*), sticking to the end\n // of the axis when the visible items are wider than the room beside it. Browsers stop a\n // sticky element at the scroll container's padding, so -end-1 lets it reach the clipping\n // edge, and while pinned it keeps 4px inside for its own focus indicator. (WebKit stops a\n // sticky element short of the inline end of a right-to-left row; it stays in the row.)\n <OverflowButtonSlot\n key={BUTTON_KEY}\n store={store}\n hiddenIds={hiddenIds}\n buttonRef={setButton}\n // A list row (role=\"list\", a Breadcrumb trail) holds only list items.\n role={rest.role === 'list' ? 'listitem' : undefined}\n data-overflow-button=\"\"\n data-overflow-pinned={buttonCovers ? '' : undefined}\n className={cn(\n overflowClassNames.overflowButton,\n BUTTON_CLASSES[buttonPosition][orientation],\n )}\n >\n {overflowButton(hiddenCount, buttonIds)}\n </OverflowButtonSlot>\n ) : null;\n // `before-hidden`: the button stands just before the first hidden item (hiddenIds are in DOM\n // order).\n const placed =\n buttonPosition === 'before-hidden'\n ? placeButtonBeforeHidden(children, button, hiddenIds[0])\n : null;\n const unplaced = placed?.missing ?? false;\n React.useEffect(() => {\n if (!unplaced) return;\n warnOnce(\n 'Overflow:button-position',\n 'Overflow: buttonPosition=\"before-hidden\" puts the button before the first hidden ' +\n 'item only when that item is a child of the Overflow (Fragments and arrays are opened), ' +\n 'not one rendered by another component; the button is rendered after the items instead.',\n );\n }, [unplaced]);\n\n return (\n <OverflowContext.Provider value={ctx}>\n <div\n ref={containerRef}\n // The row clips its content at its padding edge: the 4px padding leaves room for the focus\n // indicator a focused item draws 4px around itself. No negative margin offsets it: the\n // row's box would then reach past its container, which a scroll container around an\n // edge-to-edge row (or the page) counts as overflow. The store measures the room without\n // the padding.\n className={cn(\n overflowClassNames.root,\n 'flex overflow-hidden p-1',\n ROOT_ORIENTATION_CLASSES[orientation],\n className,\n )}\n data-orientation={orientation}\n data-overflow-direction={overflowDirection}\n data-button-position={buttonPosition}\n {...rest}\n >\n {placed ? placed.nodes : children}\n {placed ? null : button}\n </div>\n </OverflowContext.Provider>\n );\n};\nOverflowRoot.displayName = 'Overflow';\n\n/**\n * One entry of an {@link Overflow}. `priority` (higher overflows later, default 0) or `pinned`\n * (never overflows) decide when it hides; setting either on any item makes every item without\n * `pinned` hidable, the first one included. `groupId` puts it in a group that an\n * {@link OverflowDivider} and {@link useIsOverflowGroupVisible} follow. While it does not fit it\n * stays mounted but is hidden (`data-overflow-hidden` and an inline `display: none` placed after\n * the consumer's own `style`), `aria-hidden` and `inert`. The inline style wins over the\n * consumer's `style.display` and over display utilities in any cascade layer (a prefixed Tailwind\n * app's `tw:flex` included), so a hidden item is never shown while it is counted in \"+N\". With\n * `asChild` the item renders no wrapper: its props are merged onto its single element child.\n * Must be rendered inside `Overflow`.\n */\nexport const OverflowItem = ({\n itemId,\n priority,\n pinned = false,\n groupId,\n asChild = false,\n children,\n className,\n style,\n ref,\n 'aria-hidden': ariaHidden,\n inert,\n ...rest\n}: OverflowItemProps) => {\n const { store, hiddenSet } = useOverflowContext('OverflowItem');\n const isHidden = hiddenSet.has(itemId);\n React.useEffect(() => store.registerItemId(itemId), [store, itemId]);\n\n // asChild: the single element (a Fragment around one is unwrapped) that takes the item's props.\n const child = asChild ? unwrapFragment(children) : undefined;\n const childElement = isCloneableElement(child) ? child : null;\n const childProps = childElement ? (childElement.props as Record<string, unknown>) : null;\n const { ref: childRef, ...ownChildProps } = childProps ?? {};\n const wrapsChildren = asChild && childElement === null && children != null;\n React.useEffect(() => {\n if (!wrapsChildren) return;\n warnOnce(\n 'Overflow.Item:as-child-children',\n 'Overflow.Item: asChild expects a single React element child (not text or several ' +\n 'elements); the children are rendered inside a <div> instead.',\n );\n }, [wrapsChildren]);\n\n const registerRef = React.useCallback(\n (node: HTMLElement | null) => (node ? store.registerItem(node, itemId) : undefined),\n [store, itemId],\n );\n const elementRef = React.useRef<HTMLElement | null>(null);\n const mergedRef = useMergedRefs<HTMLElement>(\n ref as React.Ref<HTMLElement> | undefined,\n registerRef,\n elementRef,\n childRef as React.Ref<HTMLElement> | undefined,\n );\n // After the ref has registered the item: its priority, pinned state or group re-measures the\n // row. Runs after every commit, not only when these change: registering an element (with asChild\n // the element is replaced by a toggle, a child of another type or key) resets what the store\n // knows about it, and the call is a no-op while nothing differs.\n React.useLayoutEffect(() => {\n if (elementRef.current) store.setItemMeta(elementRef.current, priority, pinned, groupId);\n });\n\n const itemClassName = cn(overflowItemClassNames.root, 'shrink-0', className);\n\n if (childElement) {\n // Only a hidden item sets these (and a consumer's own values), so a shown item keeps the\n // child's.\n const hiddenProps: Record<string, unknown> = isHidden\n ? { 'aria-hidden': true, inert: true, 'data-overflow-hidden': '' }\n : {};\n if (!isHidden && ariaHidden !== undefined) hiddenProps['aria-hidden'] = ariaHidden;\n if (!isHidden && inert !== undefined) hiddenProps.inert = inert;\n const merged = mergeProps(\n { ...rest, ...hiddenProps, className: itemClassName, style },\n ownChildProps,\n { oursWin: ['aria-hidden', 'inert', 'data-overflow-hidden'] },\n );\n // The hidden display wins over the child's own style, as it does over the consumer's.\n const mergedStyle = merged.style as React.CSSProperties | undefined;\n return React.cloneElement(childElement, {\n ...merged,\n ref: mergedRef,\n style: isHidden ? { ...mergedStyle, display: 'none' } : mergedStyle,\n } as Record<string, unknown>);\n }\n\n return (\n <div\n ref={mergedRef as React.Ref<HTMLDivElement>}\n className={itemClassName}\n {...rest}\n style={isHidden ? { ...style, display: 'none' } : style}\n aria-hidden={isHidden ? true : ariaHidden}\n inert={isHidden ? true : inert}\n data-overflow-hidden={isHidden ? '' : undefined}\n >\n {children}\n </div>\n );\n};\nOverflowItem.displayName = 'OverflowItem';\n\n/**\n * A divider between item groups of an {@link Overflow}, drawn by its children (for example a\n * vertical `Divider` or a `Toolbar.Divider`). It renders a `<div>` that stretches across the row\n * (to the row's height, or to a vertical column's width) and lays out its child on that axis, so\n * a child that stretches itself, such as `Toolbar.Divider`, spans the row; an explicitly sized\n * child is centred in a row and kept at the start of a column. It is measured like an item and\n * hidden, with `data-overflow-hidden`, an inline `display: none`, `aria-hidden` and `inert`, while\n * the group `groupId` is `'hidden'` (none of its items is shown). Must be rendered inside\n * `Overflow`.\n */\nexport const OverflowDivider = ({\n groupId,\n children,\n className,\n style,\n ref,\n 'aria-hidden': ariaHidden,\n inert,\n ...rest\n}: OverflowDividerProps) => {\n const { store, groupVisibility, orientation } = useOverflowContext('OverflowDivider');\n const isHidden = groupVisibility[groupId] === 'hidden';\n const registerRef = React.useCallback(\n (node: HTMLDivElement | null) => (node ? store.registerDivider(node, groupId) : undefined),\n [store, groupId],\n );\n const mergedRef = useMergedRefs<HTMLDivElement>(ref, registerRef);\n\n return (\n <div\n ref={mergedRef}\n className={cn(\n overflowDividerClassNames.root,\n DIVIDER_ORIENTATION_CLASSES[orientation],\n className,\n )}\n {...rest}\n style={isHidden ? { ...style, display: 'none' } : style}\n aria-hidden={isHidden ? true : ariaHidden}\n inert={isHidden ? true : inert}\n data-overflow-hidden={isHidden ? '' : undefined}\n >\n {children}\n </div>\n );\n};\nOverflowDivider.displayName = 'OverflowDivider';\n\n/**\n * A single row (or column) that hides the items which do not fit and shows an overflow button\n * instead.\n *\n * Wrap each entry in {@link OverflowItem} with a unique `itemId`; the row holds only items and\n * {@link OverflowDivider}s (other content is not measured, see `children`). Items are measured\n * while visible and hidden while they do not fit: by ascending `priority` (equal priorities from\n * the end of the DOM order, or from its start with `overflowDirection=\"start\"`), never a `pinned`\n * item and never below `minimumVisible`. Until an item sets `priority` or `pinned`, the first item\n * (`end`) or the last one (`start`) always stays, as in 0.13. `orientation=\"vertical\"` lays the\n * items out in a column and measures heights; the column needs a definite height. The room is the\n * row's own box, so it must not depend on the items shown: in a container as wide as its content,\n * such as a Toolbar at its default width, the row narrows as items hide and never gets the room\n * back to show them again; give the Overflow a width of its own, or put it in a row that takes its\n * width from its parent and let it fill that row.\n *\n * Items with the same `groupId` form a group that is `'visible'`, `'hidden'` or `'overflow'` (some\n * members hidden): a divider with that `groupId` hides with a hidden group,\n * {@link useIsOverflowGroupVisible} reads a group and {@link useHasHiddenItems} whether anything\n * is hidden. `onOverflowChange` reports the hidden `itemId`s and the group visibility when the\n * hidden items change. Hidden items get `data-overflow-hidden`, an inline `display: none`,\n * `aria-hidden` and `inert`. Reordered items (for example a keyed sort) are re-measured in their\n * new order. `overflowButton(count, hiddenIds)` renders the button after the visible items, or\n * just before the first hidden item with `buttonPosition=\"before-hidden\"` (its measured size is\n * reserved); components inside it can use {@link useOverflowMenu} to list the\n * hidden items (e.g. in a Menu), and {@link useIsOverflowItemVisible} reports a single item. In a\n * horizontal row the button sticks to the inline end, so a first item wider than the room beside\n * it cannot push it out of view: it then covers the end of that item and gets\n * `data-overflow-pinned`, with the `background` token behind it (a vertical column sticks it to\n * the bottom). (In a right-to-left row, WebKit stops the pinned button short of the end, still\n * inside the row.)\n *\n * The row clips what does not fit. So that the focus indicators of its items are not cut off, it\n * has a 4px padding: the items sit 4px in from its edges, and the row is 8px taller than they are.\n * An explicit width (such as `w-full` or a style width) includes that padding. The row never\n * reaches past its own box, so an edge-to-edge row adds no scrollbar to the page or to a scroll\n * container around it. A negative margin of 4px lines the items up with the content around the\n * row; add it only where nothing within 4px of the row scrolls (the row's box then reaches 4px past\n * its container on every side). `p-0` removes the room (focus indicators at the row's edges are\n * then clipped).\n *\n * Works without `ResizeObserver` (jsdom, old browsers): it then re-measures on window resize and\n * when items mount, unmount or move.\n *\n * The item is also `Overflow.Item` and the divider `Overflow.Divider`. The same components are\n * exported as `OverflowItem` and `OverflowDivider`; React Server Components import those flat names\n * (dotted access needs a client file).\n */\nexport const Overflow = /* @__PURE__ */ Object.assign(OverflowRoot, {\n Item: OverflowItem,\n Divider: OverflowDivider,\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";const e=require("../../lib/dev.cjs");var t=[];function n(){return typeof ResizeObserver<`u`}function r(e,t){return e===t?0:e.compareDocumentPosition(t)&Node.DOCUMENT_POSITION_FOLLOWING?-1:1}var i={childList:!0,subtree:!0};function a(e,t){return e.length===t.length&&e.every((e,n)=>e===t[n])}function o(t){e.warnOnce(`Overflow:duplicate:${t}`,`Overflow: several items share the itemId "${t}". Item ids must be unique within an Overflow; items with the same itemId are hidden and shown together.`)}var s=()=>{};function c(e,t){let n=t===`vertical`,r=0,i=0,a=e.ownerDocument.defaultView;if(a){let t=a.getComputedStyle(e);r=n?(parseFloat(t.paddingTop)||0)+(parseFloat(t.paddingBottom)||0):(parseFloat(t.paddingLeft)||0)+(parseFloat(t.paddingRight)||0),i=parseFloat(n?t.rowGap:t.columnGap)||0}return{available:(n?e.clientHeight:e.clientWidth)-r,gap:i}}function l(){return Object.create(null)}var u=l();function d(e,t,n,r){let i=-1,a=0;for(let o=0;o<e.length;o++){let s=n===`end`?e.length-1-o:o,{priority:c,pinned:l}=e[s];if(t[s]||l||s===r)continue;let u=c??0;(i<0||u<a)&&(i=s,a=u)}return i}var f=class{container=null;button=null;buttonSize=0;buttonMeasured=!1;items=new Map;dividers=new Map;itemIdCounts=new Map;sizes=new WeakMap;listeners=new Set;config={direction:`end`,orientation:`horizontal`,minimumVisible:0,hasHiddenItems:!1};hidden=t;itemIds=t;buttonCovers=!1;groups=u;measured=!1;order=[];connected=!1;observer=null;reorderObserver=null;removeResizeListener=null;subscribe=e=>(this.listeners.add(e),()=>{this.listeners.delete(e)});getSnapshot=()=>this.hidden;getServerSnapshot=()=>t;getButtonCovers=()=>this.buttonCovers;getGroups=()=>this.groups;getServerGroups=()=>u;getMeasured=()=>this.measured;getServerFlag=()=>!1;isSettled(e){return this.hidden.length===0||!e||this.buttonMeasured}getVisibleIds(){let e=new Set(this.hidden);return this.itemIds.filter(t=>!e.has(t))}getItemElements(){let e=this.container;return e?Array.from(this.items).filter(([t])=>t.isConnected&&e.contains(t)).sort(([e],[t])=>r(e,t)).map(([e,{id:t}])=>({element:e,id:t})):[]}setConfig(e){let t=this.config;(t.direction!==e.direction||t.orientation!==e.orientation||t.minimumVisible!==e.minimumVisible||t.hasHiddenItems!==e.hasHiddenItems)&&(t.orientation!==e.orientation&&(this.sizes=new WeakMap,this.buttonSize=0),this.config=e,this.measure())}connect=()=>{if(this.connected=!0,n()){this.observer=new ResizeObserver(()=>this.measure());for(let e of this.observedElements())this.observer.observe(e)}else if(typeof window<`u`){let e=()=>this.measure();window.addEventListener(`resize`,e),this.removeResizeListener=()=>window.removeEventListener(`resize`,e)}return typeof MutationObserver<`u`&&(this.reorderObserver=new MutationObserver(()=>this.checkOrder()),this.container&&this.reorderObserver.observe(this.container,i)),this.measure(),()=>{this.connected=!1,this.observer?.disconnect(),this.observer=null,this.reorderObserver?.disconnect(),this.reorderObserver=null,this.removeResizeListener?.(),this.removeResizeListener=null}};setContainer=e=>{e!==this.container&&(this.container&&this.observer?.unobserve(this.container),this.container=e,e&&this.observer?.observe(e),this.reorderObserver&&(this.reorderObserver.disconnect(),e&&this.reorderObserver.observe(e,i)),this.measure())};checkOrder=()=>{let e=this.order;for(let t=1;t<e.length;t++)if(r(e[t-1],e[t])>0){this.measure();return}};setButton=e=>{e!==this.button&&(this.button&&this.observer?.unobserve(this.button),this.button=e,e&&this.observer?.observe(e),this.measure())};registerItem(e,t){return this.items.set(e,{id:t,priority:void 0,pinned:!1,groupId:void 0}),this.observer?.observe(e),this.measure(),()=>{this.items.get(e)?.id===t&&(this.items.delete(e),this.observer?.unobserve(e),this.measure())}}setItemMeta(e,t,n,r){let i=this.items.get(e);!i||i.priority===t&&i.pinned===n&&i.groupId===r||(i.priority=t,i.pinned=n,i.groupId=r,this.measure())}registerDivider(e,t){return this.dividers.set(e,{groupId:t}),this.observer?.observe(e),this.measure(),()=>{this.dividers.delete(e)&&(this.observer?.unobserve(e),this.measure())}}registerItemId=t=>{if(!e.isDev)return s;let n=this.itemIdCounts,r=(n.get(t)??0)+1;return n.set(t,r),r>1&&o(t),()=>{let e=(n.get(t)??1)-1;e>0?n.set(t,e):n.delete(t)}};observedElements(){let e=[...this.items.keys(),...this.dividers.keys()];return this.container&&e.push(this.container),this.button&&e.push(this.button),e}measure(){let e=this.container;if(!this.connected||!e)return;let{direction:n,orientation:i,minimumVisible:o}=this.config,s=i===`vertical`,l=e=>s?e.offsetHeight:e.offsetWidth,u=([t])=>t.isConnected&&e.contains(t),f=Array.from(this.items).filter(u).sort(([e],[t])=>r(e,t)),p=Array.from(this.dividers).filter(u);this.order=f.map(([e])=>e);for(let[e]of[...f,...p])e.hasAttribute(`data-overflow-hidden`)||this.sizes.set(e,l(e));this.buttonMeasured=!1,this.button?.isConnected&&(this.buttonSize=l(this.button),this.buttonMeasured=!0);let{available:m,gap:h}=c(e,i),g=f.map(([,e])=>e),_=f.map(([e])=>this.sizes.get(e)??0),v=p.map(([e,{groupId:t}])=>({groupId:t,size:this.sizes.get(e)??0})),y=g.map(()=>!1),b=g.length,x=new Map;for(let{groupId:e}of g)e!==void 0&&x.set(e,(x.get(e)??0)+1);let S=()=>{let e=new Map;return g.forEach(({groupId:t},n)=>{t!==void 0&&!y[n]&&e.set(t,(e.get(t)??0)+1)}),e},C=()=>{let e=S(),t=0,n=0;g.forEach((e,r)=>{y[r]||(t+=_[r],n++)});for(let{groupId:r,size:i}of v)(!x.has(r)||e.has(r))&&(t+=i,n++);return t+h*Math.max(0,n-1)},w=C();if(w>m){let e=this.buttonSize>0?this.buttonSize+h:0,t=g.some(e=>e.pinned||e.priority!==void 0)?-1:n===`end`?0:g.length-1;for(;w+e>m&&b>o;){let e=d(g,y,n,t);if(e<0)break;y[e]=!0,b--,w=C()}}let T=g.filter((e,t)=>y[t]).map(e=>e.id),E=T.length>0&&w+this.buttonSize>m,D=this.nextGroups(x,S()),O=!a(T,this.hidden),k=g.map(e=>e.id),A=!a(k,this.itemIds),j=D!==this.groups;if(!O&&!A&&!j&&E===this.buttonCovers&&this.measured)return;O&&(this.hidden=T.length>0?T:t),A&&(this.itemIds=k),this.groups=D;let M=O||j||E!==this.buttonCovers||!this.measured&&this.config.hasHiddenItems;if(this.buttonCovers=E,this.measured=!0,M)for(let e of Array.from(this.listeners))e()}nextGroups(e,t){let n=l();for(let[r,i]of e){let e=t.get(r)??0;n[r]=e===0?`hidden`:e===i?`visible`:`overflow`}let r=Object.keys(n),i=this.groups;return r.length===Object.keys(i).length&&r.every(e=>n[e]===i[e])?i:r.length>0?n:u}};exports.NO_GROUPS=u,exports.NO_IDS=t,exports.OverflowStore=f,exports.hasResizeObserver=n,exports.sameIds=a;
|
|
2
|
+
//# sourceMappingURL=Overflow.store.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Overflow.store.cjs","names":["isDev","require_dev","NO_IDS","hasResizeObserver","documentOrder","a","b","REORDER_OBSERVER_OPTIONS","sameIds","id","i","warnDuplicateItemId","itemId","noop","readContainer","vertical","orientation","padding","gap","view","container","style","groupRecord","NO_GROUPS","pickVictim","best","bestPriority","step","metas","direction","hidden","pinned","protectedIndex","value","priority","OverflowStore","listener","hasButton","el","element","previous","config","onResize","node","order","meta","groupId","counts","count","remaining","elements","sizeOf","inRow","entries","dividerEntries","sizes","dividers","hiddenFlags","visibleCount","members","shownMembers","shown","usedRoom","total","size","used","available","reserve","minimumVisible","victim","next","covers","groups","hiddenChanged","itemIds","idsChanged","groupsChanged","changed","keys","current","key"],"sources":["../../../src/components/layout/Overflow.store.ts"],"sourcesContent":["import { isDev, warnOnce } from '../../lib/dev';\nimport type { Orientation } from '../../lib/types';\n\n/**\n * Which end of the row overflows first: `'end'` hides the last items in DOM order first, `'start'`\n * the first ones. Equal priorities follow it.\n */\nexport type OverflowDirection = 'end' | 'start';\n\n/**\n * How much of an item group is shown: `'visible'` (every member), `'hidden'` (none) or `'overflow'`\n * (some).\n */\nexport type OverflowGroupVisibility = 'visible' | 'hidden' | 'overflow';\n\n// ---------------------------------------------------------------------------\n// Measurement store\n// ---------------------------------------------------------------------------\n\n/**\n * The empty snapshot. Snapshots are internal: they are compared by identity and never handed to\n * consumers, who receive their own copies (see `useOverflowMenu` and `overflowButton`).\n */\nexport const NO_IDS: string[] = [];\n\nexport function hasResizeObserver(): boolean {\n return typeof ResizeObserver !== 'undefined';\n}\n\nfunction documentOrder(a: Element, b: Element): number {\n if (a === b) return 0;\n return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;\n}\n\n/** Moves anywhere in the row: items reordered directly or inside wrappers. */\nconst REORDER_OBSERVER_OPTIONS: MutationObserverInit = { childList: true, subtree: true };\n\nexport function sameIds(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((id, i) => id === b[i]);\n}\n\nfunction warnDuplicateItemId(itemId: string): void {\n warnOnce(\n `Overflow:duplicate:${itemId}`,\n `Overflow: several items share the itemId \"${itemId}\". Item ids must be unique within an ` +\n 'Overflow; items with the same itemId are hidden and shown together.',\n );\n}\n\nconst noop = () => {};\n\n/** Room available to items: the content box of the container on the axis, and the flex gap. */\nfunction readContainer(\n container: HTMLElement,\n orientation: Orientation,\n): { available: number; gap: number } {\n const vertical = orientation === 'vertical';\n let padding = 0;\n let gap = 0;\n const view = container.ownerDocument.defaultView;\n if (view) {\n const style = view.getComputedStyle(container);\n padding = vertical\n ? (parseFloat(style.paddingTop) || 0) + (parseFloat(style.paddingBottom) || 0)\n : (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);\n gap = parseFloat(vertical ? style.rowGap : style.columnGap) || 0;\n }\n return { available: (vertical ? container.clientHeight : container.clientWidth) - padding, gap };\n}\n\n/** What an item tells the store besides its id. */\nexport interface ItemMeta {\n id: string;\n priority: number | undefined;\n pinned: boolean;\n groupId: string | undefined;\n}\n\n/**\n * The visibility of each item group, by `groupId`. Records have no prototype, so a `groupId` such\n * as `constructor` or `__proto__` is an entry like any other.\n */\nexport type GroupVisibilityRecord = Record<string, OverflowGroupVisibility>;\n\n/** A new record without a prototype. */\nfunction groupRecord(): GroupVisibilityRecord {\n return Object.create(null) as GroupVisibilityRecord;\n}\n\n/** The empty record. Like `NO_IDS`, records are compared by identity and never handed out. */\nexport const NO_GROUPS: GroupVisibilityRecord = /* @__PURE__ */ groupRecord();\n\n/** What the store was told by the root's props. */\nexport interface StoreConfig {\n direction: OverflowDirection;\n orientation: Orientation;\n minimumVisible: number;\n /** The first measurement is published too (it takes the reserved button away). */\n hasHiddenItems: boolean;\n}\n\n/**\n * Picks the next item to hide: the visible, hidable item with the lowest priority; among equals\n * the last in DOM order for `end`, the first for `start`. `-1` when none is left.\n */\nfunction pickVictim(\n metas: readonly ItemMeta[],\n hidden: readonly boolean[],\n direction: OverflowDirection,\n protectedIndex: number,\n): number {\n let best = -1;\n let bestPriority = 0;\n for (let step = 0; step < metas.length; step++) {\n const i = direction === 'end' ? metas.length - 1 - step : step;\n const { priority, pinned } = metas[i];\n if (hidden[i] || pinned || i === protectedIndex) continue;\n const value = priority ?? 0;\n if (best < 0 || value < bestPriority) {\n best = i;\n bestPriority = value;\n }\n }\n return best;\n}\n\n/**\n * Tracks the container, the items, the dividers and the overflow button of one `Overflow` and\n * publishes the ids of the hidden items (DOM order), the visibility of each item group and whether\n * the button covers the end of the visible items, to `useSyncExternalStore`.\n *\n * - **Measurement never writes styles.** An item's or divider's size on the row's axis (width, or\n * height for a vertical row) is read (`offsetWidth` or `offsetHeight`) only while it is visible\n * and cached; a hidden one (`data-overflow-hidden` and an inline `display: none`, both rendered\n * by React) keeps its last visible size. All reads happen before React applies the result.\n * - **Membership-only updates.** A new snapshot is published only when the hidden set, a group's\n * visibility or whether the button covers the visible items changes, so a resize that hides the\n * same items renders nothing. The group record is a new object only when one entry changed.\n * - **One observer.** A single `ResizeObserver` (created when the root mounts) watches the\n * container, every item and divider and the overflow button. Without `ResizeObserver` the store\n * measures whenever something registers and on window `resize`.\n * - **Reorders.** A keyed reorder moves item elements without registering them again or changing\n * a size. The order of the last measurement is re-checked (n − 1 `compareDocumentPosition`\n * calls, no layout reads) after every commit of the root and, through a `MutationObserver`\n * (`childList`, `subtree`) on the container, after moves that do not render the root (a list\n * component inside the row that owns its order); only an inversion re-measures.\n */\nexport class OverflowStore {\n private container: HTMLElement | null = null;\n private button: HTMLElement | null = null;\n private buttonSize = 0;\n /** The button is mounted and its size was read. */\n private buttonMeasured = false;\n private readonly items = new Map<HTMLElement, ItemMeta>();\n /** The dividers, each with the group whose visibility it follows. */\n private readonly dividers = new Map<HTMLElement, { groupId: string }>();\n /** How many mounted items use each `itemId` (development only: a repeated one warns). */\n private readonly itemIdCounts = new Map<string, number>();\n /** The last visible size of each item on the measured axis. */\n private sizes = new WeakMap<HTMLElement, number>();\n private readonly listeners = new Set<() => void>();\n private config: StoreConfig = {\n direction: 'end',\n orientation: 'horizontal',\n minimumVisible: 0,\n hasHiddenItems: false,\n };\n private hidden: string[] = NO_IDS;\n /** Every item's id in DOM order, as of the last measurement. */\n private itemIds: string[] = NO_IDS;\n /** The visible items need more room than is left beside the button: it covers their end. */\n private buttonCovers = false;\n /** The visibility of each item group (a new object only when one changed). */\n private groups: GroupVisibilityRecord = NO_GROUPS;\n /** Whether a measurement has run (the server snapshot is `false`). */\n private measured = false;\n /** The item elements of the last measurement, in the DOM order they had then. */\n private order: HTMLElement[] = [];\n private connected = false;\n private observer: ResizeObserver | null = null;\n private reorderObserver: MutationObserver | null = null;\n private removeResizeListener: (() => void) | null = null;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): string[] => this.hidden;\n\n getServerSnapshot = (): string[] => NO_IDS;\n\n getButtonCovers = (): boolean => this.buttonCovers;\n\n getGroups = (): GroupVisibilityRecord => this.groups;\n\n getServerGroups = (): GroupVisibilityRecord => NO_GROUPS;\n\n getMeasured = (): boolean => this.measured;\n\n getServerFlag = (): boolean => false;\n\n /**\n * Whether the hidden set is final: the first items to overflow are measured without the button\n * that they bring in, so a set is provisional until a button that will render is measured.\n */\n isSettled(hasButton: boolean): boolean {\n return this.hidden.length === 0 || !hasButton || this.buttonMeasured;\n }\n\n /** The ids of the shown items, in DOM order. */\n getVisibleIds(): string[] {\n const hidden = new Set(this.hidden);\n return this.itemIds.filter((id) => !hidden.has(id));\n }\n\n /**\n * The item elements in the row now, in DOM order, with their ids (where focus goes when the\n * overflow button that held it goes away).\n */\n getItemElements(): Array<{ element: HTMLElement; id: string }> {\n const container = this.container;\n if (!container) return [];\n return Array.from(this.items)\n .filter(([el]) => el.isConnected && container.contains(el))\n .sort(([a], [b]) => documentOrder(a, b))\n .map(([element, { id }]) => ({ element, id }));\n }\n\n /** Applies the root's props (layout effect); measures again when one changed. */\n setConfig(config: StoreConfig): void {\n const previous = this.config;\n if (\n previous.direction === config.direction &&\n previous.orientation === config.orientation &&\n previous.minimumVisible === config.minimumVisible &&\n previous.hasHiddenItems === config.hasHiddenItems\n ) {\n return;\n }\n // Sizes of the other axis are of no use to hidden items or to an unmounted button.\n if (previous.orientation !== config.orientation) {\n this.sizes = new WeakMap();\n this.buttonSize = 0;\n }\n this.config = config;\n this.measure();\n }\n /** Starts observing (root layout effect); returns the teardown. */\n connect = (): (() => void) => {\n this.connected = true;\n if (hasResizeObserver()) {\n this.observer = new ResizeObserver(() => this.measure());\n for (const el of this.observedElements()) this.observer.observe(el);\n } else if (typeof window !== 'undefined') {\n const onResize = () => this.measure();\n window.addEventListener('resize', onResize);\n this.removeResizeListener = () => window.removeEventListener('resize', onResize);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.reorderObserver = new MutationObserver(() => this.checkOrder());\n if (this.container) this.reorderObserver.observe(this.container, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n return () => {\n this.connected = false;\n this.observer?.disconnect();\n this.observer = null;\n this.reorderObserver?.disconnect();\n this.reorderObserver = null;\n this.removeResizeListener?.();\n this.removeResizeListener = null;\n };\n };\n\n /** Ref callback of the container. */\n setContainer = (node: HTMLDivElement | null): void => {\n if (node === this.container) return;\n if (this.container) this.observer?.unobserve(this.container);\n this.container = node;\n if (node) this.observer?.observe(node);\n if (this.reorderObserver) {\n this.reorderObserver.disconnect();\n if (node) this.reorderObserver.observe(node, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n };\n\n /**\n * Re-measures when the items of the last measurement are no longer in DOM order (a keyed\n * reorder). Cheap: neighbour comparisons only, no layout reads.\n */\n checkOrder = (): void => {\n const order = this.order;\n for (let i = 1; i < order.length; i++) {\n if (documentOrder(order[i - 1], order[i]) > 0) {\n this.measure();\n return;\n }\n }\n };\n\n /** Ref callback of the overflow button wrapper. The last measured size outlives it. */\n setButton = (node: HTMLDivElement | null): void => {\n if (node === this.button) return;\n if (this.button) this.observer?.unobserve(this.button);\n this.button = node;\n if (node) this.observer?.observe(node);\n this.measure();\n };\n\n /** Registers an item element; returns its unregistration. */\n registerItem(el: HTMLElement, id: string): () => void {\n this.items.set(el, { id, priority: undefined, pinned: false, groupId: undefined });\n this.observer?.observe(el);\n this.measure();\n return () => {\n if (this.items.get(el)?.id !== id) return;\n this.items.delete(el);\n this.observer?.unobserve(el);\n this.measure();\n };\n }\n\n /** Updates an item's priority, pinned state and group (layout effect of the item). */\n setItemMeta(\n el: HTMLElement,\n priority: number | undefined,\n pinned: boolean,\n groupId: string | undefined,\n ): void {\n const meta = this.items.get(el);\n if (\n !meta ||\n (meta.priority === priority && meta.pinned === pinned && meta.groupId === groupId)\n ) {\n return;\n }\n meta.priority = priority;\n meta.pinned = pinned;\n meta.groupId = groupId;\n this.measure();\n }\n\n /** Registers a divider element with its group; returns its unregistration. */\n registerDivider(el: HTMLElement, groupId: string): () => void {\n this.dividers.set(el, { groupId });\n this.observer?.observe(el);\n this.measure();\n return () => {\n if (!this.dividers.delete(el)) return;\n this.observer?.unobserve(el);\n this.measure();\n };\n }\n\n /**\n * Counts the `itemId` of a mounted item (called from the item's effect, C-DEV); a second item\n * with an id already in use warns once per id. Returns the cleanup.\n */\n registerItemId = (itemId: string): (() => void) => {\n if (!isDev) return noop;\n const counts = this.itemIdCounts;\n const count = (counts.get(itemId) ?? 0) + 1;\n counts.set(itemId, count);\n if (count > 1) warnDuplicateItemId(itemId);\n return () => {\n const remaining = (counts.get(itemId) ?? 1) - 1;\n if (remaining > 0) counts.set(itemId, remaining);\n else counts.delete(itemId);\n };\n };\n\n private observedElements(): HTMLElement[] {\n const elements = [...this.items.keys(), ...this.dividers.keys()];\n if (this.container) elements.push(this.container);\n if (this.button) elements.push(this.button);\n return elements;\n }\n\n private measure(): void {\n const container = this.container;\n if (!this.connected || !container) return;\n const { direction, orientation, minimumVisible } = this.config;\n const vertical = orientation === 'vertical';\n const sizeOf = (el: HTMLElement) => (vertical ? el.offsetHeight : el.offsetWidth);\n const inRow = ([el]: [HTMLElement, unknown]) => el.isConnected && container.contains(el);\n\n // Reads first: sizes of the visible items and dividers, the button and the container.\n const entries = Array.from(this.items)\n .filter(inRow)\n .sort(([a], [b]) => documentOrder(a, b));\n const dividerEntries = Array.from(this.dividers).filter(inRow);\n this.order = entries.map(([el]) => el);\n for (const [el] of [...entries, ...dividerEntries]) {\n if (!el.hasAttribute('data-overflow-hidden')) this.sizes.set(el, sizeOf(el));\n }\n this.buttonMeasured = false;\n if (this.button?.isConnected) {\n this.buttonSize = sizeOf(this.button);\n this.buttonMeasured = true;\n }\n const { available, gap } = readContainer(container, orientation);\n\n const metas = entries.map(([, meta]) => meta);\n const sizes = entries.map(([el]) => this.sizes.get(el) ?? 0);\n const dividers = dividerEntries.map(([el, { groupId }]) => ({\n groupId,\n size: this.sizes.get(el) ?? 0,\n }));\n const hiddenFlags = metas.map(() => false);\n let visibleCount = metas.length;\n\n // A divider takes room while its group has a shown member (or no member at all).\n const members = new Map<string, number>();\n for (const { groupId } of metas) {\n if (groupId !== undefined) members.set(groupId, (members.get(groupId) ?? 0) + 1);\n }\n const shownMembers = (): Map<string, number> => {\n const shown = new Map<string, number>();\n metas.forEach(({ groupId }, i) => {\n if (groupId !== undefined && !hiddenFlags[i])\n shown.set(groupId, (shown.get(groupId) ?? 0) + 1);\n });\n return shown;\n };\n const usedRoom = (): number => {\n const shown = shownMembers();\n let total = 0;\n let count = 0;\n metas.forEach((_, i) => {\n if (hiddenFlags[i]) return;\n total += sizes[i];\n count++;\n });\n for (const { groupId, size } of dividers) {\n if (members.has(groupId) && !shown.has(groupId)) continue;\n total += size;\n count++;\n }\n return total + gap * Math.max(0, count - 1);\n };\n let used = usedRoom();\n\n if (used > available) {\n // Items beside the overflow button stay. Until an item sets a priority or pins itself, the\n // item at the far end from the hidden side stays too (0.13: the first item).\n const reserve = this.buttonSize > 0 ? this.buttonSize + gap : 0;\n const legacy = !metas.some((meta) => meta.pinned || meta.priority !== undefined);\n const protectedIndex = legacy ? (direction === 'end' ? 0 : metas.length - 1) : -1;\n while (used + reserve > available && visibleCount > minimumVisible) {\n const victim = pickVictim(metas, hiddenFlags, direction, protectedIndex);\n if (victim < 0) break;\n hiddenFlags[victim] = true;\n visibleCount--;\n used = usedRoom();\n }\n }\n\n const next = metas.filter((_, i) => hiddenFlags[i]).map((meta) => meta.id);\n // The sticky button eats the gap before it first; it covers the visible items only when the\n // two do not fit side by side.\n const covers = next.length > 0 && used + this.buttonSize > available;\n const groups = this.nextGroups(members, shownMembers());\n\n const hiddenChanged = !sameIds(next, this.hidden);\n const itemIds = metas.map((meta) => meta.id);\n const idsChanged = !sameIds(itemIds, this.itemIds);\n const groupsChanged = groups !== this.groups;\n if (\n !hiddenChanged &&\n !idsChanged &&\n !groupsChanged &&\n covers === this.buttonCovers &&\n this.measured\n ) {\n return;\n }\n // The same hidden set keeps its array, so the items and useOverflowMenu() do not update.\n if (hiddenChanged) this.hidden = next.length > 0 ? next : NO_IDS;\n if (idsChanged) this.itemIds = itemIds;\n this.groups = groups;\n const changed =\n hiddenChanged ||\n groupsChanged ||\n covers !== this.buttonCovers ||\n (!this.measured && this.config.hasHiddenItems);\n this.buttonCovers = covers;\n this.measured = true;\n if (changed) for (const listener of Array.from(this.listeners)) listener();\n }\n\n /** The group record of this measurement: the current object when nothing in it changed. */\n private nextGroups(\n members: ReadonlyMap<string, number>,\n shown: ReadonlyMap<string, number>,\n ): GroupVisibilityRecord {\n const next = groupRecord();\n for (const [groupId, total] of members) {\n const count = shown.get(groupId) ?? 0;\n next[groupId] = count === 0 ? 'hidden' : count === total ? 'visible' : 'overflow';\n }\n const keys = Object.keys(next);\n const current = this.groups;\n const same =\n keys.length === Object.keys(current).length &&\n keys.every((key) => next[key] === current[key]);\n return same ? current : keys.length > 0 ? next : NO_GROUPS;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isDev as e, warnOnce as t } from "../../lib/dev.mjs";
|
|
3
|
+
//#region src/components/layout/Overflow.store.ts
|
|
4
|
+
var n = [];
|
|
5
|
+
function r() {
|
|
6
|
+
return typeof ResizeObserver < "u";
|
|
7
|
+
}
|
|
8
|
+
function i(e, t) {
|
|
9
|
+
return e === t ? 0 : e.compareDocumentPosition(t) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
|
10
|
+
}
|
|
11
|
+
var a = {
|
|
12
|
+
childList: !0,
|
|
13
|
+
subtree: !0
|
|
14
|
+
};
|
|
15
|
+
function o(e, t) {
|
|
16
|
+
return e.length === t.length && e.every((e, n) => e === t[n]);
|
|
17
|
+
}
|
|
18
|
+
function s(e) {
|
|
19
|
+
t(`Overflow:duplicate:${e}`, `Overflow: several items share the itemId "${e}". Item ids must be unique within an Overflow; items with the same itemId are hidden and shown together.`);
|
|
20
|
+
}
|
|
21
|
+
var c = () => {};
|
|
22
|
+
function l(e, t) {
|
|
23
|
+
let n = t === "vertical", r = 0, i = 0, a = e.ownerDocument.defaultView;
|
|
24
|
+
if (a) {
|
|
25
|
+
let t = a.getComputedStyle(e);
|
|
26
|
+
r = n ? (parseFloat(t.paddingTop) || 0) + (parseFloat(t.paddingBottom) || 0) : (parseFloat(t.paddingLeft) || 0) + (parseFloat(t.paddingRight) || 0), i = parseFloat(n ? t.rowGap : t.columnGap) || 0;
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
available: (n ? e.clientHeight : e.clientWidth) - r,
|
|
30
|
+
gap: i
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function u() {
|
|
34
|
+
return Object.create(null);
|
|
35
|
+
}
|
|
36
|
+
var d = /* @__PURE__ */ u();
|
|
37
|
+
function f(e, t, n, r) {
|
|
38
|
+
let i = -1, a = 0;
|
|
39
|
+
for (let o = 0; o < e.length; o++) {
|
|
40
|
+
let s = n === "end" ? e.length - 1 - o : o, { priority: c, pinned: l } = e[s];
|
|
41
|
+
if (t[s] || l || s === r) continue;
|
|
42
|
+
let u = c ?? 0;
|
|
43
|
+
(i < 0 || u < a) && (i = s, a = u);
|
|
44
|
+
}
|
|
45
|
+
return i;
|
|
46
|
+
}
|
|
47
|
+
var p = class {
|
|
48
|
+
container = null;
|
|
49
|
+
button = null;
|
|
50
|
+
buttonSize = 0;
|
|
51
|
+
buttonMeasured = !1;
|
|
52
|
+
items = /* @__PURE__ */ new Map();
|
|
53
|
+
dividers = /* @__PURE__ */ new Map();
|
|
54
|
+
itemIdCounts = /* @__PURE__ */ new Map();
|
|
55
|
+
sizes = /* @__PURE__ */ new WeakMap();
|
|
56
|
+
listeners = /* @__PURE__ */ new Set();
|
|
57
|
+
config = {
|
|
58
|
+
direction: "end",
|
|
59
|
+
orientation: "horizontal",
|
|
60
|
+
minimumVisible: 0,
|
|
61
|
+
hasHiddenItems: !1
|
|
62
|
+
};
|
|
63
|
+
hidden = n;
|
|
64
|
+
itemIds = n;
|
|
65
|
+
buttonCovers = !1;
|
|
66
|
+
groups = d;
|
|
67
|
+
measured = !1;
|
|
68
|
+
order = [];
|
|
69
|
+
connected = !1;
|
|
70
|
+
observer = null;
|
|
71
|
+
reorderObserver = null;
|
|
72
|
+
removeResizeListener = null;
|
|
73
|
+
subscribe = (e) => (this.listeners.add(e), () => {
|
|
74
|
+
this.listeners.delete(e);
|
|
75
|
+
});
|
|
76
|
+
getSnapshot = () => this.hidden;
|
|
77
|
+
getServerSnapshot = () => n;
|
|
78
|
+
getButtonCovers = () => this.buttonCovers;
|
|
79
|
+
getGroups = () => this.groups;
|
|
80
|
+
getServerGroups = () => d;
|
|
81
|
+
getMeasured = () => this.measured;
|
|
82
|
+
getServerFlag = () => !1;
|
|
83
|
+
isSettled(e) {
|
|
84
|
+
return this.hidden.length === 0 || !e || this.buttonMeasured;
|
|
85
|
+
}
|
|
86
|
+
getVisibleIds() {
|
|
87
|
+
let e = new Set(this.hidden);
|
|
88
|
+
return this.itemIds.filter((t) => !e.has(t));
|
|
89
|
+
}
|
|
90
|
+
getItemElements() {
|
|
91
|
+
let e = this.container;
|
|
92
|
+
return e ? Array.from(this.items).filter(([t]) => t.isConnected && e.contains(t)).sort(([e], [t]) => i(e, t)).map(([e, { id: t }]) => ({
|
|
93
|
+
element: e,
|
|
94
|
+
id: t
|
|
95
|
+
})) : [];
|
|
96
|
+
}
|
|
97
|
+
setConfig(e) {
|
|
98
|
+
let t = this.config;
|
|
99
|
+
(t.direction !== e.direction || t.orientation !== e.orientation || t.minimumVisible !== e.minimumVisible || t.hasHiddenItems !== e.hasHiddenItems) && (t.orientation !== e.orientation && (this.sizes = /* @__PURE__ */ new WeakMap(), this.buttonSize = 0), this.config = e, this.measure());
|
|
100
|
+
}
|
|
101
|
+
connect = () => {
|
|
102
|
+
if (this.connected = !0, r()) {
|
|
103
|
+
this.observer = new ResizeObserver(() => this.measure());
|
|
104
|
+
for (let e of this.observedElements()) this.observer.observe(e);
|
|
105
|
+
} else if (typeof window < "u") {
|
|
106
|
+
let e = () => this.measure();
|
|
107
|
+
window.addEventListener("resize", e), this.removeResizeListener = () => window.removeEventListener("resize", e);
|
|
108
|
+
}
|
|
109
|
+
return typeof MutationObserver < "u" && (this.reorderObserver = new MutationObserver(() => this.checkOrder()), this.container && this.reorderObserver.observe(this.container, a)), this.measure(), () => {
|
|
110
|
+
this.connected = !1, this.observer?.disconnect(), this.observer = null, this.reorderObserver?.disconnect(), this.reorderObserver = null, this.removeResizeListener?.(), this.removeResizeListener = null;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
setContainer = (e) => {
|
|
114
|
+
e !== this.container && (this.container && this.observer?.unobserve(this.container), this.container = e, e && this.observer?.observe(e), this.reorderObserver && (this.reorderObserver.disconnect(), e && this.reorderObserver.observe(e, a)), this.measure());
|
|
115
|
+
};
|
|
116
|
+
checkOrder = () => {
|
|
117
|
+
let e = this.order;
|
|
118
|
+
for (let t = 1; t < e.length; t++) if (i(e[t - 1], e[t]) > 0) {
|
|
119
|
+
this.measure();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
setButton = (e) => {
|
|
124
|
+
e !== this.button && (this.button && this.observer?.unobserve(this.button), this.button = e, e && this.observer?.observe(e), this.measure());
|
|
125
|
+
};
|
|
126
|
+
registerItem(e, t) {
|
|
127
|
+
return this.items.set(e, {
|
|
128
|
+
id: t,
|
|
129
|
+
priority: void 0,
|
|
130
|
+
pinned: !1,
|
|
131
|
+
groupId: void 0
|
|
132
|
+
}), this.observer?.observe(e), this.measure(), () => {
|
|
133
|
+
this.items.get(e)?.id === t && (this.items.delete(e), this.observer?.unobserve(e), this.measure());
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
setItemMeta(e, t, n, r) {
|
|
137
|
+
let i = this.items.get(e);
|
|
138
|
+
!i || i.priority === t && i.pinned === n && i.groupId === r || (i.priority = t, i.pinned = n, i.groupId = r, this.measure());
|
|
139
|
+
}
|
|
140
|
+
registerDivider(e, t) {
|
|
141
|
+
return this.dividers.set(e, { groupId: t }), this.observer?.observe(e), this.measure(), () => {
|
|
142
|
+
this.dividers.delete(e) && (this.observer?.unobserve(e), this.measure());
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
registerItemId = (t) => {
|
|
146
|
+
if (!e) return c;
|
|
147
|
+
let n = this.itemIdCounts, r = (n.get(t) ?? 0) + 1;
|
|
148
|
+
return n.set(t, r), r > 1 && s(t), () => {
|
|
149
|
+
let e = (n.get(t) ?? 1) - 1;
|
|
150
|
+
e > 0 ? n.set(t, e) : n.delete(t);
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
observedElements() {
|
|
154
|
+
let e = [...this.items.keys(), ...this.dividers.keys()];
|
|
155
|
+
return this.container && e.push(this.container), this.button && e.push(this.button), e;
|
|
156
|
+
}
|
|
157
|
+
measure() {
|
|
158
|
+
let e = this.container;
|
|
159
|
+
if (!this.connected || !e) return;
|
|
160
|
+
let { direction: t, orientation: r, minimumVisible: a } = this.config, s = r === "vertical", c = (e) => s ? e.offsetHeight : e.offsetWidth, u = ([t]) => t.isConnected && e.contains(t), d = Array.from(this.items).filter(u).sort(([e], [t]) => i(e, t)), p = Array.from(this.dividers).filter(u);
|
|
161
|
+
this.order = d.map(([e]) => e);
|
|
162
|
+
for (let [e] of [...d, ...p]) e.hasAttribute("data-overflow-hidden") || this.sizes.set(e, c(e));
|
|
163
|
+
this.buttonMeasured = !1, this.button?.isConnected && (this.buttonSize = c(this.button), this.buttonMeasured = !0);
|
|
164
|
+
let { available: m, gap: h } = l(e, r), g = d.map(([, e]) => e), _ = d.map(([e]) => this.sizes.get(e) ?? 0), v = p.map(([e, { groupId: t }]) => ({
|
|
165
|
+
groupId: t,
|
|
166
|
+
size: this.sizes.get(e) ?? 0
|
|
167
|
+
})), y = g.map(() => !1), b = g.length, x = /* @__PURE__ */ new Map();
|
|
168
|
+
for (let { groupId: e } of g) e !== void 0 && x.set(e, (x.get(e) ?? 0) + 1);
|
|
169
|
+
let S = () => {
|
|
170
|
+
let e = /* @__PURE__ */ new Map();
|
|
171
|
+
return g.forEach(({ groupId: t }, n) => {
|
|
172
|
+
t !== void 0 && !y[n] && e.set(t, (e.get(t) ?? 0) + 1);
|
|
173
|
+
}), e;
|
|
174
|
+
}, C = () => {
|
|
175
|
+
let e = S(), t = 0, n = 0;
|
|
176
|
+
g.forEach((e, r) => {
|
|
177
|
+
y[r] || (t += _[r], n++);
|
|
178
|
+
});
|
|
179
|
+
for (let { groupId: r, size: i } of v) (!x.has(r) || e.has(r)) && (t += i, n++);
|
|
180
|
+
return t + h * Math.max(0, n - 1);
|
|
181
|
+
}, w = C();
|
|
182
|
+
if (w > m) {
|
|
183
|
+
let e = this.buttonSize > 0 ? this.buttonSize + h : 0, n = g.some((e) => e.pinned || e.priority !== void 0) ? -1 : t === "end" ? 0 : g.length - 1;
|
|
184
|
+
for (; w + e > m && b > a;) {
|
|
185
|
+
let e = f(g, y, t, n);
|
|
186
|
+
if (e < 0) break;
|
|
187
|
+
y[e] = !0, b--, w = C();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
let T = g.filter((e, t) => y[t]).map((e) => e.id), E = T.length > 0 && w + this.buttonSize > m, D = this.nextGroups(x, S()), O = !o(T, this.hidden), k = g.map((e) => e.id), A = !o(k, this.itemIds), j = D !== this.groups;
|
|
191
|
+
if (!O && !A && !j && E === this.buttonCovers && this.measured) return;
|
|
192
|
+
O && (this.hidden = T.length > 0 ? T : n), A && (this.itemIds = k), this.groups = D;
|
|
193
|
+
let M = O || j || E !== this.buttonCovers || !this.measured && this.config.hasHiddenItems;
|
|
194
|
+
if (this.buttonCovers = E, this.measured = !0, M) for (let e of Array.from(this.listeners)) e();
|
|
195
|
+
}
|
|
196
|
+
nextGroups(e, t) {
|
|
197
|
+
let n = u();
|
|
198
|
+
for (let [r, i] of e) {
|
|
199
|
+
let e = t.get(r) ?? 0;
|
|
200
|
+
n[r] = e === 0 ? "hidden" : e === i ? "visible" : "overflow";
|
|
201
|
+
}
|
|
202
|
+
let r = Object.keys(n), i = this.groups;
|
|
203
|
+
return r.length === Object.keys(i).length && r.every((e) => n[e] === i[e]) ? i : r.length > 0 ? n : d;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
//#endregion
|
|
207
|
+
export { d as NO_GROUPS, n as NO_IDS, p as OverflowStore, r as hasResizeObserver, o as sameIds };
|
|
208
|
+
|
|
209
|
+
//# sourceMappingURL=Overflow.store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Overflow.store.mjs","names":["NO_IDS","hasResizeObserver","documentOrder","a","b","REORDER_OBSERVER_OPTIONS","sameIds","id","i","warnDuplicateItemId","itemId","noop","readContainer","vertical","orientation","padding","gap","view","container","style","groupRecord","NO_GROUPS","pickVictim","best","bestPriority","step","metas","direction","hidden","pinned","protectedIndex","value","priority","OverflowStore","listener","hasButton","el","element","previous","config","onResize","node","order","meta","groupId","isDev","counts","count","remaining","elements","sizeOf","inRow","entries","dividerEntries","sizes","dividers","hiddenFlags","visibleCount","members","shownMembers","shown","usedRoom","total","size","used","available","reserve","minimumVisible","victim","next","covers","groups","hiddenChanged","itemIds","idsChanged","groupsChanged","changed","keys","current","key"],"sources":["../../../src/components/layout/Overflow.store.ts"],"sourcesContent":["import { isDev, warnOnce } from '../../lib/dev';\nimport type { Orientation } from '../../lib/types';\n\n/**\n * Which end of the row overflows first: `'end'` hides the last items in DOM order first, `'start'`\n * the first ones. Equal priorities follow it.\n */\nexport type OverflowDirection = 'end' | 'start';\n\n/**\n * How much of an item group is shown: `'visible'` (every member), `'hidden'` (none) or `'overflow'`\n * (some).\n */\nexport type OverflowGroupVisibility = 'visible' | 'hidden' | 'overflow';\n\n// ---------------------------------------------------------------------------\n// Measurement store\n// ---------------------------------------------------------------------------\n\n/**\n * The empty snapshot. Snapshots are internal: they are compared by identity and never handed to\n * consumers, who receive their own copies (see `useOverflowMenu` and `overflowButton`).\n */\nexport const NO_IDS: string[] = [];\n\nexport function hasResizeObserver(): boolean {\n return typeof ResizeObserver !== 'undefined';\n}\n\nfunction documentOrder(a: Element, b: Element): number {\n if (a === b) return 0;\n return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;\n}\n\n/** Moves anywhere in the row: items reordered directly or inside wrappers. */\nconst REORDER_OBSERVER_OPTIONS: MutationObserverInit = { childList: true, subtree: true };\n\nexport function sameIds(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((id, i) => id === b[i]);\n}\n\nfunction warnDuplicateItemId(itemId: string): void {\n warnOnce(\n `Overflow:duplicate:${itemId}`,\n `Overflow: several items share the itemId \"${itemId}\". Item ids must be unique within an ` +\n 'Overflow; items with the same itemId are hidden and shown together.',\n );\n}\n\nconst noop = () => {};\n\n/** Room available to items: the content box of the container on the axis, and the flex gap. */\nfunction readContainer(\n container: HTMLElement,\n orientation: Orientation,\n): { available: number; gap: number } {\n const vertical = orientation === 'vertical';\n let padding = 0;\n let gap = 0;\n const view = container.ownerDocument.defaultView;\n if (view) {\n const style = view.getComputedStyle(container);\n padding = vertical\n ? (parseFloat(style.paddingTop) || 0) + (parseFloat(style.paddingBottom) || 0)\n : (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);\n gap = parseFloat(vertical ? style.rowGap : style.columnGap) || 0;\n }\n return { available: (vertical ? container.clientHeight : container.clientWidth) - padding, gap };\n}\n\n/** What an item tells the store besides its id. */\nexport interface ItemMeta {\n id: string;\n priority: number | undefined;\n pinned: boolean;\n groupId: string | undefined;\n}\n\n/**\n * The visibility of each item group, by `groupId`. Records have no prototype, so a `groupId` such\n * as `constructor` or `__proto__` is an entry like any other.\n */\nexport type GroupVisibilityRecord = Record<string, OverflowGroupVisibility>;\n\n/** A new record without a prototype. */\nfunction groupRecord(): GroupVisibilityRecord {\n return Object.create(null) as GroupVisibilityRecord;\n}\n\n/** The empty record. Like `NO_IDS`, records are compared by identity and never handed out. */\nexport const NO_GROUPS: GroupVisibilityRecord = /* @__PURE__ */ groupRecord();\n\n/** What the store was told by the root's props. */\nexport interface StoreConfig {\n direction: OverflowDirection;\n orientation: Orientation;\n minimumVisible: number;\n /** The first measurement is published too (it takes the reserved button away). */\n hasHiddenItems: boolean;\n}\n\n/**\n * Picks the next item to hide: the visible, hidable item with the lowest priority; among equals\n * the last in DOM order for `end`, the first for `start`. `-1` when none is left.\n */\nfunction pickVictim(\n metas: readonly ItemMeta[],\n hidden: readonly boolean[],\n direction: OverflowDirection,\n protectedIndex: number,\n): number {\n let best = -1;\n let bestPriority = 0;\n for (let step = 0; step < metas.length; step++) {\n const i = direction === 'end' ? metas.length - 1 - step : step;\n const { priority, pinned } = metas[i];\n if (hidden[i] || pinned || i === protectedIndex) continue;\n const value = priority ?? 0;\n if (best < 0 || value < bestPriority) {\n best = i;\n bestPriority = value;\n }\n }\n return best;\n}\n\n/**\n * Tracks the container, the items, the dividers and the overflow button of one `Overflow` and\n * publishes the ids of the hidden items (DOM order), the visibility of each item group and whether\n * the button covers the end of the visible items, to `useSyncExternalStore`.\n *\n * - **Measurement never writes styles.** An item's or divider's size on the row's axis (width, or\n * height for a vertical row) is read (`offsetWidth` or `offsetHeight`) only while it is visible\n * and cached; a hidden one (`data-overflow-hidden` and an inline `display: none`, both rendered\n * by React) keeps its last visible size. All reads happen before React applies the result.\n * - **Membership-only updates.** A new snapshot is published only when the hidden set, a group's\n * visibility or whether the button covers the visible items changes, so a resize that hides the\n * same items renders nothing. The group record is a new object only when one entry changed.\n * - **One observer.** A single `ResizeObserver` (created when the root mounts) watches the\n * container, every item and divider and the overflow button. Without `ResizeObserver` the store\n * measures whenever something registers and on window `resize`.\n * - **Reorders.** A keyed reorder moves item elements without registering them again or changing\n * a size. The order of the last measurement is re-checked (n − 1 `compareDocumentPosition`\n * calls, no layout reads) after every commit of the root and, through a `MutationObserver`\n * (`childList`, `subtree`) on the container, after moves that do not render the root (a list\n * component inside the row that owns its order); only an inversion re-measures.\n */\nexport class OverflowStore {\n private container: HTMLElement | null = null;\n private button: HTMLElement | null = null;\n private buttonSize = 0;\n /** The button is mounted and its size was read. */\n private buttonMeasured = false;\n private readonly items = new Map<HTMLElement, ItemMeta>();\n /** The dividers, each with the group whose visibility it follows. */\n private readonly dividers = new Map<HTMLElement, { groupId: string }>();\n /** How many mounted items use each `itemId` (development only: a repeated one warns). */\n private readonly itemIdCounts = new Map<string, number>();\n /** The last visible size of each item on the measured axis. */\n private sizes = new WeakMap<HTMLElement, number>();\n private readonly listeners = new Set<() => void>();\n private config: StoreConfig = {\n direction: 'end',\n orientation: 'horizontal',\n minimumVisible: 0,\n hasHiddenItems: false,\n };\n private hidden: string[] = NO_IDS;\n /** Every item's id in DOM order, as of the last measurement. */\n private itemIds: string[] = NO_IDS;\n /** The visible items need more room than is left beside the button: it covers their end. */\n private buttonCovers = false;\n /** The visibility of each item group (a new object only when one changed). */\n private groups: GroupVisibilityRecord = NO_GROUPS;\n /** Whether a measurement has run (the server snapshot is `false`). */\n private measured = false;\n /** The item elements of the last measurement, in the DOM order they had then. */\n private order: HTMLElement[] = [];\n private connected = false;\n private observer: ResizeObserver | null = null;\n private reorderObserver: MutationObserver | null = null;\n private removeResizeListener: (() => void) | null = null;\n\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): string[] => this.hidden;\n\n getServerSnapshot = (): string[] => NO_IDS;\n\n getButtonCovers = (): boolean => this.buttonCovers;\n\n getGroups = (): GroupVisibilityRecord => this.groups;\n\n getServerGroups = (): GroupVisibilityRecord => NO_GROUPS;\n\n getMeasured = (): boolean => this.measured;\n\n getServerFlag = (): boolean => false;\n\n /**\n * Whether the hidden set is final: the first items to overflow are measured without the button\n * that they bring in, so a set is provisional until a button that will render is measured.\n */\n isSettled(hasButton: boolean): boolean {\n return this.hidden.length === 0 || !hasButton || this.buttonMeasured;\n }\n\n /** The ids of the shown items, in DOM order. */\n getVisibleIds(): string[] {\n const hidden = new Set(this.hidden);\n return this.itemIds.filter((id) => !hidden.has(id));\n }\n\n /**\n * The item elements in the row now, in DOM order, with their ids (where focus goes when the\n * overflow button that held it goes away).\n */\n getItemElements(): Array<{ element: HTMLElement; id: string }> {\n const container = this.container;\n if (!container) return [];\n return Array.from(this.items)\n .filter(([el]) => el.isConnected && container.contains(el))\n .sort(([a], [b]) => documentOrder(a, b))\n .map(([element, { id }]) => ({ element, id }));\n }\n\n /** Applies the root's props (layout effect); measures again when one changed. */\n setConfig(config: StoreConfig): void {\n const previous = this.config;\n if (\n previous.direction === config.direction &&\n previous.orientation === config.orientation &&\n previous.minimumVisible === config.minimumVisible &&\n previous.hasHiddenItems === config.hasHiddenItems\n ) {\n return;\n }\n // Sizes of the other axis are of no use to hidden items or to an unmounted button.\n if (previous.orientation !== config.orientation) {\n this.sizes = new WeakMap();\n this.buttonSize = 0;\n }\n this.config = config;\n this.measure();\n }\n /** Starts observing (root layout effect); returns the teardown. */\n connect = (): (() => void) => {\n this.connected = true;\n if (hasResizeObserver()) {\n this.observer = new ResizeObserver(() => this.measure());\n for (const el of this.observedElements()) this.observer.observe(el);\n } else if (typeof window !== 'undefined') {\n const onResize = () => this.measure();\n window.addEventListener('resize', onResize);\n this.removeResizeListener = () => window.removeEventListener('resize', onResize);\n }\n if (typeof MutationObserver !== 'undefined') {\n this.reorderObserver = new MutationObserver(() => this.checkOrder());\n if (this.container) this.reorderObserver.observe(this.container, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n return () => {\n this.connected = false;\n this.observer?.disconnect();\n this.observer = null;\n this.reorderObserver?.disconnect();\n this.reorderObserver = null;\n this.removeResizeListener?.();\n this.removeResizeListener = null;\n };\n };\n\n /** Ref callback of the container. */\n setContainer = (node: HTMLDivElement | null): void => {\n if (node === this.container) return;\n if (this.container) this.observer?.unobserve(this.container);\n this.container = node;\n if (node) this.observer?.observe(node);\n if (this.reorderObserver) {\n this.reorderObserver.disconnect();\n if (node) this.reorderObserver.observe(node, REORDER_OBSERVER_OPTIONS);\n }\n this.measure();\n };\n\n /**\n * Re-measures when the items of the last measurement are no longer in DOM order (a keyed\n * reorder). Cheap: neighbour comparisons only, no layout reads.\n */\n checkOrder = (): void => {\n const order = this.order;\n for (let i = 1; i < order.length; i++) {\n if (documentOrder(order[i - 1], order[i]) > 0) {\n this.measure();\n return;\n }\n }\n };\n\n /** Ref callback of the overflow button wrapper. The last measured size outlives it. */\n setButton = (node: HTMLDivElement | null): void => {\n if (node === this.button) return;\n if (this.button) this.observer?.unobserve(this.button);\n this.button = node;\n if (node) this.observer?.observe(node);\n this.measure();\n };\n\n /** Registers an item element; returns its unregistration. */\n registerItem(el: HTMLElement, id: string): () => void {\n this.items.set(el, { id, priority: undefined, pinned: false, groupId: undefined });\n this.observer?.observe(el);\n this.measure();\n return () => {\n if (this.items.get(el)?.id !== id) return;\n this.items.delete(el);\n this.observer?.unobserve(el);\n this.measure();\n };\n }\n\n /** Updates an item's priority, pinned state and group (layout effect of the item). */\n setItemMeta(\n el: HTMLElement,\n priority: number | undefined,\n pinned: boolean,\n groupId: string | undefined,\n ): void {\n const meta = this.items.get(el);\n if (\n !meta ||\n (meta.priority === priority && meta.pinned === pinned && meta.groupId === groupId)\n ) {\n return;\n }\n meta.priority = priority;\n meta.pinned = pinned;\n meta.groupId = groupId;\n this.measure();\n }\n\n /** Registers a divider element with its group; returns its unregistration. */\n registerDivider(el: HTMLElement, groupId: string): () => void {\n this.dividers.set(el, { groupId });\n this.observer?.observe(el);\n this.measure();\n return () => {\n if (!this.dividers.delete(el)) return;\n this.observer?.unobserve(el);\n this.measure();\n };\n }\n\n /**\n * Counts the `itemId` of a mounted item (called from the item's effect, C-DEV); a second item\n * with an id already in use warns once per id. Returns the cleanup.\n */\n registerItemId = (itemId: string): (() => void) => {\n if (!isDev) return noop;\n const counts = this.itemIdCounts;\n const count = (counts.get(itemId) ?? 0) + 1;\n counts.set(itemId, count);\n if (count > 1) warnDuplicateItemId(itemId);\n return () => {\n const remaining = (counts.get(itemId) ?? 1) - 1;\n if (remaining > 0) counts.set(itemId, remaining);\n else counts.delete(itemId);\n };\n };\n\n private observedElements(): HTMLElement[] {\n const elements = [...this.items.keys(), ...this.dividers.keys()];\n if (this.container) elements.push(this.container);\n if (this.button) elements.push(this.button);\n return elements;\n }\n\n private measure(): void {\n const container = this.container;\n if (!this.connected || !container) return;\n const { direction, orientation, minimumVisible } = this.config;\n const vertical = orientation === 'vertical';\n const sizeOf = (el: HTMLElement) => (vertical ? el.offsetHeight : el.offsetWidth);\n const inRow = ([el]: [HTMLElement, unknown]) => el.isConnected && container.contains(el);\n\n // Reads first: sizes of the visible items and dividers, the button and the container.\n const entries = Array.from(this.items)\n .filter(inRow)\n .sort(([a], [b]) => documentOrder(a, b));\n const dividerEntries = Array.from(this.dividers).filter(inRow);\n this.order = entries.map(([el]) => el);\n for (const [el] of [...entries, ...dividerEntries]) {\n if (!el.hasAttribute('data-overflow-hidden')) this.sizes.set(el, sizeOf(el));\n }\n this.buttonMeasured = false;\n if (this.button?.isConnected) {\n this.buttonSize = sizeOf(this.button);\n this.buttonMeasured = true;\n }\n const { available, gap } = readContainer(container, orientation);\n\n const metas = entries.map(([, meta]) => meta);\n const sizes = entries.map(([el]) => this.sizes.get(el) ?? 0);\n const dividers = dividerEntries.map(([el, { groupId }]) => ({\n groupId,\n size: this.sizes.get(el) ?? 0,\n }));\n const hiddenFlags = metas.map(() => false);\n let visibleCount = metas.length;\n\n // A divider takes room while its group has a shown member (or no member at all).\n const members = new Map<string, number>();\n for (const { groupId } of metas) {\n if (groupId !== undefined) members.set(groupId, (members.get(groupId) ?? 0) + 1);\n }\n const shownMembers = (): Map<string, number> => {\n const shown = new Map<string, number>();\n metas.forEach(({ groupId }, i) => {\n if (groupId !== undefined && !hiddenFlags[i])\n shown.set(groupId, (shown.get(groupId) ?? 0) + 1);\n });\n return shown;\n };\n const usedRoom = (): number => {\n const shown = shownMembers();\n let total = 0;\n let count = 0;\n metas.forEach((_, i) => {\n if (hiddenFlags[i]) return;\n total += sizes[i];\n count++;\n });\n for (const { groupId, size } of dividers) {\n if (members.has(groupId) && !shown.has(groupId)) continue;\n total += size;\n count++;\n }\n return total + gap * Math.max(0, count - 1);\n };\n let used = usedRoom();\n\n if (used > available) {\n // Items beside the overflow button stay. Until an item sets a priority or pins itself, the\n // item at the far end from the hidden side stays too (0.13: the first item).\n const reserve = this.buttonSize > 0 ? this.buttonSize + gap : 0;\n const legacy = !metas.some((meta) => meta.pinned || meta.priority !== undefined);\n const protectedIndex = legacy ? (direction === 'end' ? 0 : metas.length - 1) : -1;\n while (used + reserve > available && visibleCount > minimumVisible) {\n const victim = pickVictim(metas, hiddenFlags, direction, protectedIndex);\n if (victim < 0) break;\n hiddenFlags[victim] = true;\n visibleCount--;\n used = usedRoom();\n }\n }\n\n const next = metas.filter((_, i) => hiddenFlags[i]).map((meta) => meta.id);\n // The sticky button eats the gap before it first; it covers the visible items only when the\n // two do not fit side by side.\n const covers = next.length > 0 && used + this.buttonSize > available;\n const groups = this.nextGroups(members, shownMembers());\n\n const hiddenChanged = !sameIds(next, this.hidden);\n const itemIds = metas.map((meta) => meta.id);\n const idsChanged = !sameIds(itemIds, this.itemIds);\n const groupsChanged = groups !== this.groups;\n if (\n !hiddenChanged &&\n !idsChanged &&\n !groupsChanged &&\n covers === this.buttonCovers &&\n this.measured\n ) {\n return;\n }\n // The same hidden set keeps its array, so the items and useOverflowMenu() do not update.\n if (hiddenChanged) this.hidden = next.length > 0 ? next : NO_IDS;\n if (idsChanged) this.itemIds = itemIds;\n this.groups = groups;\n const changed =\n hiddenChanged ||\n groupsChanged ||\n covers !== this.buttonCovers ||\n (!this.measured && this.config.hasHiddenItems);\n this.buttonCovers = covers;\n this.measured = true;\n if (changed) for (const listener of Array.from(this.listeners)) listener();\n }\n\n /** The group record of this measurement: the current object when nothing in it changed. */\n private nextGroups(\n members: ReadonlyMap<string, number>,\n shown: ReadonlyMap<string, number>,\n ): GroupVisibilityRecord {\n const next = groupRecord();\n for (const [groupId, total] of members) {\n const count = shown.get(groupId) ?? 0;\n next[groupId] = count === 0 ? 'hidden' : count === total ? 'visible' : 'overflow';\n }\n const keys = Object.keys(next);\n const current = this.groups;\n const same =\n keys.length === Object.keys(current).length &&\n keys.every((key) => next[key] === current[key]);\n return same ? current : keys.length > 0 ? next : NO_GROUPS;\n }\n}\n"],"mappings":";;;AAuBA,IAAaA,IAAmB,CAAC;AAEjC,SAAgBC,IAA6B;CAC3C,OAAO,OAAO,iBAAmB;AACnC;AAEA,SAASC,EAAc,GAAY,GAAoB;CAErD,OADIC,MAAMC,IAAU,IACbD,EAAE,wBAAwBC,CAAC,IAAI,KAAK,8BAA8B,KAAK;AAChF;AAGA,IAAMC,IAAiD;CAAE,WAAW;CAAM,SAAS;AAAK;AAExF,SAAgBC,EAAQ,GAAsB,GAA+B;CAC3E,OAAOH,EAAE,WAAWC,EAAE,UAAUD,EAAE,OAAO,GAAI,MAAMI,MAAOH,EAAEI,EAAE;AAChE;AAEA,SAASC,EAAoB,GAAsB;CACjD,EACE,sBAAsBC,KACtB,6CAA6CA,EAAO,yGAEtD;AACF;AAEA,IAAMC,UAAa,CAAC;AAGpB,SAASC,EACP,GACA,GACoC;CACpC,IAAMC,IAAWC,MAAgB,YAC7BC,IAAU,GACVC,IAAM,GACJC,IAAOC,EAAU,cAAc;CACrC,IAAID,GAAM;EACR,IAAME,IAAQF,EAAK,iBAAiBC,CAAS;EAI7C,AAHA,IAAUL,KACL,WAAWM,EAAM,UAAU,KAAK,MAAM,WAAWA,EAAM,aAAa,KAAK,MACzE,WAAWA,EAAM,WAAW,KAAK,MAAM,WAAWA,EAAM,YAAY,KAAK,IAC9E,IAAM,WAAWN,IAAWM,EAAM,SAASA,EAAM,SAAS,KAAK;CACjE;CACA,OAAO;EAAE,YAAYN,IAAWK,EAAU,eAAeA,EAAU,eAAeH;EAAS;CAAI;AACjG;AAiBA,SAASK,IAAqC;CAC5C,OAAO,OAAO,OAAO,IAAI;AAC3B;AAGA,IAAaC,IAAmD,kBAAY;AAe5E,SAASC,EACP,GACA,GACA,GACA,GACQ;CACR,IAAIC,IAAO,IACPC,IAAe;CACnB,KAAK,IAAIC,IAAO,GAAGA,IAAOC,EAAM,QAAQ,KAAQ;EAC9C,IAAMlB,IAAImB,MAAc,QAAQD,EAAM,SAAS,IAAID,IAAOA,GACpD,EAAE,aAAU,cAAWC,EAAMlB;EACnC,IAAIoB,EAAOpB,MAAMqB,KAAUrB,MAAMsB,GAAgB;EACjD,IAAMC,IAAQC,KAAY;EAC1B,CAAIT,IAAO,KAAKQ,IAAQP,OACtB,IAAOhB,GACP,IAAeuB;CAEnB;CACA,OAAOR;AACT;AAuBA,IAAaU,IAAb,MAA2B;CACzB,YAAwC;CACxC,SAAqC;CACrC,aAAqB;CAErB,iBAAyB;CACzB,wBAAyB,IAAI,IAA2B;CAExD,2BAA4B,IAAI,IAAsC;CAEtE,+BAAgC,IAAI,IAAoB;CAExD,wBAAgB,IAAI,QAA6B;CACjD,4BAA6B,IAAI,IAAgB;CACjD,SAA8B;EAC5B,WAAW;EACX,aAAa;EACb,gBAAgB;EAChB,gBAAgB;CAClB;CACA,SAA2BjC;CAE3B,UAA4BA;CAE5B,eAAuB;CAEvB,SAAwCqB;CAExC,WAAmB;CAEnB,QAA+B,CAAC;CAChC,YAAoB;CACpB,WAA0C;CAC1C,kBAAmD;CACnD,uBAAoD;CAEpD,aAAa,OACX,KAAK,UAAU,IAAIa,CAAQ,SACd;EACX,KAAK,UAAU,OAAOA,CAAQ;CAChC;CAGF,oBAA8B,KAAK;CAEnC,0BAAoClC;CAEpC,wBAAiC,KAAK;CAEtC,kBAAyC,KAAK;CAE9C,wBAA+CqB;CAE/C,oBAA6B,KAAK;CAElC,sBAA+B;CAM/B,UAAU,GAA6B;EACrC,OAAO,KAAK,OAAO,WAAW,KAAK,CAACc,KAAa,KAAK;CACxD;CAGA,gBAA0B;EACxB,IAAMP,IAAS,IAAI,IAAI,KAAK,MAAM;EAClC,OAAO,KAAK,QAAQ,QAAQ,MAAO,CAACA,EAAO,IAAIrB,CAAE,CAAC;CACpD;CAMA,kBAA+D;EAC7D,IAAMW,IAAY,KAAK;EAEvB,OADKA,IACE,MAAM,KAAK,KAAK,KAAK,CAAC,CAC1B,QAAQ,CAACkB,OAAQA,EAAG,eAAelB,EAAU,SAASkB,CAAE,CAAC,CAAC,CAC1D,MAAM,CAACjC,IAAI,CAACC,OAAOF,EAAcC,GAAGC,CAAC,CAAC,CAAC,CACvC,KAAK,CAACiC,GAAS,EAAE,cAAW;GAAE;GAAS;EAAG,EAAE,IAJxB,CAAC;CAK1B;CAGA,UAAU,GAA2B;EACnC,IAAMC,IAAW,KAAK;EACtB,CACEA,EAAS,cAAcC,EAAO,aAC9BD,EAAS,gBAAgBC,EAAO,eAChCD,EAAS,mBAAmBC,EAAO,kBACnCD,EAAS,mBAAmBC,EAAO,oBAKjCD,EAAS,gBAAgBC,EAAO,gBAClC,KAAK,wBAAQ,IAAI,QAAQ,GACzB,KAAK,aAAa,IAEpB,KAAK,SAASA,GACd,KAAK,QAAQ;CACf;CAEA,gBAA8B;EAE5B,IADA,KAAK,YAAY,IACbtC,EAAkB,GAAG;GACvB,KAAK,WAAW,IAAI,qBAAqB,KAAK,QAAQ,CAAC;GACvD,KAAK,IAAMmC,KAAM,KAAK,iBAAiB,GAAG,KAAK,SAAS,QAAQA,CAAE;EACpE,OAAO,IAAI,OAAO,SAAW,KAAa;GACxC,IAAMI,UAAiB,KAAK,QAAQ;GAEpC,AADA,OAAO,iBAAiB,UAAUA,CAAQ,GAC1C,KAAK,6BAA6B,OAAO,oBAAoB,UAAUA,CAAQ;EACjF;EAMA,OALI,OAAO,mBAAqB,QAC9B,KAAK,kBAAkB,IAAI,uBAAuB,KAAK,WAAW,CAAC,GAC/D,KAAK,aAAW,KAAK,gBAAgB,QAAQ,KAAK,WAAWnC,CAAwB,IAE3F,KAAK,QAAQ,SACA;GAOX,AANA,KAAK,YAAY,IACjB,KAAK,UAAU,WAAW,GAC1B,KAAK,WAAW,MAChB,KAAK,iBAAiB,WAAW,GACjC,KAAK,kBAAkB,MACvB,KAAK,uBAAuB,GAC5B,KAAK,uBAAuB;EAC9B;CACF;CAGA,gBAAgB,MAAsC;EACpD,AAAIoC,MAAS,KAAK,cACd,KAAK,aAAW,KAAK,UAAU,UAAU,KAAK,SAAS,GAC3D,KAAK,YAAYA,GACbA,KAAM,KAAK,UAAU,QAAQA,CAAI,GACjC,KAAK,oBACP,KAAK,gBAAgB,WAAW,GAC5BA,KAAM,KAAK,gBAAgB,QAAQA,GAAMpC,CAAwB,IAEvE,KAAK,QAAQ;CACf;CAMA,mBAAyB;EACvB,IAAMqC,IAAQ,KAAK;EACnB,KAAK,IAAIlC,IAAI,GAAGA,IAAIkC,EAAM,QAAQ,KAChC,IAAIxC,EAAcwC,EAAMlC,IAAI,IAAIkC,EAAMlC,EAAE,IAAI,GAAG;GAC7C,KAAK,QAAQ;GACb;EACF;CAEJ;CAGA,aAAa,MAAsC;EACjD,AAAIiC,MAAS,KAAK,WACd,KAAK,UAAQ,KAAK,UAAU,UAAU,KAAK,MAAM,GACrD,KAAK,SAASA,GACVA,KAAM,KAAK,UAAU,QAAQA,CAAI,GACrC,KAAK,QAAQ;CACf;CAGA,aAAa,GAAiB,GAAwB;EAIpD,OAHA,KAAK,MAAM,IAAIL,GAAI;GAAE;GAAI,UAAU,KAAA;GAAW,QAAQ;GAAO,SAAS,KAAA;EAAU,CAAC,GACjF,KAAK,UAAU,QAAQA,CAAE,GACzB,KAAK,QAAQ,SACA;GACX,AAAI,KAAK,MAAM,IAAIA,CAAE,CAAC,EAAE,OAAO7B,MAC/B,KAAK,MAAM,OAAO6B,CAAE,GACpB,KAAK,UAAU,UAAUA,CAAE,GAC3B,KAAK,QAAQ;EACf;CACF;CAGA,YACE,GACA,GACA,GACA,GACM;EACN,IAAMO,IAAO,KAAK,MAAM,IAAIP,CAAE;EAC9B,AACE,CAACO,KACAA,EAAK,aAAaX,KAAYW,EAAK,WAAWd,KAAUc,EAAK,YAAYC,MAI5E,EAAK,WAAWZ,GAChB,EAAK,SAASH,GACd,EAAK,UAAUe,GACf,KAAK,QAAQ;CACf;CAGA,gBAAgB,GAAiB,GAA6B;EAI5D,OAHA,KAAK,SAAS,IAAIR,GAAI,EAAE,WAAQ,CAAC,GACjC,KAAK,UAAU,QAAQA,CAAE,GACzB,KAAK,QAAQ,SACA;GACX,AAAK,KAAK,SAAS,OAAOA,CAAE,MAC5B,KAAK,UAAU,UAAUA,CAAE,GAC3B,KAAK,QAAQ;EACf;CACF;CAMA,kBAAkB,MAAiC;EACjD,IAAI,CAACS,GAAO,OAAOlC;EACnB,IAAMmC,IAAS,KAAK,cACdC,KAASD,EAAO,IAAIpC,CAAM,KAAK,KAAK;EAG1C,OAFAoC,EAAO,IAAIpC,GAAQqC,CAAK,GACpBA,IAAQ,KAAGtC,EAAoBC,CAAM,SAC5B;GACX,IAAMsC,KAAaF,EAAO,IAAIpC,CAAM,KAAK,KAAK;GAC9C,AAAIsC,IAAY,IAAGF,EAAO,IAAIpC,GAAQsC,CAAS,IAC1CF,EAAO,OAAOpC,CAAM;EAC3B;CACF;CAEA,mBAA0C;EACxC,IAAMuC,IAAW,CAAC,GAAG,KAAK,MAAM,KAAK,GAAG,GAAG,KAAK,SAAS,KAAK,CAAC;EAG/D,OAFI,KAAK,aAAWA,EAAS,KAAK,KAAK,SAAS,GAC5C,KAAK,UAAQA,EAAS,KAAK,KAAK,MAAM,GACnCA;CACT;CAEA,UAAwB;EACtB,IAAM/B,IAAY,KAAK;EACvB,IAAI,CAAC,KAAK,aAAa,CAACA,GAAW;EACnC,IAAM,EAAE,cAAW,gBAAa,sBAAmB,KAAK,QAClDL,IAAWC,MAAgB,YAC3BoC,KAAU,MAAqBrC,IAAWuB,EAAG,eAAeA,EAAG,aAC/De,KAAS,CAACf,OAAgCA,EAAG,eAAelB,EAAU,SAASkB,CAAE,GAGjFgB,IAAU,MAAM,KAAK,KAAK,KAAK,CAAC,CACnC,OAAOD,CAAK,CAAC,CACb,MAAM,CAAChD,IAAI,CAACC,OAAOF,EAAcC,GAAGC,CAAC,CAAC,GACnCiD,IAAiB,MAAM,KAAK,KAAK,QAAQ,CAAC,CAAC,OAAOF,CAAK;EAC7D,KAAK,QAAQC,EAAQ,KAAK,CAAChB,OAAQA,CAAE;EACrC,KAAK,IAAM,CAACA,MAAO,CAAC,GAAGgB,GAAS,GAAGC,CAAc,GAC/C,AAAKjB,EAAG,aAAa,sBAAsB,KAAG,KAAK,MAAM,IAAIA,GAAIc,EAAOd,CAAE,CAAC;EAG7E,AADA,KAAK,iBAAiB,IAClB,KAAK,QAAQ,gBACf,KAAK,aAAac,EAAO,KAAK,MAAM,GACpC,KAAK,iBAAiB;EAExB,IAAM,EAAE,cAAW,WAAQtC,EAAcM,GAAWJ,CAAW,GAEzDY,IAAQ0B,EAAQ,KAAK,GAAGT,OAAUA,CAAI,GACtCW,IAAQF,EAAQ,KAAK,CAAChB,OAAQ,KAAK,MAAM,IAAIA,CAAE,KAAK,CAAC,GACrDmB,IAAWF,EAAe,KAAK,CAACjB,GAAI,EAAE,mBAAgB;GAC1D;GACA,MAAM,KAAK,MAAM,IAAIA,CAAE,KAAK;EAC9B,EAAE,GACIoB,IAAc9B,EAAM,UAAU,EAAK,GACrC+B,IAAe/B,EAAM,QAGnBgC,oBAAU,IAAI,IAAoB;EACxC,KAAK,IAAM,EAAE,gBAAahC,GACxB,AAAIkB,MAAY,KAAA,KAAWc,EAAQ,IAAId,IAAUc,EAAQ,IAAId,CAAO,KAAK,KAAK,CAAC;EAEjF,IAAMe,UAA0C;GAC9C,IAAMC,oBAAQ,IAAI,IAAoB;GAKtC,OAJAlC,EAAM,SAAS,EAAE,cAAW,MAAM;IAChC,AAAIkB,MAAY,KAAA,KAAa,CAACY,EAAYhD,MACxCoD,EAAM,IAAIhB,IAAUgB,EAAM,IAAIhB,CAAO,KAAK,KAAK,CAAC;GACpD,CAAC,GACMgB;EACT,GACMC,UAAyB;GAC7B,IAAMD,IAAQD,EAAa,GACvBG,IAAQ,GACRf,IAAQ;GACZ,EAAM,SAAS,GAAG,MAAM;IACtB,AAAIS,EAAYhD,OAChB,KAAS8C,EAAM9C,IACf;GACF,CAAC;GACD,KAAK,IAAM,EAAE,YAAS,aAAU+C,GAC9B,CAAI,GAAQ,IAAIX,CAAO,KAAMgB,EAAM,IAAIhB,CAAO,OAC9C,KAASmB,GACT;GAEF,OAAOD,IAAQ9C,IAAM,KAAK,IAAI,GAAG+B,IAAQ,CAAC;EAC5C,GACIiB,IAAOH,EAAS;EAEpB,IAAIG,IAAOC,GAAW;GAGpB,IAAMC,IAAU,KAAK,aAAa,IAAI,KAAK,aAAalD,IAAM,GAExDc,IADUJ,EAAM,MAAM,MAASiB,EAAK,UAAUA,EAAK,aAAa,KAAA,CAAS,IACA,KAA9ChB,MAAc,QAAQ,IAAID,EAAM,SAAS;GAC1E,OAAOsC,IAAOE,IAAUD,KAAaR,IAAeU,IAAgB;IAClE,IAAMC,IAAS9C,EAAWI,GAAO8B,GAAa7B,GAAWG,CAAc;IACvE,IAAIsC,IAAS,GAAG;IAGhB,AAFA,EAAYA,KAAU,IACtB,KACA,IAAOP,EAAS;GAClB;EACF;EAEA,IAAMQ,IAAO3C,EAAM,QAAQ,GAAG,MAAM8B,EAAYhD,EAAE,CAAC,CAAC,KAAK,MAASmC,EAAK,EAAE,GAGnE2B,IAASD,EAAK,SAAS,KAAKL,IAAO,KAAK,aAAaC,GACrDM,IAAS,KAAK,WAAWb,GAASC,EAAa,CAAC,GAEhDa,IAAgB,CAAClE,EAAQ+D,GAAM,KAAK,MAAM,GAC1CI,IAAU/C,EAAM,KAAK,MAASiB,EAAK,EAAE,GACrC+B,IAAa,CAACpE,EAAQmE,GAAS,KAAK,OAAO,GAC3CE,IAAgBJ,MAAW,KAAK;EACtC,IACE,CAACC,KACD,CAACE,KACD,CAACC,KACDL,MAAW,KAAK,gBAChB,KAAK,UAEL;EAKF,AAFIE,MAAe,KAAK,SAASH,EAAK,SAAS,IAAIA,IAAOrE,IACtD0E,MAAY,KAAK,UAAUD,IAC/B,KAAK,SAASF;EACd,IAAMK,IACJJ,KACAG,KACAL,MAAW,KAAK,gBACf,CAAC,KAAK,YAAY,KAAK,OAAO;EAGjC,IAFA,KAAK,eAAeA,GACpB,KAAK,WAAW,IACZM,GAAS,KAAK,IAAM1C,KAAY,MAAM,KAAK,KAAK,SAAS,GAAG,EAAS;CAC3E;CAGA,WACE,GACA,GACuB;EACvB,IAAMmC,IAAOjD,EAAY;EACzB,KAAK,IAAM,CAACwB,GAASkB,MAAUJ,GAAS;GACtC,IAAMX,IAAQa,EAAM,IAAIhB,CAAO,KAAK;GACpC,EAAKA,KAAWG,MAAU,IAAI,WAAWA,MAAUe,IAAQ,YAAY;EACzE;EACA,IAAMe,IAAO,OAAO,KAAKR,CAAI,GACvBS,IAAU,KAAK;EAIrB,OAFED,EAAK,WAAW,OAAO,KAAKC,CAAO,CAAC,CAAC,UACrCD,EAAK,OAAO,MAAQR,EAAKU,OAASD,EAAQC,EAAI,IAClCD,IAAUD,EAAK,SAAS,IAAIR,IAAOhD;CACnD;AACF"}
|