/** * Horizontal rhythm owned by `DataTable` / `HubTable` toolbar + grid shells. * Do not stack parent `px-*` / `mx-*` or `ListPageViewFrame` gutter on the table wrapper. * * Rule: `.cursor/rules/exxat-data-tables.mdc` ("Table edge inset"). * Handbook: `apps/web/AGENTS.md` §5. */ /** Toolbar row — filter chips, search, Properties trigger */ export const DATA_TABLE_TOOLBAR_INSET_CLASS = "px-4 lg:px-6" /** Bordered grid scrollport + attached pagination chrome */ export const DATA_TABLE_GRID_INSET_CLASS = "mx-4 lg:mx-6" const STACKED_INSET_WARN_THRESHOLD_PX = 8 function horizontalBoxInsetPx(el: HTMLElement): number { const style = getComputedStyle(el) return ( parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.marginLeft) + parseFloat(style.marginRight) ) } /** Dev-only: warn when a parent adds horizontal inset on top of DataTable-owned gutters. */ export function warnIfStackedTableEdgeInset( tableRoot: HTMLElement | null, label = "DataTable", ): void { if (typeof window === "undefined" || process.env.NODE_ENV === "production") return const parent = tableRoot?.parentElement if (!parent) return const inset = horizontalBoxInsetPx(parent) if (inset <= STACKED_INSET_WARN_THRESHOLD_PX) return const idSuffix = parent.id ? `#${parent.id}` : "" console.warn( `[Exxat DS][${label}] Parent <${parent.tagName.toLowerCase()}${idSuffix}> ` + `adds ~${Math.round(inset)}px horizontal inset on top of DataTable gutters ` + `(toolbar ${DATA_TABLE_TOOLBAR_INSET_CLASS}, grid ${DATA_TABLE_GRID_INSET_CLASS}). ` + "Remove parent px-* / mx-* or ListPageViewFrame gutter from the table wrapper. " + "Dashboard sections: pad the section intro only; keep HubTable full-bleed. " + "See exxat-data-tables.mdc (Table edge inset).", ) }