{"version":3,"file":"useLayoutAncestry.mjs","sources":["../../../../../src/lib/layouts/context-aware/hooks/useLayoutAncestry.ts"],"sourcesContent":["/**\n * @fileoverview useLayoutAncestry Hook\n *\n * Provides access to the layout ancestry chain from DOM context.\n *\n * @module layouts/context-aware/hooks/useLayoutAncestry\n * @author Agent 4 - PhD Context Systems Expert\n * @version 1.0.0\n */\n\nimport { useCallback, useMemo } from 'react';\n\nimport type {\n  LayoutAncestor,\n  LayoutType,\n  LayoutConstraints,\n  UseLayoutAncestryReturn,\n} from '../types';\nimport { useDOMContextValue } from '../DOMContextProvider';\nimport {\n  findAncestorByType,\n  findScrollContainerAncestor,\n  findContainingBlockAncestor,\n  computeInheritedConstraints,\n  isWithinLayoutType,\n  getLayoutDepth,\n} from '../dom-context';\n\n// ============================================================================\n// useLayoutAncestry Hook\n// ============================================================================\n\n/**\n * Hook to access layout ancestry information.\n *\n * @remarks\n * This hook provides information about the parent layout chain,\n * making it easy to build layout-aware components.\n *\n * @returns Layout ancestry information and utility functions\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const {\n *     ancestors,\n *     findAncestor,\n *     isInLayout,\n *     constraints,\n *     depth,\n *   } = useLayoutAncestry();\n *\n *   const flexParent = findAncestor('flex');\n *   const isInGrid = isInLayout('grid');\n *\n *   return (\n *     <div>\n *       {flexParent && <span>In flex container</span>}\n *       {isInGrid && <span>In grid container</span>}\n *       {constraints && (\n *         <span>\n *           Max width: {constraints.width.max}px\n *         </span>\n *       )}\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useLayoutAncestry(): UseLayoutAncestryReturn {\n  const context = useDOMContextValue();\n  const { ancestors } = context;\n\n  /**\n   * Finds the closest ancestor of a specific layout type.\n   */\n  const findAncestor = useCallback(\n    (type: LayoutType): LayoutAncestor | undefined => {\n      return findAncestorByType(ancestors as LayoutAncestor[], type);\n    },\n    [ancestors]\n  );\n\n  /**\n   * Checks if the element is within a specific layout type.\n   */\n  const isInLayout = useCallback(\n    (type: LayoutType): boolean => {\n      return isWithinLayoutType(ancestors as LayoutAncestor[], type);\n    },\n    [ancestors]\n  );\n\n  /**\n   * Gets the inherited constraints from ancestors.\n   */\n  const constraints = useMemo((): LayoutConstraints | null => {\n    return computeInheritedConstraints(ancestors as LayoutAncestor[]);\n  }, [ancestors]);\n\n  /**\n   * Gets the layout depth.\n   */\n  const depth = useMemo((): number => {\n    return getLayoutDepth(ancestors as LayoutAncestor[]);\n  }, [ancestors]);\n\n  return {\n    ancestors,\n    findAncestor,\n    isInLayout,\n    constraints,\n    depth,\n  };\n}\n\n// ============================================================================\n// Specialized Ancestry Hooks\n// ============================================================================\n\n/**\n * Hook to get the nearest flex container ancestor.\n *\n * @returns Flex ancestor or undefined\n *\n * @example\n * ```tsx\n * function FlexChild() {\n *   const flexParent = useFlexAncestor();\n *\n *   if (flexParent) {\n *     console.log('Flex direction:', flexParent.flexProperties?.direction);\n *   }\n *\n *   return <div>...</div>;\n * }\n * ```\n */\nexport function useFlexAncestor(): LayoutAncestor | undefined {\n  const { findAncestor } = useLayoutAncestry();\n  return useMemo(() => findAncestor('flex') ?? findAncestor('inline-flex'), [findAncestor]);\n}\n\n/**\n * Hook to get the nearest grid container ancestor.\n *\n * @returns Grid ancestor or undefined\n *\n * @example\n * ```tsx\n * function GridChild() {\n *   const gridParent = useGridAncestor();\n *\n *   if (gridParent) {\n *     console.log('Grid columns:', gridParent.gridProperties?.templateColumns);\n *   }\n *\n *   return <div>...</div>;\n * }\n * ```\n */\nexport function useGridAncestor(): LayoutAncestor | undefined {\n  const { findAncestor } = useLayoutAncestry();\n  return useMemo(() => findAncestor('grid') ?? findAncestor('inline-grid'), [findAncestor]);\n}\n\n/**\n * Hook to get the nearest scroll container ancestor.\n *\n * @returns Scroll container ancestor or undefined\n *\n * @example\n * ```tsx\n * function ScrollChild() {\n *   const scrollContainer = useScrollContainerAncestor();\n *\n *   if (scrollContainer) {\n *     console.log('Scroll container bounds:', scrollContainer.bounds);\n *   }\n *\n *   return <div>...</div>;\n * }\n * ```\n */\nexport function useScrollContainerAncestor(): LayoutAncestor | undefined {\n  const context = useDOMContextValue();\n  return useMemo(\n    () => findScrollContainerAncestor(context.ancestors as LayoutAncestor[]),\n    [context.ancestors]\n  );\n}\n\n/**\n * Hook to get the nearest containing block ancestor.\n *\n * @returns Containing block ancestor or undefined\n *\n * @example\n * ```tsx\n * function AbsoluteChild() {\n *   const containingBlock = useContainingBlockAncestor();\n *\n *   if (containingBlock) {\n *     console.log('Containing block:', containingBlock.bounds);\n *   }\n *\n *   return <div style={{ position: 'absolute' }}>...</div>;\n * }\n * ```\n */\nexport function useContainingBlockAncestor(): LayoutAncestor | undefined {\n  const context = useDOMContextValue();\n  return useMemo(\n    () => findContainingBlockAncestor(context.ancestors as LayoutAncestor[]),\n    [context.ancestors]\n  );\n}\n\n// ============================================================================\n// Layout Type Detection Hooks\n// ============================================================================\n\n/**\n * Hook to check if element is in a flex context.\n *\n * @returns Whether in flex context\n *\n * @example\n * ```tsx\n * function MyComponent() {\n *   const isInFlex = useIsInFlex();\n *\n *   return (\n *     <div style={isInFlex ? { flexGrow: 1 } : { width: '100%' }}>\n *       Content\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useIsInFlex(): boolean {\n  const { isInLayout } = useLayoutAncestry();\n  return useMemo(() => isInLayout('flex') || isInLayout('inline-flex'), [isInLayout]);\n}\n\n/**\n * Hook to check if element is in a grid context.\n *\n * @returns Whether in grid context\n */\nexport function useIsInGrid(): boolean {\n  const { isInLayout } = useLayoutAncestry();\n  return useMemo(() => isInLayout('grid') || isInLayout('inline-grid'), [isInLayout]);\n}\n\n/**\n * Hook to check if element is in an inline context.\n *\n * @returns Whether in inline context\n */\nexport function useIsInInline(): boolean {\n  const { isInLayout } = useLayoutAncestry();\n  return useMemo(\n    () =>\n      isInLayout('inline') ||\n      isInLayout('inline-block') ||\n      isInLayout('inline-flex') ||\n      isInLayout('inline-grid'),\n    [isInLayout]\n  );\n}\n\n// ============================================================================\n// Constraint Hooks\n// ============================================================================\n\n/**\n * Hook to get available width from constraints.\n *\n * @returns Available width in pixels or null\n *\n * @example\n * ```tsx\n * function ResponsiveComponent() {\n *   const availableWidth = useAvailableWidth();\n *\n *   if (availableWidth !== null && availableWidth < 300) {\n *     return <CompactView />;\n *   }\n *\n *   return <NormalView />;\n * }\n * ```\n */\nexport function useAvailableWidth(): number | null {\n  const { constraints, ancestors } = useLayoutAncestry();\n\n  return useMemo(() => {\n    if (constraints) {\n      return constraints.width.current;\n    }\n    if (ancestors.length > 0) {\n      return ancestors[0]?.bounds.contentBox.width ?? 0;\n    }\n    return null;\n  }, [constraints, ancestors]);\n}\n\n/**\n * Hook to get available height from constraints.\n *\n * @returns Available height in pixels or null\n */\nexport function useAvailableHeight(): number | null {\n  const { constraints, ancestors } = useLayoutAncestry();\n\n  return useMemo(() => {\n    if (constraints) {\n      return constraints.height.current;\n    }\n    if (ancestors.length > 0) {\n      return ancestors[0]?.bounds.contentBox.height ?? 0;\n    }\n    return null;\n  }, [constraints, ancestors]);\n}\n\n/**\n * Hook to get the parent aspect ratio constraint.\n *\n * @returns Aspect ratio or null\n */\nexport function useParentAspectRatio(): number | null {\n  const { constraints, ancestors } = useLayoutAncestry();\n\n  return useMemo(() => {\n    if (constraints?.aspectRatio != null) {\n      return constraints.aspectRatio;\n    }\n    if (ancestors.length > 0) {\n      const { width, height } = ancestors[0]?.bounds.contentBox ?? { width: 0, height: 0 };\n      if (height > 0) {\n        return width / height;\n      }\n    }\n    return null;\n  }, [constraints, ancestors]);\n}\n"],"names":["useLayoutAncestry","context","useDOMContextValue","ancestors","findAncestor","useCallback","type","findAncestorByType","isInLayout","isWithinLayoutType","constraints","useMemo","computeInheritedConstraints","depth","getLayoutDepth","useFlexAncestor","useGridAncestor","useScrollContainerAncestor","findScrollContainerAncestor","useContainingBlockAncestor","findContainingBlockAncestor","useIsInFlex","useIsInGrid","useIsInInline","useAvailableWidth","useAvailableHeight","useParentAspectRatio","width","height"],"mappings":";;;AAqEO,SAASA,IAA6C;AAC3D,QAAMC,IAAUC,EAAA,GACV,EAAE,WAAAC,MAAcF,GAKhBG,IAAeC;AAAA,IACnB,CAACC,MACQC,EAAmBJ,GAA+BG,CAAI;AAAA,IAE/D,CAACH,CAAS;AAAA,EAAA,GAMNK,IAAaH;AAAA,IACjB,CAACC,MACQG,EAAmBN,GAA+BG,CAAI;AAAA,IAE/D,CAACH,CAAS;AAAA,EAAA,GAMNO,IAAcC,EAAQ,MACnBC,EAA4BT,CAA6B,GAC/D,CAACA,CAAS,CAAC,GAKRU,IAAQF,EAAQ,MACbG,EAAeX,CAA6B,GAClD,CAACA,CAAS,CAAC;AAEd,SAAO;AAAA,IACL,WAAAA;AAAA,IACA,cAAAC;AAAA,IACA,YAAAI;AAAA,IACA,aAAAE;AAAA,IACA,OAAAG;AAAA,EAAA;AAEJ;AAwBO,SAASE,IAA8C;AAC5D,QAAM,EAAE,cAAAX,EAAA,IAAiBJ,EAAA;AACzB,SAAOW,EAAQ,MAAMP,EAAa,MAAM,KAAKA,EAAa,aAAa,GAAG,CAACA,CAAY,CAAC;AAC1F;AAoBO,SAASY,IAA8C;AAC5D,QAAM,EAAE,cAAAZ,EAAA,IAAiBJ,EAAA;AACzB,SAAOW,EAAQ,MAAMP,EAAa,MAAM,KAAKA,EAAa,aAAa,GAAG,CAACA,CAAY,CAAC;AAC1F;AAoBO,SAASa,IAAyD;AACvE,QAAMhB,IAAUC,EAAA;AAChB,SAAOS;AAAA,IACL,MAAMO,EAA4BjB,EAAQ,SAA6B;AAAA,IACvE,CAACA,EAAQ,SAAS;AAAA,EAAA;AAEtB;AAoBO,SAASkB,IAAyD;AACvE,QAAMlB,IAAUC,EAAA;AAChB,SAAOS;AAAA,IACL,MAAMS,EAA4BnB,EAAQ,SAA6B;AAAA,IACvE,CAACA,EAAQ,SAAS;AAAA,EAAA;AAEtB;AAwBO,SAASoB,IAAuB;AACrC,QAAM,EAAE,YAAAb,EAAA,IAAeR,EAAA;AACvB,SAAOW,EAAQ,MAAMH,EAAW,MAAM,KAAKA,EAAW,aAAa,GAAG,CAACA,CAAU,CAAC;AACpF;AAOO,SAASc,IAAuB;AACrC,QAAM,EAAE,YAAAd,EAAA,IAAeR,EAAA;AACvB,SAAOW,EAAQ,MAAMH,EAAW,MAAM,KAAKA,EAAW,aAAa,GAAG,CAACA,CAAU,CAAC;AACpF;AAOO,SAASe,IAAyB;AACvC,QAAM,EAAE,YAAAf,EAAA,IAAeR,EAAA;AACvB,SAAOW;AAAA,IACL,MACEH,EAAW,QAAQ,KACnBA,EAAW,cAAc,KACzBA,EAAW,aAAa,KACxBA,EAAW,aAAa;AAAA,IAC1B,CAACA,CAAU;AAAA,EAAA;AAEf;AAwBO,SAASgB,IAAmC;AACjD,QAAM,EAAE,aAAAd,GAAa,WAAAP,EAAA,IAAcH,EAAA;AAEnC,SAAOW,EAAQ,MACTD,IACKA,EAAY,MAAM,UAEvBP,EAAU,SAAS,IACdA,EAAU,CAAC,GAAG,OAAO,WAAW,SAAS,IAE3C,MACN,CAACO,GAAaP,CAAS,CAAC;AAC7B;AAOO,SAASsB,IAAoC;AAClD,QAAM,EAAE,aAAAf,GAAa,WAAAP,EAAA,IAAcH,EAAA;AAEnC,SAAOW,EAAQ,MACTD,IACKA,EAAY,OAAO,UAExBP,EAAU,SAAS,IACdA,EAAU,CAAC,GAAG,OAAO,WAAW,UAAU,IAE5C,MACN,CAACO,GAAaP,CAAS,CAAC;AAC7B;AAOO,SAASuB,IAAsC;AACpD,QAAM,EAAE,aAAAhB,GAAa,WAAAP,EAAA,IAAcH,EAAA;AAEnC,SAAOW,EAAQ,MAAM;AACnB,QAAID,GAAa,eAAe;AAC9B,aAAOA,EAAY;AAErB,QAAIP,EAAU,SAAS,GAAG;AACxB,YAAM,EAAE,OAAAwB,GAAO,QAAAC,MAAWzB,EAAU,CAAC,GAAG,OAAO,cAAc,EAAE,OAAO,GAAG,QAAQ,EAAA;AACjF,UAAIyB,IAAS;AACX,eAAOD,IAAQC;AAAA,IAEnB;AACA,WAAO;AAAA,EACT,GAAG,CAAClB,GAAaP,CAAS,CAAC;AAC7B;"}