{"version":3,"file":"grid.cjs","names":[],"sources":["../src/layout/grid/grid.ts"],"sourcesContent":["import { define, getHost, html, onCleanup, onMounted, prop, watchEffect } from '@vielzeug/ore';\nimport { createElementSize } from '@vielzeug/sentinel';\n\nimport styles from './grid.css?inline';\n\nconst BREAKPOINTS: ['cols2xl' | 'colsXl' | 'colsLg' | 'colsMd' | 'colsSm', string][] = [\n  ['cols2xl', '--size-screen-2xl'],\n  ['colsXl', '--size-screen-xl'],\n  ['colsLg', '--size-screen-lg'],\n  ['colsMd', '--size-screen-md'],\n  ['colsSm', '--size-screen-sm'],\n];\n\nconst AREAS_BREAKPOINTS: ['areas2xl' | 'areasXl' | 'areasLg' | 'areasMd' | 'areasSm', string][] = [\n  ['areas2xl', '--size-screen-2xl'],\n  ['areasXl', '--size-screen-xl'],\n  ['areasLg', '--size-screen-lg'],\n  ['areasMd', '--size-screen-md'],\n  ['areasSm', '--size-screen-sm'],\n];\n\nconst resolveBp = (host: HTMLElement, varName: string, fallback: number): number => {\n  const raw = getComputedStyle(host).getPropertyValue(varName).trim();\n  const parsed = Number.parseFloat(raw);\n\n  return Number.isFinite(parsed) ? parsed : fallback;\n};\n\nconst BP_FALLBACKS: Record<string, number> = {\n  '--size-screen-2xl': 1536,\n  '--size-screen-lg': 1024,\n  '--size-screen-md': 768,\n  '--size-screen-sm': 640,\n  '--size-screen-xl': 1280,\n};\n\ntype ColCount = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n\n/** Grid component properties */\nexport type OreGridProps = {\n  /** Align items vertically */\n  align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';\n  /** CSS grid-template-areas value */\n  areas?: string;\n  /** grid-template-areas at 2xl breakpoint (≥1536px) */\n  areas2xl?: string;\n  /** grid-template-areas at lg breakpoint (≥1024px) */\n  areasLg?: string;\n  /** grid-template-areas at md breakpoint (≥768px) */\n  areasMd?: string;\n  /** grid-template-areas at sm breakpoint (≥640px) */\n  areasSm?: string;\n  /** grid-template-areas at xl breakpoint (≥1280px) */\n  areasXl?: string;\n  /** Number of columns: '1'-'12' | 'auto' */\n  cols?: ColCount;\n  /** Columns at 2xl breakpoint (≥1536px) */\n  cols2xl?: ColCount;\n  /** Columns at lg breakpoint (≥1024px) */\n  colsLg?: ColCount;\n  /** Columns at md breakpoint (≥768px) */\n  colsMd?: ColCount;\n  /** Columns at sm breakpoint (≥640px) */\n  colsSm?: ColCount;\n  /** Columns at xl breakpoint (≥1280px) */\n  colsXl?: ColCount;\n  /** Grid auto flow direction */\n  flow?: 'row' | 'column' | 'row-dense' | 'column-dense';\n  /** Stretch the grid to fill its container's full width */\n  fullwidth?: boolean;\n  /** Gap between items */\n  gap?: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n  /** Justify items horizontally */\n  justify?: 'start' | 'center' | 'end' | 'stretch';\n  /** Minimum column width for responsive mode (default: 250px) */\n  minColWidth?: string;\n  /** Use auto-fit responsive columns */\n  responsive?: boolean;\n  /** Number of rows: '1'-'12' | 'auto' */\n  rows?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto';\n};\n\n/**\n * ore-grid — Flexible grid layout with responsive column control.\n *\n * Columns are computed in JS and applied as `--_cols` inline, so they respond\n * to the element's own width via ResizeObserver. CSS custom properties\n * `--grid-cols`, `--grid-rows`, `--grid-gap`, `--grid-row-gap`, `--grid-col-gap`\n * are honoured as fallbacks when no attribute is set.\n *\n * @element ore-grid\n *\n * @attr {string} cols - Column count: '1'–'12' | 'auto'\n * @attr {string} cols-sm - Columns when width ≥ 640px\n * @attr {string} cols-md - Columns when width ≥ 768px\n * @attr {string} cols-lg - Columns when width ≥ 1024px\n * @attr {string} cols-xl - Columns when width ≥ 1280px\n * @attr {string} cols-2xl - Columns when width ≥ 1536px\n * @attr {string} rows - Row count: '1'–'12' | 'auto'\n * @attr {string} gap - Gap token: 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n * @attr {string} align - align-items: 'start' | 'center' | 'end' | 'stretch' | 'baseline'\n * @attr {string} justify - justify-items: 'start' | 'center' | 'end' | 'stretch'\n * @attr {string} flow - grid-auto-flow: 'row' | 'column' | 'row-dense' | 'column-dense'\n * @attr {boolean} responsive - Enables auto-fit columns without a fixed count\n * @attr {string} min-col-width - Min column width for responsive mode (default: 250px)\n * @attr {boolean} fullwidth - Stretch the grid to fill its container's full width\n * @attr {string} areas - CSS grid-template-areas value (e.g. \"'header header' 'nav main'\")\n * @attr {string} areas-sm - grid-template-areas when width ≥ 640px\n * @attr {string} areas-md - grid-template-areas when width ≥ 768px\n * @attr {string} areas-lg - grid-template-areas when width ≥ 1024px\n * @attr {string} areas-xl - grid-template-areas when width ≥ 1280px\n * @attr {string} areas-2xl - grid-template-areas when width ≥ 1536px\n *\n * @slot - Grid items\n *\n * @cssprop --grid-cols - Fallback column template (used when no cols attr is set)\n * @cssprop --grid-rows - Fallback row template\n * @cssprop --grid-gap - Fallback gap\n * @cssprop --grid-row-gap - Fallback row gap\n * @cssprop --grid-col-gap - Fallback column gap\n *\n * @example\n * <ore-grid cols=\"1\" cols-sm=\"2\" cols-lg=\"4\" gap=\"md\">\n *   <div>Item</div>\n * </ore-grid>\n *\n * @example\n * <!-- Responsive auto-fit -->\n * <ore-grid responsive min-col-width=\"200px\" gap=\"sm\">\n *   <div>Card</div>\n * </ore-grid>\n *\n * @example\n * <!-- Named grid areas -->\n * <ore-grid cols=\"2\" rows=\"2\" areas=\"'header header' 'nav main'\">\n *   <header style=\"grid-area: header\">Header</header>\n *   <nav style=\"grid-area: nav\">Nav</nav>\n *   <main style=\"grid-area: main\">Main</main>\n * </ore-grid>\n */\nexport const GRID_TAG = 'ore-grid' as const;\ndefine<OreGridProps>(GRID_TAG, {\n  props: {\n    align: prop.string<'start' | 'center' | 'end' | 'stretch' | 'baseline'>(),\n    areas: prop.string(),\n    areas2xl: prop.string(),\n    areasLg: prop.string(),\n    areasMd: prop.string(),\n    areasSm: prop.string(),\n    areasXl: prop.string(),\n    cols: prop.string<ColCount>(),\n    cols2xl: prop.string<ColCount>(),\n    colsLg: prop.string<ColCount>(),\n    colsMd: prop.string<ColCount>(),\n    colsSm: prop.string<ColCount>(),\n    colsXl: prop.string<ColCount>(),\n    flow: prop.string<'row' | 'column' | 'row-dense' | 'column-dense'>(),\n    fullwidth: prop.bool(false),\n    gap: prop.string<'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'>(),\n    justify: prop.string<'start' | 'center' | 'end' | 'stretch'>(),\n    minColWidth: prop.string(),\n    responsive: prop.bool(false),\n    rows: prop.string<'1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10' | '11' | '12' | 'auto'>(),\n  },\n\n  setup(props) {\n    const el = getHost();\n    const watch = watchEffect;\n\n    const computeCols = (activeCols: string | undefined, responsive: boolean, minW: string): string | null => {\n      if (activeCols === 'auto' || (!activeCols && responsive)) {\n        return `repeat(auto-fit, minmax(${minW || '250px'}, 1fr))`;\n      }\n\n      return activeCols ? `repeat(${activeCols}, 1fr)` : null;\n    };\n    const updateCols = () => {\n      const w = el.offsetWidth;\n      const responsive = Boolean(props.responsive.value);\n      const minW = props.minColWidth.value ?? '';\n      let activeCols: string | undefined;\n\n      for (const [key, cssVar] of BREAKPOINTS) {\n        if (w >= resolveBp(el, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n          activeCols = props[key].value!;\n          break;\n        }\n      }\n      activeCols ||= props.cols.value || undefined;\n\n      const colsValue = computeCols(activeCols, responsive, minW);\n\n      if (colsValue) {\n        el.style.setProperty('--_cols', colsValue);\n      } else {\n        el.style.removeProperty('--_cols');\n      }\n    };\n\n    // Re-run cols whenever any responsive prop changes\n    watch(() => {\n      void [\n        props.cols.value,\n        props.colsSm.value,\n        props.colsMd.value,\n        props.colsLg.value,\n        props.colsXl.value,\n        props.cols2xl.value,\n        props.responsive.value,\n        props.minColWidth.value,\n      ];\n      updateCols();\n    });\n\n    const updateAreas = () => {\n      const w = el.offsetWidth;\n      let active = '';\n\n      for (const [key, cssVar] of AREAS_BREAKPOINTS) {\n        if (w >= resolveBp(el, cssVar, BP_FALLBACKS[cssVar]) && props[key].value) {\n          active = props[key].value!;\n          break;\n        }\n      }\n      active ||= props.areas.value || '';\n\n      if (active) {\n        el.style.setProperty('grid-template-areas', active);\n      } else {\n        el.style.removeProperty('grid-template-areas');\n      }\n    };\n\n    // Rows\n    watch(() => {\n      const rows = props.rows.value;\n\n      if (rows && rows !== 'auto') {\n        el.style.setProperty('--_rows', `repeat(${rows}, 1fr)`);\n      } else {\n        el.style.removeProperty('--_rows');\n      }\n    });\n    // Grid template areas (responsive)\n    watch(() => {\n      void [\n        props.areas.value,\n        props.areasSm.value,\n        props.areasMd.value,\n        props.areasLg.value,\n        props.areasXl.value,\n        props.areas2xl.value,\n      ];\n      updateAreas();\n    });\n\n    // Also, update on element resize (drives breakpoint switching)\n    onMounted(() => {\n      const size = createElementSize(el);\n\n      onCleanup(() => size.dispose());\n\n      watch(() => {\n        const dims = size.value;\n        if (dims) {\n          updateCols();\n          updateAreas();\n        }\n      });\n    });\n\n    return html`\n      <slot></slot>\n    `;\n  },\n\n  styles: [styles],\n});\n"],"mappings":"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"}