{"version":3,"sources":["../src/core/Components/Actions/hooks/useCollapsibility.ts"],"names":["ThCollapsibilityVisibility","actionIcons","menuItems"],"mappings":"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","file":"chunk-AQSJDL63.mjs","sourcesContent":["\"use client\";\n\nimport { RefObject, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\";\n\nimport { ThActionEntry } from \"../ThActionsBar\";\n\nexport type ThCollapsibility = boolean | Record<string, number | \"all\">;\n\nexport enum ThCollapsibilityVisibility {\n  always = \"always\",\n  partially = \"partially\",\n  overflow = \"overflow\"\n}\n\nexport interface CollapsiblePref {\n  displayOrder: string[];\n  collapse: ThCollapsibility;\n  keys: {\n    [key: string]: {\n      [key: string]: any;\n      visibility: ThCollapsibilityVisibility;\n    };\n  }\n}\n\nexport const useCollapsibility = (\n  items: ThActionEntry<string>[],\n  prefs: CollapsiblePref,\n  breakpoint?: string,\n  containerRef?: RefObject<HTMLElement | null>\n) => {\n  const isSpaceFit = prefs.collapse === true;\n\n  // --- Space-fit mode (collapse: true) ---\n  // How many `partially` items currently fit in the bar.\n  // MAX_SAFE_INTEGER = \"assume all fit\" — corrected by useLayoutEffect before first paint.\n  const [partialInBar, setPartialInBar] = useState<number>(Number.MAX_SAFE_INTEGER);\n  const lastCountRef = useRef<number>(Number.MAX_SAFE_INTEGER);\n\n  // Ghost element tracking — spans wrapping each item in the hidden measurement clone.\n  // The ghost always renders all items, so widths are stable regardless of bar state.\n  const keyToElement = useRef(new Map<string, HTMLElement>());\n  const itemWidthsRef = useRef(new Map<string, number>());\n\n  // Inputs for computeLayout, kept in refs so the function is stable\n  const alwaysKeysRef = useRef<string[]>([]);\n  const orderedPartialKeysRef = useRef<string[]>([]);\n  const hasOverflowRef = useRef<boolean>(false);\n  const columnGapRef = useRef<number>(0);\n\n  // Shared rAF handle — both ResizeObservers dequeue into the same frame slot.\n  const rafIdRef = useRef<number | null>(null);\n\n  // Tracks the last spec so categorization is skipped when nothing meaningful changed.\n  const specRef = useRef<string>(\"\");\n\n  // computeLayout reads only refs — no closure over props, truly stable.\n  // Called from remeasureAndCompute after fresh DOM reads.\n  const computeLayout = useCallback((containerWidth: number) => {\n    if (!containerWidth) return;\n\n    const widths = itemWidthsRef.current;\n    const alwaysKeys = alwaysKeysRef.current;\n    const partialKeys = orderedPartialKeysRef.current;\n    const gap = columnGapRef.current;\n\n    const N_a = alwaysKeys.length;\n    const alwaysTotal = alwaysKeys.reduce((s, k) => s + (widths.get(k) ?? 0), 0);\n    const partialWidths = partialKeys.map(k => widths.get(k) ?? 0);\n    const partialTotal = partialWidths.reduce((s, w) => s + w, 0);\n\n    let newCount: number;\n\n    // Check if everything fits without an overflow menu trigger\n    const noMenuTotal = alwaysTotal + partialTotal + gap * Math.max(0, N_a + partialKeys.length - 1);\n    if (!hasOverflowRef.current && noMenuTotal <= containerWidth) {\n      newCount = partialKeys.length;\n    } else {\n      // Need the overflow menu trigger — use first measured width as proxy\n      // (all icon buttons are the same size)\n      const menuW = widths.values().next().value ?? 0;\n      if (!menuW) return;\n\n      let count = 0, usedPartial = 0;\n      for (const w of partialWidths) {\n        // Items in bar at this step: N_a always + count partial + 1 new partial + 1 menu trigger\n        const totalGap = gap * Math.max(0, N_a + count + 1);\n        if (alwaysTotal + usedPartial + w + menuW + totalGap <= containerWidth) {\n          usedPartial += w;\n          count++;\n        } else {\n          break;\n        }\n      }\n      newCount = count;\n    }\n\n    if (newCount !== lastCountRef.current) {\n      lastCountRef.current = newCount;\n      setPartialInBar(newCount);\n    }\n  }, []);\n\n  // Re-measures all ghost item widths and the container gap, then calls computeLayout.\n  // getBoundingClientRect and getComputedStyle are cheap when called from a rAF callback\n  // or useLayoutEffect (layout is already computed by the browser at those points).\n  // Passing containerWidth avoids a second getBoundingClientRect on the container when\n  // the caller already has it (e.g. from ResizeObserver contentRect).\n  const remeasureAndCompute = useCallback((containerWidth?: number) => {\n    if (!containerRef?.current) return;\n    for (const [key, el] of keyToElement.current) {\n      itemWidthsRef.current.set(key, el.getBoundingClientRect().width);\n    }\n    columnGapRef.current = parseFloat(getComputedStyle(containerRef.current).columnGap) || 0;\n    computeLayout(containerWidth ?? containerRef.current.getBoundingClientRect().width);\n  }, [containerRef, computeLayout]);\n\n  // Kept in a ref so the ghost observer's rAF closure is always current\n  // without the observer needing to re-subscribe when the function identity changes.\n  const remeasureAndComputeRef = useRef(remeasureAndCompute);\n  useLayoutEffect(() => { remeasureAndComputeRef.current = remeasureAndCompute; }, [remeasureAndCompute]);\n\n  // Categorize items by visibility and do initial measurement before first paint.\n  // useLayoutEffect runs synchronously after DOM mutations — so the initial\n  // correction happens before the user sees anything.\n  // The spec guard skips the effect when items/prefs object references are unstable\n  // but nothing meaningful changed, UNLESS widths haven't been populated yet\n  // (ghost elements not yet measured on first mount).\n  useLayoutEffect(() => {\n    if (!isSpaceFit || !containerRef?.current) return;\n\n    const spec = items.map(i => `${i.key}:${prefs.keys[i.key]?.visibility ?? \"\"}`).join(\",\");\n    const widthsMissing = items.some(i => !(itemWidthsRef.current.get(i.key) ?? 0));\n    if (spec === specRef.current && !widthsMissing) return;\n    specRef.current = spec;\n\n    const always: string[] = [], partial: string[] = [];\n    let hasOverflow = false;\n\n    for (const item of items) {\n      const v = prefs.keys[item.key]?.visibility;\n      if (v === ThCollapsibilityVisibility.overflow) hasOverflow = true;\n      else if (v === ThCollapsibilityVisibility.always) always.push(item.key);\n      else partial.push(item.key);\n    }\n\n    alwaysKeysRef.current = always;\n    orderedPartialKeysRef.current = partial;\n    hasOverflowRef.current = hasOverflow;\n\n    remeasureAndCompute(containerRef.current.getBoundingClientRect().width);\n  }, [isSpaceFit, items, prefs, containerRef, remeasureAndCompute]);\n\n  // Container ResizeObserver — fires when the container width changes.\n  // Batched via rAF so we compute at most once per frame, not once per pixel.\n  // Re-measures item widths each time so icon size changes (e.g. zoom) that also\n  // cause a container reflow are picked up automatically.\n  useEffect(() => {\n    if (!isSpaceFit || !containerRef?.current) return;\n\n    const observer = new ResizeObserver(entries => {\n      const w = entries[0]?.contentRect.width;\n      if (w === undefined) return;\n\n      if (rafIdRef.current !== null) cancelAnimationFrame(rafIdRef.current);\n      rafIdRef.current = requestAnimationFrame(() => {\n        rafIdRef.current = null;\n        remeasureAndCompute(w);\n      });\n    });\n\n    observer.observe(containerRef.current);\n    return () => {\n      observer.disconnect();\n      if (rafIdRef.current !== null) cancelAnimationFrame(rafIdRef.current);\n    };\n  }, [isSpaceFit, containerRef, remeasureAndCompute]);\n\n  // Ghost wrapper ResizeObserver — fires when icon sizes change independently of\n  // container width (e.g. app-level zoom on a fixed-width container).\n  // Implemented as a callback ref so the observer is set up directly on mount\n  // without a separate state variable or useEffect dependency on a mutable ref.\n  const ghostObserverRef = useRef<ResizeObserver | null>(null);\n  const getGhostRef = useCallback((el: HTMLDivElement | null) => {\n    ghostObserverRef.current?.disconnect();\n    ghostObserverRef.current = null;\n    if (el && isSpaceFit) {\n      const observer = new ResizeObserver(() => {\n        if (rafIdRef.current !== null) cancelAnimationFrame(rafIdRef.current);\n        rafIdRef.current = requestAnimationFrame(() => {\n          rafIdRef.current = null;\n          remeasureAndComputeRef.current();\n        });\n      });\n      observer.observe(el);\n      ghostObserverRef.current = observer;\n    }\n  }, [isSpaceFit]);\n\n  // Ref callback factory — attaches to ghost spans for width measurement.\n  // Harmless noop in other modes.\n  const getItemRef = useCallback((key: string) => (el: HTMLElement | null) => {\n    if (el) {\n      keyToElement.current.set(key, el);\n    } else {\n      keyToElement.current.delete(key);\n      itemWidthsRef.current.delete(key);\n    }\n  }, []);\n\n  // --- Triage ---\n\n  const [actionIcons, menuItems] = useMemo(() => {\n    const actionIcons: ThActionEntry<string>[] = [];\n    const menuItems: ThActionEntry<string>[] = [];\n\n    if (!prefs.collapse) {\n      items.forEach((item) => actionIcons.push(item));\n      return [actionIcons, menuItems];\n    }\n\n    if (prefs.collapse === true) {\n      // Build the set of partial keys that fit in the bar (first N in displayOrder)\n      const barPartialSet = new Set<string>();\n      let partialCount = 0;\n      for (const item of items) {\n        if (prefs.keys[item.key]?.visibility === ThCollapsibilityVisibility.partially) {\n          if (partialCount < partialInBar) {\n            barPartialSet.add(item.key);\n            partialCount++;\n          }\n        }\n      }\n\n      for (const item of items) {\n        const v = prefs.keys[item.key]?.visibility;\n        if (v === ThCollapsibilityVisibility.overflow || (v === ThCollapsibilityVisibility.partially && !barPartialSet.has(item.key))) {\n          menuItems.push(item);\n        } else {\n          actionIcons.push(item);\n        }\n      }\n\n      return [actionIcons, menuItems];\n    }\n\n    // collapse: Record — breakpoint-based triage (existing logic)\n    let countdown: number = 0;\n\n    if (breakpoint) {\n      const prefForBreakpoint = prefs.collapse[breakpoint];\n      if (prefForBreakpoint) {\n        // `always` items are never collapsed, so count only partially + overflow items\n        const partialCount = items.filter(i => prefs.keys[i.key]?.visibility === ThCollapsibilityVisibility.partially).length;\n        const overflowCount = items.filter(i => prefs.keys[i.key]?.visibility === ThCollapsibilityVisibility.overflow).length;\n        const collapsibleCount = partialCount + overflowCount;\n\n        if (prefForBreakpoint === \"all\") {\n          countdown = overflowCount;\n        } else if (!isNaN(prefForBreakpoint)) {\n          countdown = Math.max(0, collapsibleCount - (prefForBreakpoint - 1));\n        }\n      }\n    }\n\n    // Creating a shallow copy so that actionsOrder doesn't mutate between rerenders\n    [...items].reverse().forEach((item) => {\n      const actionPref = prefs.keys[item.key];\n      if (actionPref.visibility === ThCollapsibilityVisibility.overflow) {\n        menuItems.unshift(item);\n        --countdown;\n      } else if (actionPref.visibility === ThCollapsibilityVisibility.partially) {\n        if (countdown > 0) {\n          menuItems.unshift(item);\n          --countdown;\n        } else {\n          actionIcons.unshift(item);\n        }\n      } else {\n        actionIcons.unshift(item);\n      }\n    });\n\n    return [actionIcons, menuItems];\n  }, [items, prefs, breakpoint, partialInBar]);\n\n  return { ActionIcons: actionIcons, MenuItems: menuItems, getItemRef, getGhostRef };\n}\n"]}