bento-grid-builder 0.1.0 → 0.2.1

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/dist/index.d.mts CHANGED
@@ -77,6 +77,8 @@ interface BentoLayoutConfig {
77
77
  columnGap?: number;
78
78
  /** Gap between rows in pixels (overrides gap for rows) */
79
79
  rowGap?: number;
80
+ /** Custom row heights (e.g., ["1fr", "2fr", "100px", "auto"]) */
81
+ rowHeights?: string[];
80
82
  /** Card placements in the grid */
81
83
  placements: CardPlacement[];
82
84
  }
@@ -373,6 +375,7 @@ declare function layoutBuilder(columns: number): {
373
375
  columnGap(value: number): /*elided*/ any;
374
376
  rowGap(value: number): /*elided*/ any;
375
377
  rows(value: number): /*elided*/ any;
378
+ rowHeights(heights: string[]): /*elided*/ any;
376
379
  place(cardId: string, col: number, row: number, options?: {
377
380
  colSpan?: number;
378
381
  rowSpan?: number;
package/dist/index.d.ts CHANGED
@@ -77,6 +77,8 @@ interface BentoLayoutConfig {
77
77
  columnGap?: number;
78
78
  /** Gap between rows in pixels (overrides gap for rows) */
79
79
  rowGap?: number;
80
+ /** Custom row heights (e.g., ["1fr", "2fr", "100px", "auto"]) */
81
+ rowHeights?: string[];
80
82
  /** Card placements in the grid */
81
83
  placements: CardPlacement[];
82
84
  }
@@ -373,6 +375,7 @@ declare function layoutBuilder(columns: number): {
373
375
  columnGap(value: number): /*elided*/ any;
374
376
  rowGap(value: number): /*elided*/ any;
375
377
  rows(value: number): /*elided*/ any;
378
+ rowHeights(heights: string[]): /*elided*/ any;
376
379
  place(cardId: string, col: number, row: number, options?: {
377
380
  colSpan?: number;
378
381
  rowSpan?: number;
package/dist/index.js CHANGED
@@ -256,6 +256,10 @@ function layoutBuilder(columns) {
256
256
  config.rows = value;
257
257
  return builder;
258
258
  },
259
+ rowHeights(heights) {
260
+ config.rowHeights = heights;
261
+ return builder;
262
+ },
259
263
  place(cardId, col, row, options) {
260
264
  config.placements.push({
261
265
  cardId,
@@ -439,13 +443,15 @@ function useGridStyles() {
439
443
  .bento-grid {
440
444
  display: grid;
441
445
  grid-template-columns: repeat(var(--bento-columns, 3), 1fr);
442
- grid-template-rows: repeat(var(--bento-rows, 2), minmax(0, 1fr));
446
+ grid-template-rows: var(--bento-row-heights, repeat(var(--bento-rows, 2), minmax(0, 1fr)));
443
447
  column-gap: var(--bento-column-gap, var(--bento-gap, 16px));
444
448
  row-gap: var(--bento-row-gap, var(--bento-gap, 16px));
445
449
  }
446
450
  .bento-cell {
447
451
  grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);
448
452
  grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);
453
+ min-height: 0;
454
+ overflow: hidden;
449
455
  }
450
456
  `;
451
457
  document.head.appendChild(style);
@@ -574,12 +580,15 @@ function BentoGrid({
574
580
  gap = 16,
575
581
  columnGap,
576
582
  rowGap,
583
+ rowHeights,
577
584
  placements
578
585
  } = resolvedLayout;
579
586
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
587
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
580
588
  const gridStyle = {
581
589
  "--bento-columns": columns,
582
590
  "--bento-rows": calculatedRows,
591
+ "--bento-row-heights": rowTemplate,
583
592
  "--bento-gap": `${gap}px`,
584
593
  "--bento-column-gap": `${columnGap ?? gap}px`,
585
594
  "--bento-row-gap": `${rowGap ?? gap}px`,
@@ -706,12 +715,15 @@ function UnifiedBentoGrid({
706
715
  gap = 16,
707
716
  columnGap,
708
717
  rowGap,
718
+ rowHeights,
709
719
  placements
710
720
  } = resolvedLayout;
711
721
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
722
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
712
723
  const gridStyle = {
713
724
  "--bento-columns": columns,
714
725
  "--bento-rows": calculatedRows,
726
+ "--bento-row-heights": rowTemplate,
715
727
  "--bento-gap": `${gap}px`,
716
728
  "--bento-column-gap": `${columnGap ?? gap}px`,
717
729
  "--bento-row-gap": `${rowGap ?? gap}px`,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/BentoGrid.tsx","../src/presets.ts","../src/BentoCard.tsx","../src/utils.ts","../src/hooks.ts"],"sourcesContent":["// Core components\nexport { BentoGrid, UnifiedBentoGrid } from \"./BentoGrid.js\";\nexport { BentoCard } from \"./BentoCard.js\";\n\n// Hooks\nexport {\n useCardDefinitions,\n useDataMapping,\n useLayout,\n useResponsiveLayout,\n useWindowWidth,\n isResponsiveConfig,\n} from \"./hooks.js\";\n\n// Utilities\nexport { createSimpleLayout, layoutBuilder, validateLayout } from \"./utils.js\";\n\n// Presets\nexport {\n PRESET_LAYOUTS,\n presetToLayout,\n isPresetName,\n getPresetSlotNames,\n} from \"./presets.js\";\n\n// Types\nexport type {\n BentoGridProps,\n UnifiedBentoGridProps,\n BentoCardProps,\n BentoCardDefinition,\n UnifiedCardDefinition,\n BentoLayoutConfig,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n CardPlacement,\n CardDataMapping,\n CardWrapperProps,\n PresetLayoutName,\n PresetLayout,\n PresetSlotMapping,\n} from \"./types.js\";\n","import React, { useMemo, useEffect } from \"react\";\nimport type {\n BentoGridProps,\n BentoLayoutConfig,\n BentoCardDefinition,\n CardDataMapping,\n CardWrapperProps,\n UnifiedBentoGridProps,\n UnifiedCardDefinition,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\nimport { BentoCard } from \"./BentoCard.js\";\nimport { validateLayout } from \"./utils.js\";\nimport { useResponsiveLayout } from \"./hooks.js\";\n\n/**\n * Default card wrapper - just uses BentoCard\n */\nconst DefaultCardWrapper: React.FC<CardWrapperProps> = ({\n children,\n className,\n style,\n}) => (\n <BentoCard className={className} style={style}>\n {children}\n </BentoCard>\n);\n\n/**\n * Default loading component - simple pulse animation\n */\nconst DefaultLoadingComponent: React.FC = () => (\n <div\n className=\"bento-card-loading\"\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 100,\n backgroundColor: \"var(--bento-loading-bg, rgba(128, 128, 128, 0.1))\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n animation: \"bento-pulse 1.5s ease-in-out infinite\",\n }}\n aria-label=\"Loading\"\n role=\"status\"\n />\n);\n\n/**\n * Inject base grid styles into the document\n * Uses CSS custom properties so Tailwind classes can override\n */\nfunction useGridStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-styles\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .bento-grid {\n display: grid;\n grid-template-columns: repeat(var(--bento-columns, 3), 1fr);\n grid-template-rows: repeat(var(--bento-rows, 2), minmax(0, 1fr));\n column-gap: var(--bento-column-gap, var(--bento-gap, 16px));\n row-gap: var(--bento-row-gap, var(--bento-gap, 16px));\n }\n .bento-cell {\n grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);\n grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Inject animation keyframes into the document\n */\nfunction useAnimationStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-animations\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n @keyframes bento-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n @keyframes bento-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n .bento-cell-animated {\n animation: bento-fade-in var(--bento-animation-duration, 300ms) ease-out;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Error boundary for individual cards\n * Resets when cardId or children change\n */\nclass CardErrorBoundary extends React.Component<\n {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n },\n { hasError: boolean; errorKey: string }\n> {\n constructor(props: {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n }) {\n super(props);\n this.state = {\n hasError: false,\n errorKey: `${props.cardId}-${props.resetKey ?? \"\"}`,\n };\n }\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n static getDerivedStateFromProps(\n props: { cardId: string; resetKey?: string | number },\n state: { errorKey: string },\n ) {\n const newKey = `${props.cardId}-${props.resetKey ?? \"\"}`;\n // Reset error state when key changes\n if (newKey !== state.errorKey) {\n return { hasError: false, errorKey: newKey };\n }\n return null;\n }\n\n componentDidCatch(error: Error) {\n this.props.onError?.(this.props.cardId, error);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div\n className=\"bento-card-error\"\n role=\"alert\"\n style={{ color: \"#ef4444\", padding: 16 }}\n >\n Failed to render card\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n/**\n * BentoGrid - A flexible, configurable bento grid layout system\n *\n * @example\n * ```tsx\n * <BentoGrid\n * layout=\"3x3\"\n * cards={[\n * { id: 'stats', component: StatsCard },\n * { id: 'chart', component: ChartCard },\n * ]}\n * data={myData}\n * dataMapping={[\n * { cardId: 'stats', propsSelector: (d) => ({ count: d.total }) },\n * { cardId: 'chart', propsSelector: (d) => ({ points: d.chartData }) },\n * ]}\n * />\n * ```\n */\nexport function BentoGrid<TData>({\n layout,\n cards,\n data,\n dataMapping,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n cellClassName,\n}: BentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = dataMapping.map((m) => m.cardId);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, dataMapping]);\n\n // Create lookup maps for cards and data mappings\n const cardMap = useMemo(() => {\n const map = new Map<string, BentoCardDefinition>();\n cards.forEach((card) => map.set(card.id, card));\n return map;\n }, [cards]);\n\n const dataMappingMap = useMemo(() => {\n const map = new Map<string, CardDataMapping<TData>>();\n dataMapping.forEach((mapping) => map.set(mapping.cardId, mapping));\n return map;\n }, [dataMapping]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"BentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!cards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n\n // Check for missing data mappings\n for (const placement of resolvedLayout.placements) {\n if (!dataMapping.some((m) => m.cardId === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" has no data mapping`,\n );\n }\n }\n }\n }, [resolvedLayout, cards, dataMapping]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n const mapping = dataMappingMap.get(placement.cardId);\n\n if (!card) {\n console.warn(`BentoGrid: Card \"${placement.cardId}\" not found`);\n return null;\n }\n\n // Get props from data mapping or empty object\n const cardProps = mapping ? mapping.propsSelector(data) : {};\n\n // Create a reset key for error boundary - changes when data changes\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n <CardComponent {...cardProps} />\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Check if a card should be visible based on its visibility config\n */\nfunction isCardVisible<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.visible === undefined) return true;\n if (typeof card.visible === \"function\") return card.visible(data);\n return card.visible;\n}\n\n/**\n * Check if a card is in loading state\n */\nfunction isCardLoading<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.loading === undefined) return false;\n if (typeof card.loading === \"function\") return card.loading(data);\n return card.loading;\n}\n\n/**\n * UnifiedBentoGrid - Cleaner API that combines cards and data mapping\n *\n * This is the preferred way to use BentoGrid. Instead of separate `cards` and\n * `dataMapping` arrays, you define everything in one place.\n *\n * @example\n * ```tsx\n * <UnifiedBentoGrid\n * layout=\"3x2\"\n * cards={[\n * {\n * id: 'stats',\n * component: StatsCard,\n * propsSelector: (d) => ({ count: d.total, label: 'Users' }),\n * colSpan: 2,\n * },\n * {\n * id: 'chart',\n * component: ChartCard,\n * propsSelector: (d) => ({ data: d.chartData }),\n * visible: (d) => d.chartData.length > 0,\n * loading: (d) => d.isLoading,\n * },\n * ]}\n * data={myData}\n * animated\n * />\n * ```\n */\nexport function UnifiedBentoGrid<TData>({\n layout,\n cards,\n data,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n loadingComponent: GlobalLoadingComponent = DefaultLoadingComponent,\n cellClassName,\n}: UnifiedBentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Filter visible cards\n const visibleCards = useMemo(() => {\n return cards.filter((card) => isCardVisible(card, data));\n }, [cards, data]);\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = visibleCards.map((c) => c.id);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, visibleCards]);\n\n // Create lookup map for cards\n const cardMap = useMemo(() => {\n const map = new Map<string, UnifiedCardDefinition<TData>>();\n visibleCards.forEach((card) => map.set(card.id, card));\n return map;\n }, [visibleCards]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"UnifiedBentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!visibleCards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n }\n }, [resolvedLayout, visibleCards]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n\n if (!card) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" not found`,\n );\n }\n return null;\n }\n\n // Check loading state\n const loading = isCardLoading(card, data);\n\n // Get props from card's propsSelector\n const cardProps = card.propsSelector(data);\n\n // Create a reset key for error boundary\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n const LoadingComponent =\n card.loadingComponent ?? GlobalLoadingComponent;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n {loading ? (\n <LoadingComponent />\n ) : (\n <CardComponent {...cardProps} />\n )}\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n","import type {\n PresetLayout,\n PresetLayoutName,\n BentoLayoutConfig,\n PresetSlotMapping,\n} from \"./types.js\";\n\n/**\n * Preset layout definitions\n * Users can use these by name instead of defining custom layouts\n */\nexport const PRESET_LAYOUTS: Record<PresetLayoutName, PresetLayout> = {\n \"2x2\": {\n name: \"2x2\",\n columns: 2,\n rows: 2,\n slots: [\n { name: \"top-left\", col: 1, row: 1 },\n { name: \"top-right\", col: 2, row: 1 },\n { name: \"bottom-left\", col: 1, row: 2 },\n { name: \"bottom-right\", col: 2, row: 2 },\n ],\n },\n \"3x2\": {\n name: \"3x2\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n ],\n },\n \"3x3\": {\n name: \"3x3\",\n columns: 3,\n rows: 3,\n slots: [\n { name: \"r1-c1\", col: 1, row: 1 },\n { name: \"r1-c2\", col: 2, row: 1 },\n { name: \"r1-c3\", col: 3, row: 1 },\n { name: \"r2-c1\", col: 1, row: 2 },\n { name: \"r2-c2\", col: 2, row: 2 },\n { name: \"r2-c3\", col: 3, row: 2 },\n { name: \"r3-c1\", col: 1, row: 3 },\n { name: \"r3-c2\", col: 2, row: 3 },\n { name: \"r3-c3\", col: 3, row: 3 },\n ],\n },\n \"4x2\": {\n name: \"4x2\",\n columns: 4,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"top-4\", col: 4, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n { name: \"bottom-4\", col: 4, row: 2 },\n ],\n },\n \"2x1-hero-left\": {\n name: \"2x1-hero-left\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"hero\", col: 1, row: 1, colSpan: 2, rowSpan: 2 },\n { name: \"side-top\", col: 3, row: 1 },\n { name: \"side-bottom\", col: 3, row: 2 },\n ],\n },\n \"2x1-hero-right\": {\n name: \"2x1-hero-right\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"side-top\", col: 1, row: 1 },\n { name: \"side-bottom\", col: 1, row: 2 },\n { name: \"hero\", col: 2, row: 1, colSpan: 2, rowSpan: 2 },\n ],\n },\n \"dashboard-9\": {\n name: \"dashboard-9\",\n columns: 3,\n rows: 4,\n slots: [\n { name: \"header-wide\", col: 1, row: 1, colSpan: 2 },\n { name: \"header-right\", col: 3, row: 1 },\n { name: \"hero\", col: 1, row: 2, rowSpan: 2 },\n { name: \"mid-center\", col: 2, row: 2 },\n { name: \"mid-right\", col: 3, row: 2 },\n { name: \"lower-center\", col: 2, row: 3 },\n { name: \"lower-right\", col: 3, row: 3 },\n { name: \"footer-left\", col: 1, row: 4 },\n { name: \"footer-wide\", col: 2, row: 4, colSpan: 2 },\n ],\n },\n};\n\n/**\n * Convert a preset name to a full layout config with card IDs\n * Supports both legacy array-based assignment and explicit slot mapping\n */\nexport function presetToLayout(\n presetName: PresetLayoutName,\n cardIdsOrMapping: string[] | PresetSlotMapping[],\n): BentoLayoutConfig {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n\n let placements;\n\n // Check if it's explicit slot mapping or legacy array\n if (\n cardIdsOrMapping.length > 0 &&\n typeof cardIdsOrMapping[0] === \"object\" &&\n \"slot\" in cardIdsOrMapping[0]\n ) {\n // Explicit slot mapping\n const slotMapping = cardIdsOrMapping as PresetSlotMapping[];\n placements = slotMapping\n .map((mapping) => {\n const slotIndex =\n typeof mapping.slot === \"number\"\n ? mapping.slot\n : preset.slots.findIndex((s) => s.name === mapping.slot);\n\n if (slotIndex === -1 || slotIndex >= preset.slots.length) {\n console.warn(\n `Preset \"${presetName}\": slot \"${mapping.slot}\" not found`,\n );\n return null;\n }\n\n const slot = preset.slots[slotIndex];\n return {\n cardId: mapping.cardId,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n };\n })\n .filter((p): p is NonNullable<typeof p> => p !== null);\n } else {\n // Legacy array-based assignment\n const cardIds = cardIdsOrMapping as string[];\n placements = preset.slots.map((slot, index) => ({\n cardId: cardIds[index] ?? `card-${index}`,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n }));\n }\n\n return {\n columns: preset.columns,\n rows: preset.rows,\n placements,\n };\n}\n\n/**\n * Get available slot names for a preset layout\n * Useful for discovering what slots are available\n */\nexport function getPresetSlotNames(presetName: PresetLayoutName): string[] {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n return preset.slots.map((s, i) => s.name ?? `slot-${i}`);\n}\n\n/**\n * Check if a value is a preset layout name\n */\nexport function isPresetName(value: unknown): value is PresetLayoutName {\n return typeof value === \"string\" && value in PRESET_LAYOUTS;\n}\n","import React from \"react\";\nimport type { BentoCardProps } from \"./types.js\";\n\n/**\n * Default card wrapper component\n * Provides basic styling - users can override with their own wrapper\n * Uses CSS custom properties for easy theming\n */\nexport const BentoCard: React.FC<BentoCardProps> = ({\n children,\n className = \"\",\n style,\n}) => (\n <div\n className={`bento-card ${className}`}\n style={{\n backgroundColor: \"var(--bento-card-bg, transparent)\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n padding: \"var(--bento-card-padding, 16px)\",\n border: \"var(--bento-card-border, 1px solid rgba(128, 128, 128, 0.2))\",\n height: \"100%\",\n boxSizing: \"border-box\",\n ...style,\n }}\n >\n {children}\n </div>\n);\n","import type { BentoLayoutConfig, CardPlacement } from \"./types.js\";\n\n/**\n * Create a simple grid layout where cards are placed sequentially\n * Useful for quick prototyping\n *\n * @example\n * ```ts\n * const layout = createSimpleLayout(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]);\n * // Creates a 3-column grid with cards placed left-to-right, top-to-bottom\n * ```\n */\nexport function createSimpleLayout(\n columns: number,\n cardIds: string[],\n gap?: number,\n): BentoLayoutConfig {\n const placements: CardPlacement[] = cardIds.map((cardId, index) => ({\n cardId,\n col: (index % columns) + 1,\n row: Math.floor(index / columns) + 1,\n }));\n\n return {\n columns,\n gap,\n placements,\n };\n}\n\n/**\n * Layout builder for fluent API\n *\n * @example\n * ```ts\n * const layout = layoutBuilder(3)\n * .gap(16)\n * .columnGap(20)\n * .rowGap(12)\n * .place(\"hero\", 1, 1, { colSpan: 2, rowSpan: 2 })\n * .place(\"stats\", 3, 1)\n * .place(\"chart\", 3, 2)\n * .build();\n * ```\n */\nexport function layoutBuilder(columns: number) {\n const config: BentoLayoutConfig = {\n columns,\n placements: [],\n };\n\n const builder = {\n gap(value: number) {\n config.gap = value;\n return builder;\n },\n columnGap(value: number) {\n config.columnGap = value;\n return builder;\n },\n rowGap(value: number) {\n config.rowGap = value;\n return builder;\n },\n rows(value: number) {\n config.rows = value;\n return builder;\n },\n place(\n cardId: string,\n col: number,\n row: number,\n options?: { colSpan?: number; rowSpan?: number },\n ) {\n config.placements.push({\n cardId,\n col,\n row,\n ...options,\n });\n return builder;\n },\n build(): BentoLayoutConfig {\n return config;\n },\n };\n\n return builder;\n}\n\n/**\n * Validate a layout configuration\n * Returns array of validation errors (empty if valid)\n */\nexport function validateLayout(layout: BentoLayoutConfig): string[] {\n const errors: string[] = [];\n\n if (layout.columns < 1) {\n errors.push(\"columns must be at least 1\");\n }\n\n if (layout.rows !== undefined && layout.rows < 1) {\n errors.push(\"rows must be at least 1\");\n }\n\n if (layout.gap !== undefined && layout.gap < 0) {\n errors.push(\"gap cannot be negative\");\n }\n\n const occupied = new Set<string>();\n\n for (const placement of layout.placements) {\n const colSpan = placement.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? 1;\n\n // Check bounds\n if (placement.col < 1 || placement.col + colSpan - 1 > layout.columns) {\n errors.push(\n `Card \"${placement.cardId}\" exceeds column bounds (col: ${placement.col}, span: ${colSpan})`,\n );\n }\n\n if (placement.row < 1) {\n errors.push(\n `Card \"${placement.cardId}\" has invalid row: ${placement.row}`,\n );\n }\n\n // Check overlaps\n for (let c = placement.col; c < placement.col + colSpan; c++) {\n for (let r = placement.row; r < placement.row + rowSpan; r++) {\n const key = `${c},${r}`;\n if (occupied.has(key)) {\n errors.push(\n `Card \"${placement.cardId}\" overlaps at position (${c}, ${r})`,\n );\n }\n occupied.add(key);\n }\n }\n }\n\n return errors;\n}\n","import { useMemo, useRef, useState, useEffect, useCallback } from \"react\";\nimport type {\n BentoCardDefinition,\n CardDataMapping,\n BentoLayoutConfig,\n PresetLayoutName,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\n\n/**\n * Deep comparison for stable memoization of object inputs\n */\nfunction useStableValue<T>(value: T): T {\n const ref = useRef<T>(value);\n const prevJson = useRef<string>(\"\");\n\n // Compare by serializing - works for our use case of simple config objects\n // For components, we compare by reference using a custom replacer\n const json = JSON.stringify(value, (key, val) => {\n if (typeof val === \"function\") {\n return val.toString();\n }\n return val;\n });\n\n if (json !== prevJson.current) {\n ref.current = value;\n prevJson.current = json;\n }\n\n return ref.current;\n}\n\n/**\n * Check if a layout config is a responsive config\n */\nexport function isResponsiveConfig(\n layout: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): layout is ResponsiveLayoutConfig {\n return (\n typeof layout === \"object\" && \"default\" in layout && \"breakpoints\" in layout\n );\n}\n\n/**\n * Hook to handle responsive layouts based on viewport width\n * Returns the appropriate layout for the current viewport\n *\n * @example\n * ```tsx\n * const layout = useResponsiveLayout({\n * default: \"2x2\",\n * breakpoints: [\n * { minWidth: 768, layout: \"3x2\" },\n * { minWidth: 1024, layout: \"4x2\" },\n * ],\n * });\n * ```\n */\nexport function useResponsiveLayout(\n config: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): BentoLayoutConfig | PresetLayoutName {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const handleResize = () => setWidth(window.innerWidth);\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return useMemo(() => {\n if (!isResponsiveConfig(config)) {\n return config;\n }\n\n // Sort breakpoints by minWidth descending to find the largest matching one\n const sortedBreakpoints = [...config.breakpoints].sort(\n (a, b) => b.minWidth - a.minWidth,\n );\n\n for (const bp of sortedBreakpoints) {\n if (width >= bp.minWidth) {\n return bp.layout;\n }\n }\n\n return config.default;\n }, [config, width]);\n}\n\n/**\n * Hook to track window width with debouncing\n */\nexport function useWindowWidth(debounceMs = 100): number {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const handleResize = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => setWidth(window.innerWidth), debounceMs);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [debounceMs]);\n\n return width;\n}\n\n/**\n * Hook to create card definitions from an object map\n * Provides a cleaner API for defining cards\n *\n * @example\n * ```tsx\n * const cards = useCardDefinitions({\n * stats: { component: StatsCard, colSpan: 2 },\n * chart: { component: ChartCard },\n * list: { component: ListCard, rowSpan: 2 },\n * });\n * ```\n */\nexport function useCardDefinitions<\n T extends Record<string, Omit<BentoCardDefinition<any>, \"id\">>,\n>(definitions: T): BentoCardDefinition<any>[] {\n const stableDefinitions = useStableValue(definitions);\n\n return useMemo(() => {\n return Object.entries(stableDefinitions).map(([id, def]) => ({\n id,\n ...def,\n }));\n }, [stableDefinitions]);\n}\n\n/**\n * Hook to create data mappings from an object map\n * Provides a cleaner API for mapping data to cards\n *\n * @example\n * ```tsx\n * const dataMapping = useDataMapping<MyDataType>({\n * stats: (data) => ({ count: data.total, label: 'Items' }),\n * chart: (data) => ({ points: data.chartData }),\n * });\n * ```\n */\nexport function useDataMapping<TData>(\n mappings: Record<string, (data: TData) => Record<string, unknown>>,\n): CardDataMapping<TData>[] {\n const stableMappings = useStableValue(mappings);\n\n return useMemo(() => {\n return Object.entries(stableMappings).map(([cardId, propsSelector]) => ({\n cardId,\n propsSelector,\n }));\n }, [stableMappings]);\n}\n\n/**\n * Hook to create a layout configuration\n * Handles both preset names and custom configs\n *\n * @example\n * ```tsx\n * // Using preset\n * const layout = useLayout(\"3x3\", [\"stats\", \"chart\", \"list\", ...]);\n *\n * // Using custom config\n * const layout = useLayout({\n * columns: 3,\n * placements: [\n * { cardId: \"stats\", col: 1, row: 1, colSpan: 2 },\n * { cardId: \"chart\", col: 3, row: 1 },\n * ]\n * });\n * ```\n */\nexport function useLayout(\n config: PresetLayoutName | BentoLayoutConfig,\n cardIds?: string[],\n): BentoLayoutConfig {\n return useMemo(() => {\n if (isPresetName(config)) {\n if (!cardIds) {\n throw new Error(\"cardIds required when using preset layout name\");\n }\n return presetToLayout(config, cardIds);\n }\n return config;\n }, [config, cardIds]);\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","React"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/BentoGrid.tsx","../src/presets.ts","../src/BentoCard.tsx","../src/utils.ts","../src/hooks.ts"],"sourcesContent":["// Core components\nexport { BentoGrid, UnifiedBentoGrid } from \"./BentoGrid.js\";\nexport { BentoCard } from \"./BentoCard.js\";\n\n// Hooks\nexport {\n useCardDefinitions,\n useDataMapping,\n useLayout,\n useResponsiveLayout,\n useWindowWidth,\n isResponsiveConfig,\n} from \"./hooks.js\";\n\n// Utilities\nexport { createSimpleLayout, layoutBuilder, validateLayout } from \"./utils.js\";\n\n// Presets\nexport {\n PRESET_LAYOUTS,\n presetToLayout,\n isPresetName,\n getPresetSlotNames,\n} from \"./presets.js\";\n\n// Types\nexport type {\n BentoGridProps,\n UnifiedBentoGridProps,\n BentoCardProps,\n BentoCardDefinition,\n UnifiedCardDefinition,\n BentoLayoutConfig,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n CardPlacement,\n CardDataMapping,\n CardWrapperProps,\n PresetLayoutName,\n PresetLayout,\n PresetSlotMapping,\n} from \"./types.js\";\n","import React, { useMemo, useEffect } from \"react\";\nimport type {\n BentoGridProps,\n BentoLayoutConfig,\n BentoCardDefinition,\n CardDataMapping,\n CardWrapperProps,\n UnifiedBentoGridProps,\n UnifiedCardDefinition,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\nimport { BentoCard } from \"./BentoCard.js\";\nimport { validateLayout } from \"./utils.js\";\nimport { useResponsiveLayout } from \"./hooks.js\";\n\n/**\n * Default card wrapper - just uses BentoCard\n */\nconst DefaultCardWrapper: React.FC<CardWrapperProps> = ({\n children,\n className,\n style,\n}) => (\n <BentoCard className={className} style={style}>\n {children}\n </BentoCard>\n);\n\n/**\n * Default loading component - simple pulse animation\n */\nconst DefaultLoadingComponent: React.FC = () => (\n <div\n className=\"bento-card-loading\"\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 100,\n backgroundColor: \"var(--bento-loading-bg, rgba(128, 128, 128, 0.1))\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n animation: \"bento-pulse 1.5s ease-in-out infinite\",\n }}\n aria-label=\"Loading\"\n role=\"status\"\n />\n);\n\n/**\n * Inject base grid styles into the document\n * Uses CSS custom properties so Tailwind classes can override\n */\nfunction useGridStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-styles\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .bento-grid {\n display: grid;\n grid-template-columns: repeat(var(--bento-columns, 3), 1fr);\n grid-template-rows: var(--bento-row-heights, repeat(var(--bento-rows, 2), minmax(0, 1fr)));\n column-gap: var(--bento-column-gap, var(--bento-gap, 16px));\n row-gap: var(--bento-row-gap, var(--bento-gap, 16px));\n }\n .bento-cell {\n grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);\n grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);\n min-height: 0;\n overflow: hidden;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Inject animation keyframes into the document\n */\nfunction useAnimationStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-animations\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n @keyframes bento-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n @keyframes bento-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n .bento-cell-animated {\n animation: bento-fade-in var(--bento-animation-duration, 300ms) ease-out;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Error boundary for individual cards\n * Resets when cardId or children change\n */\nclass CardErrorBoundary extends React.Component<\n {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n },\n { hasError: boolean; errorKey: string }\n> {\n constructor(props: {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n }) {\n super(props);\n this.state = {\n hasError: false,\n errorKey: `${props.cardId}-${props.resetKey ?? \"\"}`,\n };\n }\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n static getDerivedStateFromProps(\n props: { cardId: string; resetKey?: string | number },\n state: { errorKey: string },\n ) {\n const newKey = `${props.cardId}-${props.resetKey ?? \"\"}`;\n // Reset error state when key changes\n if (newKey !== state.errorKey) {\n return { hasError: false, errorKey: newKey };\n }\n return null;\n }\n\n componentDidCatch(error: Error) {\n this.props.onError?.(this.props.cardId, error);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div\n className=\"bento-card-error\"\n role=\"alert\"\n style={{ color: \"#ef4444\", padding: 16 }}\n >\n Failed to render card\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n/**\n * BentoGrid - A flexible, configurable bento grid layout system\n *\n * @example\n * ```tsx\n * <BentoGrid\n * layout=\"3x3\"\n * cards={[\n * { id: 'stats', component: StatsCard },\n * { id: 'chart', component: ChartCard },\n * ]}\n * data={myData}\n * dataMapping={[\n * { cardId: 'stats', propsSelector: (d) => ({ count: d.total }) },\n * { cardId: 'chart', propsSelector: (d) => ({ points: d.chartData }) },\n * ]}\n * />\n * ```\n */\nexport function BentoGrid<TData>({\n layout,\n cards,\n data,\n dataMapping,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n cellClassName,\n}: BentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = dataMapping.map((m) => m.cardId);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, dataMapping]);\n\n // Create lookup maps for cards and data mappings\n const cardMap = useMemo(() => {\n const map = new Map<string, BentoCardDefinition>();\n cards.forEach((card) => map.set(card.id, card));\n return map;\n }, [cards]);\n\n const dataMappingMap = useMemo(() => {\n const map = new Map<string, CardDataMapping<TData>>();\n dataMapping.forEach((mapping) => map.set(mapping.cardId, mapping));\n return map;\n }, [dataMapping]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"BentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!cards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n\n // Check for missing data mappings\n for (const placement of resolvedLayout.placements) {\n if (!dataMapping.some((m) => m.cardId === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" has no data mapping`,\n );\n }\n }\n }\n }, [resolvedLayout, cards, dataMapping]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n rowHeights,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Compute row template: use custom rowHeights if provided, otherwise equal 1fr rows\n const rowTemplate = rowHeights\n ? rowHeights.join(\" \")\n : `repeat(${calculatedRows}, minmax(0, 1fr))`;\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-row-heights\": rowTemplate,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n const mapping = dataMappingMap.get(placement.cardId);\n\n if (!card) {\n console.warn(`BentoGrid: Card \"${placement.cardId}\" not found`);\n return null;\n }\n\n // Get props from data mapping or empty object\n const cardProps = mapping ? mapping.propsSelector(data) : {};\n\n // Create a reset key for error boundary - changes when data changes\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n <CardComponent {...cardProps} />\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Check if a card should be visible based on its visibility config\n */\nfunction isCardVisible<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.visible === undefined) return true;\n if (typeof card.visible === \"function\") return card.visible(data);\n return card.visible;\n}\n\n/**\n * Check if a card is in loading state\n */\nfunction isCardLoading<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.loading === undefined) return false;\n if (typeof card.loading === \"function\") return card.loading(data);\n return card.loading;\n}\n\n/**\n * UnifiedBentoGrid - Cleaner API that combines cards and data mapping\n *\n * This is the preferred way to use BentoGrid. Instead of separate `cards` and\n * `dataMapping` arrays, you define everything in one place.\n *\n * @example\n * ```tsx\n * <UnifiedBentoGrid\n * layout=\"3x2\"\n * cards={[\n * {\n * id: 'stats',\n * component: StatsCard,\n * propsSelector: (d) => ({ count: d.total, label: 'Users' }),\n * colSpan: 2,\n * },\n * {\n * id: 'chart',\n * component: ChartCard,\n * propsSelector: (d) => ({ data: d.chartData }),\n * visible: (d) => d.chartData.length > 0,\n * loading: (d) => d.isLoading,\n * },\n * ]}\n * data={myData}\n * animated\n * />\n * ```\n */\nexport function UnifiedBentoGrid<TData>({\n layout,\n cards,\n data,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n loadingComponent: GlobalLoadingComponent = DefaultLoadingComponent,\n cellClassName,\n}: UnifiedBentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Filter visible cards\n const visibleCards = useMemo(() => {\n return cards.filter((card) => isCardVisible(card, data));\n }, [cards, data]);\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = visibleCards.map((c) => c.id);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, visibleCards]);\n\n // Create lookup map for cards\n const cardMap = useMemo(() => {\n const map = new Map<string, UnifiedCardDefinition<TData>>();\n visibleCards.forEach((card) => map.set(card.id, card));\n return map;\n }, [visibleCards]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"UnifiedBentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!visibleCards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n }\n }, [resolvedLayout, visibleCards]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n rowHeights,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Compute row template: use custom rowHeights if provided, otherwise equal 1fr rows\n const rowTemplate = rowHeights\n ? rowHeights.join(\" \")\n : `repeat(${calculatedRows}, minmax(0, 1fr))`;\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-row-heights\": rowTemplate,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n\n if (!card) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" not found`,\n );\n }\n return null;\n }\n\n // Check loading state\n const loading = isCardLoading(card, data);\n\n // Get props from card's propsSelector\n const cardProps = card.propsSelector(data);\n\n // Create a reset key for error boundary\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n const LoadingComponent =\n card.loadingComponent ?? GlobalLoadingComponent;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n {loading ? (\n <LoadingComponent />\n ) : (\n <CardComponent {...cardProps} />\n )}\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n","import type {\n PresetLayout,\n PresetLayoutName,\n BentoLayoutConfig,\n PresetSlotMapping,\n} from \"./types.js\";\n\n/**\n * Preset layout definitions\n * Users can use these by name instead of defining custom layouts\n */\nexport const PRESET_LAYOUTS: Record<PresetLayoutName, PresetLayout> = {\n \"2x2\": {\n name: \"2x2\",\n columns: 2,\n rows: 2,\n slots: [\n { name: \"top-left\", col: 1, row: 1 },\n { name: \"top-right\", col: 2, row: 1 },\n { name: \"bottom-left\", col: 1, row: 2 },\n { name: \"bottom-right\", col: 2, row: 2 },\n ],\n },\n \"3x2\": {\n name: \"3x2\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n ],\n },\n \"3x3\": {\n name: \"3x3\",\n columns: 3,\n rows: 3,\n slots: [\n { name: \"r1-c1\", col: 1, row: 1 },\n { name: \"r1-c2\", col: 2, row: 1 },\n { name: \"r1-c3\", col: 3, row: 1 },\n { name: \"r2-c1\", col: 1, row: 2 },\n { name: \"r2-c2\", col: 2, row: 2 },\n { name: \"r2-c3\", col: 3, row: 2 },\n { name: \"r3-c1\", col: 1, row: 3 },\n { name: \"r3-c2\", col: 2, row: 3 },\n { name: \"r3-c3\", col: 3, row: 3 },\n ],\n },\n \"4x2\": {\n name: \"4x2\",\n columns: 4,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"top-4\", col: 4, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n { name: \"bottom-4\", col: 4, row: 2 },\n ],\n },\n \"2x1-hero-left\": {\n name: \"2x1-hero-left\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"hero\", col: 1, row: 1, colSpan: 2, rowSpan: 2 },\n { name: \"side-top\", col: 3, row: 1 },\n { name: \"side-bottom\", col: 3, row: 2 },\n ],\n },\n \"2x1-hero-right\": {\n name: \"2x1-hero-right\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"side-top\", col: 1, row: 1 },\n { name: \"side-bottom\", col: 1, row: 2 },\n { name: \"hero\", col: 2, row: 1, colSpan: 2, rowSpan: 2 },\n ],\n },\n \"dashboard-9\": {\n name: \"dashboard-9\",\n columns: 3,\n rows: 4,\n slots: [\n { name: \"header-wide\", col: 1, row: 1, colSpan: 2 },\n { name: \"header-right\", col: 3, row: 1 },\n { name: \"hero\", col: 1, row: 2, rowSpan: 2 },\n { name: \"mid-center\", col: 2, row: 2 },\n { name: \"mid-right\", col: 3, row: 2 },\n { name: \"lower-center\", col: 2, row: 3 },\n { name: \"lower-right\", col: 3, row: 3 },\n { name: \"footer-left\", col: 1, row: 4 },\n { name: \"footer-wide\", col: 2, row: 4, colSpan: 2 },\n ],\n },\n};\n\n/**\n * Convert a preset name to a full layout config with card IDs\n * Supports both legacy array-based assignment and explicit slot mapping\n */\nexport function presetToLayout(\n presetName: PresetLayoutName,\n cardIdsOrMapping: string[] | PresetSlotMapping[],\n): BentoLayoutConfig {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n\n let placements;\n\n // Check if it's explicit slot mapping or legacy array\n if (\n cardIdsOrMapping.length > 0 &&\n typeof cardIdsOrMapping[0] === \"object\" &&\n \"slot\" in cardIdsOrMapping[0]\n ) {\n // Explicit slot mapping\n const slotMapping = cardIdsOrMapping as PresetSlotMapping[];\n placements = slotMapping\n .map((mapping) => {\n const slotIndex =\n typeof mapping.slot === \"number\"\n ? mapping.slot\n : preset.slots.findIndex((s) => s.name === mapping.slot);\n\n if (slotIndex === -1 || slotIndex >= preset.slots.length) {\n console.warn(\n `Preset \"${presetName}\": slot \"${mapping.slot}\" not found`,\n );\n return null;\n }\n\n const slot = preset.slots[slotIndex];\n return {\n cardId: mapping.cardId,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n };\n })\n .filter((p): p is NonNullable<typeof p> => p !== null);\n } else {\n // Legacy array-based assignment\n const cardIds = cardIdsOrMapping as string[];\n placements = preset.slots.map((slot, index) => ({\n cardId: cardIds[index] ?? `card-${index}`,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n }));\n }\n\n return {\n columns: preset.columns,\n rows: preset.rows,\n placements,\n };\n}\n\n/**\n * Get available slot names for a preset layout\n * Useful for discovering what slots are available\n */\nexport function getPresetSlotNames(presetName: PresetLayoutName): string[] {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n return preset.slots.map((s, i) => s.name ?? `slot-${i}`);\n}\n\n/**\n * Check if a value is a preset layout name\n */\nexport function isPresetName(value: unknown): value is PresetLayoutName {\n return typeof value === \"string\" && value in PRESET_LAYOUTS;\n}\n","import React from \"react\";\nimport type { BentoCardProps } from \"./types.js\";\n\n/**\n * Default card wrapper component\n * Provides basic styling - users can override with their own wrapper\n * Uses CSS custom properties for easy theming\n */\nexport const BentoCard: React.FC<BentoCardProps> = ({\n children,\n className = \"\",\n style,\n}) => (\n <div\n className={`bento-card ${className}`}\n style={{\n backgroundColor: \"var(--bento-card-bg, transparent)\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n padding: \"var(--bento-card-padding, 16px)\",\n border: \"var(--bento-card-border, 1px solid rgba(128, 128, 128, 0.2))\",\n height: \"100%\",\n boxSizing: \"border-box\",\n ...style,\n }}\n >\n {children}\n </div>\n);\n","import type { BentoLayoutConfig, CardPlacement } from \"./types.js\";\n\n/**\n * Create a simple grid layout where cards are placed sequentially\n * Useful for quick prototyping\n *\n * @example\n * ```ts\n * const layout = createSimpleLayout(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]);\n * // Creates a 3-column grid with cards placed left-to-right, top-to-bottom\n * ```\n */\nexport function createSimpleLayout(\n columns: number,\n cardIds: string[],\n gap?: number,\n): BentoLayoutConfig {\n const placements: CardPlacement[] = cardIds.map((cardId, index) => ({\n cardId,\n col: (index % columns) + 1,\n row: Math.floor(index / columns) + 1,\n }));\n\n return {\n columns,\n gap,\n placements,\n };\n}\n\n/**\n * Layout builder for fluent API\n *\n * @example\n * ```ts\n * const layout = layoutBuilder(3)\n * .gap(16)\n * .columnGap(20)\n * .rowGap(12)\n * .place(\"hero\", 1, 1, { colSpan: 2, rowSpan: 2 })\n * .place(\"stats\", 3, 1)\n * .place(\"chart\", 3, 2)\n * .build();\n * ```\n */\nexport function layoutBuilder(columns: number) {\n const config: BentoLayoutConfig = {\n columns,\n placements: [],\n };\n\n const builder = {\n gap(value: number) {\n config.gap = value;\n return builder;\n },\n columnGap(value: number) {\n config.columnGap = value;\n return builder;\n },\n rowGap(value: number) {\n config.rowGap = value;\n return builder;\n },\n rows(value: number) {\n config.rows = value;\n return builder;\n },\n rowHeights(heights: string[]) {\n config.rowHeights = heights;\n return builder;\n },\n place(\n cardId: string,\n col: number,\n row: number,\n options?: { colSpan?: number; rowSpan?: number },\n ) {\n config.placements.push({\n cardId,\n col,\n row,\n ...options,\n });\n return builder;\n },\n build(): BentoLayoutConfig {\n return config;\n },\n };\n\n return builder;\n}\n\n/**\n * Validate a layout configuration\n * Returns array of validation errors (empty if valid)\n */\nexport function validateLayout(layout: BentoLayoutConfig): string[] {\n const errors: string[] = [];\n\n if (layout.columns < 1) {\n errors.push(\"columns must be at least 1\");\n }\n\n if (layout.rows !== undefined && layout.rows < 1) {\n errors.push(\"rows must be at least 1\");\n }\n\n if (layout.gap !== undefined && layout.gap < 0) {\n errors.push(\"gap cannot be negative\");\n }\n\n const occupied = new Set<string>();\n\n for (const placement of layout.placements) {\n const colSpan = placement.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? 1;\n\n // Check bounds\n if (placement.col < 1 || placement.col + colSpan - 1 > layout.columns) {\n errors.push(\n `Card \"${placement.cardId}\" exceeds column bounds (col: ${placement.col}, span: ${colSpan})`,\n );\n }\n\n if (placement.row < 1) {\n errors.push(\n `Card \"${placement.cardId}\" has invalid row: ${placement.row}`,\n );\n }\n\n // Check overlaps\n for (let c = placement.col; c < placement.col + colSpan; c++) {\n for (let r = placement.row; r < placement.row + rowSpan; r++) {\n const key = `${c},${r}`;\n if (occupied.has(key)) {\n errors.push(\n `Card \"${placement.cardId}\" overlaps at position (${c}, ${r})`,\n );\n }\n occupied.add(key);\n }\n }\n }\n\n return errors;\n}\n","import { useMemo, useRef, useState, useEffect, useCallback } from \"react\";\nimport type {\n BentoCardDefinition,\n CardDataMapping,\n BentoLayoutConfig,\n PresetLayoutName,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\n\n/**\n * Deep comparison for stable memoization of object inputs\n */\nfunction useStableValue<T>(value: T): T {\n const ref = useRef<T>(value);\n const prevJson = useRef<string>(\"\");\n\n // Compare by serializing - works for our use case of simple config objects\n // For components, we compare by reference using a custom replacer\n const json = JSON.stringify(value, (key, val) => {\n if (typeof val === \"function\") {\n return val.toString();\n }\n return val;\n });\n\n if (json !== prevJson.current) {\n ref.current = value;\n prevJson.current = json;\n }\n\n return ref.current;\n}\n\n/**\n * Check if a layout config is a responsive config\n */\nexport function isResponsiveConfig(\n layout: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): layout is ResponsiveLayoutConfig {\n return (\n typeof layout === \"object\" && \"default\" in layout && \"breakpoints\" in layout\n );\n}\n\n/**\n * Hook to handle responsive layouts based on viewport width\n * Returns the appropriate layout for the current viewport\n *\n * @example\n * ```tsx\n * const layout = useResponsiveLayout({\n * default: \"2x2\",\n * breakpoints: [\n * { minWidth: 768, layout: \"3x2\" },\n * { minWidth: 1024, layout: \"4x2\" },\n * ],\n * });\n * ```\n */\nexport function useResponsiveLayout(\n config: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): BentoLayoutConfig | PresetLayoutName {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const handleResize = () => setWidth(window.innerWidth);\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return useMemo(() => {\n if (!isResponsiveConfig(config)) {\n return config;\n }\n\n // Sort breakpoints by minWidth descending to find the largest matching one\n const sortedBreakpoints = [...config.breakpoints].sort(\n (a, b) => b.minWidth - a.minWidth,\n );\n\n for (const bp of sortedBreakpoints) {\n if (width >= bp.minWidth) {\n return bp.layout;\n }\n }\n\n return config.default;\n }, [config, width]);\n}\n\n/**\n * Hook to track window width with debouncing\n */\nexport function useWindowWidth(debounceMs = 100): number {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const handleResize = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => setWidth(window.innerWidth), debounceMs);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [debounceMs]);\n\n return width;\n}\n\n/**\n * Hook to create card definitions from an object map\n * Provides a cleaner API for defining cards\n *\n * @example\n * ```tsx\n * const cards = useCardDefinitions({\n * stats: { component: StatsCard, colSpan: 2 },\n * chart: { component: ChartCard },\n * list: { component: ListCard, rowSpan: 2 },\n * });\n * ```\n */\nexport function useCardDefinitions<\n T extends Record<string, Omit<BentoCardDefinition<any>, \"id\">>,\n>(definitions: T): BentoCardDefinition<any>[] {\n const stableDefinitions = useStableValue(definitions);\n\n return useMemo(() => {\n return Object.entries(stableDefinitions).map(([id, def]) => ({\n id,\n ...def,\n }));\n }, [stableDefinitions]);\n}\n\n/**\n * Hook to create data mappings from an object map\n * Provides a cleaner API for mapping data to cards\n *\n * @example\n * ```tsx\n * const dataMapping = useDataMapping<MyDataType>({\n * stats: (data) => ({ count: data.total, label: 'Items' }),\n * chart: (data) => ({ points: data.chartData }),\n * });\n * ```\n */\nexport function useDataMapping<TData>(\n mappings: Record<string, (data: TData) => Record<string, unknown>>,\n): CardDataMapping<TData>[] {\n const stableMappings = useStableValue(mappings);\n\n return useMemo(() => {\n return Object.entries(stableMappings).map(([cardId, propsSelector]) => ({\n cardId,\n propsSelector,\n }));\n }, [stableMappings]);\n}\n\n/**\n * Hook to create a layout configuration\n * Handles both preset names and custom configs\n *\n * @example\n * ```tsx\n * // Using preset\n * const layout = useLayout(\"3x3\", [\"stats\", \"chart\", \"list\", ...]);\n *\n * // Using custom config\n * const layout = useLayout({\n * columns: 3,\n * placements: [\n * { cardId: \"stats\", col: 1, row: 1, colSpan: 2 },\n * { cardId: \"chart\", col: 3, row: 1 },\n * ]\n * });\n * ```\n */\nexport function useLayout(\n config: PresetLayoutName | BentoLayoutConfig,\n cardIds?: string[],\n): BentoLayoutConfig {\n return useMemo(() => {\n if (isPresetName(config)) {\n if (!cardIds) {\n throw new Error(\"cardIds required when using preset layout name\");\n }\n return presetToLayout(config, cardIds);\n }\n return config;\n }, [config, cardIds]);\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","React"]}
package/dist/index.mjs CHANGED
@@ -205,6 +205,10 @@ function layoutBuilder(columns) {
205
205
  config.rows = value;
206
206
  return builder;
207
207
  },
208
+ rowHeights(heights) {
209
+ config.rowHeights = heights;
210
+ return builder;
211
+ },
208
212
  place(cardId, col, row, options) {
209
213
  config.placements.push({
210
214
  cardId,
@@ -388,13 +392,15 @@ function useGridStyles() {
388
392
  .bento-grid {
389
393
  display: grid;
390
394
  grid-template-columns: repeat(var(--bento-columns, 3), 1fr);
391
- grid-template-rows: repeat(var(--bento-rows, 2), minmax(0, 1fr));
395
+ grid-template-rows: var(--bento-row-heights, repeat(var(--bento-rows, 2), minmax(0, 1fr)));
392
396
  column-gap: var(--bento-column-gap, var(--bento-gap, 16px));
393
397
  row-gap: var(--bento-row-gap, var(--bento-gap, 16px));
394
398
  }
395
399
  .bento-cell {
396
400
  grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);
397
401
  grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);
402
+ min-height: 0;
403
+ overflow: hidden;
398
404
  }
399
405
  `;
400
406
  document.head.appendChild(style);
@@ -523,12 +529,15 @@ function BentoGrid({
523
529
  gap = 16,
524
530
  columnGap,
525
531
  rowGap,
532
+ rowHeights,
526
533
  placements
527
534
  } = resolvedLayout;
528
535
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
536
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
529
537
  const gridStyle = {
530
538
  "--bento-columns": columns,
531
539
  "--bento-rows": calculatedRows,
540
+ "--bento-row-heights": rowTemplate,
532
541
  "--bento-gap": `${gap}px`,
533
542
  "--bento-column-gap": `${columnGap ?? gap}px`,
534
543
  "--bento-row-gap": `${rowGap ?? gap}px`,
@@ -655,12 +664,15 @@ function UnifiedBentoGrid({
655
664
  gap = 16,
656
665
  columnGap,
657
666
  rowGap,
667
+ rowHeights,
658
668
  placements
659
669
  } = resolvedLayout;
660
670
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
671
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
661
672
  const gridStyle = {
662
673
  "--bento-columns": columns,
663
674
  "--bento-rows": calculatedRows,
675
+ "--bento-row-heights": rowTemplate,
664
676
  "--bento-gap": `${gap}px`,
665
677
  "--bento-column-gap": `${columnGap ?? gap}px`,
666
678
  "--bento-row-gap": `${rowGap ?? gap}px`,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/BentoGrid.tsx","../src/presets.ts","../src/BentoCard.tsx","../src/utils.ts","../src/hooks.ts"],"sourcesContent":["import React, { useMemo, useEffect } from \"react\";\nimport type {\n BentoGridProps,\n BentoLayoutConfig,\n BentoCardDefinition,\n CardDataMapping,\n CardWrapperProps,\n UnifiedBentoGridProps,\n UnifiedCardDefinition,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\nimport { BentoCard } from \"./BentoCard.js\";\nimport { validateLayout } from \"./utils.js\";\nimport { useResponsiveLayout } from \"./hooks.js\";\n\n/**\n * Default card wrapper - just uses BentoCard\n */\nconst DefaultCardWrapper: React.FC<CardWrapperProps> = ({\n children,\n className,\n style,\n}) => (\n <BentoCard className={className} style={style}>\n {children}\n </BentoCard>\n);\n\n/**\n * Default loading component - simple pulse animation\n */\nconst DefaultLoadingComponent: React.FC = () => (\n <div\n className=\"bento-card-loading\"\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 100,\n backgroundColor: \"var(--bento-loading-bg, rgba(128, 128, 128, 0.1))\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n animation: \"bento-pulse 1.5s ease-in-out infinite\",\n }}\n aria-label=\"Loading\"\n role=\"status\"\n />\n);\n\n/**\n * Inject base grid styles into the document\n * Uses CSS custom properties so Tailwind classes can override\n */\nfunction useGridStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-styles\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .bento-grid {\n display: grid;\n grid-template-columns: repeat(var(--bento-columns, 3), 1fr);\n grid-template-rows: repeat(var(--bento-rows, 2), minmax(0, 1fr));\n column-gap: var(--bento-column-gap, var(--bento-gap, 16px));\n row-gap: var(--bento-row-gap, var(--bento-gap, 16px));\n }\n .bento-cell {\n grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);\n grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Inject animation keyframes into the document\n */\nfunction useAnimationStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-animations\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n @keyframes bento-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n @keyframes bento-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n .bento-cell-animated {\n animation: bento-fade-in var(--bento-animation-duration, 300ms) ease-out;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Error boundary for individual cards\n * Resets when cardId or children change\n */\nclass CardErrorBoundary extends React.Component<\n {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n },\n { hasError: boolean; errorKey: string }\n> {\n constructor(props: {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n }) {\n super(props);\n this.state = {\n hasError: false,\n errorKey: `${props.cardId}-${props.resetKey ?? \"\"}`,\n };\n }\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n static getDerivedStateFromProps(\n props: { cardId: string; resetKey?: string | number },\n state: { errorKey: string },\n ) {\n const newKey = `${props.cardId}-${props.resetKey ?? \"\"}`;\n // Reset error state when key changes\n if (newKey !== state.errorKey) {\n return { hasError: false, errorKey: newKey };\n }\n return null;\n }\n\n componentDidCatch(error: Error) {\n this.props.onError?.(this.props.cardId, error);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div\n className=\"bento-card-error\"\n role=\"alert\"\n style={{ color: \"#ef4444\", padding: 16 }}\n >\n Failed to render card\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n/**\n * BentoGrid - A flexible, configurable bento grid layout system\n *\n * @example\n * ```tsx\n * <BentoGrid\n * layout=\"3x3\"\n * cards={[\n * { id: 'stats', component: StatsCard },\n * { id: 'chart', component: ChartCard },\n * ]}\n * data={myData}\n * dataMapping={[\n * { cardId: 'stats', propsSelector: (d) => ({ count: d.total }) },\n * { cardId: 'chart', propsSelector: (d) => ({ points: d.chartData }) },\n * ]}\n * />\n * ```\n */\nexport function BentoGrid<TData>({\n layout,\n cards,\n data,\n dataMapping,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n cellClassName,\n}: BentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = dataMapping.map((m) => m.cardId);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, dataMapping]);\n\n // Create lookup maps for cards and data mappings\n const cardMap = useMemo(() => {\n const map = new Map<string, BentoCardDefinition>();\n cards.forEach((card) => map.set(card.id, card));\n return map;\n }, [cards]);\n\n const dataMappingMap = useMemo(() => {\n const map = new Map<string, CardDataMapping<TData>>();\n dataMapping.forEach((mapping) => map.set(mapping.cardId, mapping));\n return map;\n }, [dataMapping]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"BentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!cards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n\n // Check for missing data mappings\n for (const placement of resolvedLayout.placements) {\n if (!dataMapping.some((m) => m.cardId === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" has no data mapping`,\n );\n }\n }\n }\n }, [resolvedLayout, cards, dataMapping]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n const mapping = dataMappingMap.get(placement.cardId);\n\n if (!card) {\n console.warn(`BentoGrid: Card \"${placement.cardId}\" not found`);\n return null;\n }\n\n // Get props from data mapping or empty object\n const cardProps = mapping ? mapping.propsSelector(data) : {};\n\n // Create a reset key for error boundary - changes when data changes\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n <CardComponent {...cardProps} />\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Check if a card should be visible based on its visibility config\n */\nfunction isCardVisible<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.visible === undefined) return true;\n if (typeof card.visible === \"function\") return card.visible(data);\n return card.visible;\n}\n\n/**\n * Check if a card is in loading state\n */\nfunction isCardLoading<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.loading === undefined) return false;\n if (typeof card.loading === \"function\") return card.loading(data);\n return card.loading;\n}\n\n/**\n * UnifiedBentoGrid - Cleaner API that combines cards and data mapping\n *\n * This is the preferred way to use BentoGrid. Instead of separate `cards` and\n * `dataMapping` arrays, you define everything in one place.\n *\n * @example\n * ```tsx\n * <UnifiedBentoGrid\n * layout=\"3x2\"\n * cards={[\n * {\n * id: 'stats',\n * component: StatsCard,\n * propsSelector: (d) => ({ count: d.total, label: 'Users' }),\n * colSpan: 2,\n * },\n * {\n * id: 'chart',\n * component: ChartCard,\n * propsSelector: (d) => ({ data: d.chartData }),\n * visible: (d) => d.chartData.length > 0,\n * loading: (d) => d.isLoading,\n * },\n * ]}\n * data={myData}\n * animated\n * />\n * ```\n */\nexport function UnifiedBentoGrid<TData>({\n layout,\n cards,\n data,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n loadingComponent: GlobalLoadingComponent = DefaultLoadingComponent,\n cellClassName,\n}: UnifiedBentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Filter visible cards\n const visibleCards = useMemo(() => {\n return cards.filter((card) => isCardVisible(card, data));\n }, [cards, data]);\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = visibleCards.map((c) => c.id);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, visibleCards]);\n\n // Create lookup map for cards\n const cardMap = useMemo(() => {\n const map = new Map<string, UnifiedCardDefinition<TData>>();\n visibleCards.forEach((card) => map.set(card.id, card));\n return map;\n }, [visibleCards]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"UnifiedBentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!visibleCards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n }\n }, [resolvedLayout, visibleCards]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n\n if (!card) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" not found`,\n );\n }\n return null;\n }\n\n // Check loading state\n const loading = isCardLoading(card, data);\n\n // Get props from card's propsSelector\n const cardProps = card.propsSelector(data);\n\n // Create a reset key for error boundary\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n const LoadingComponent =\n card.loadingComponent ?? GlobalLoadingComponent;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n {loading ? (\n <LoadingComponent />\n ) : (\n <CardComponent {...cardProps} />\n )}\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n","import type {\n PresetLayout,\n PresetLayoutName,\n BentoLayoutConfig,\n PresetSlotMapping,\n} from \"./types.js\";\n\n/**\n * Preset layout definitions\n * Users can use these by name instead of defining custom layouts\n */\nexport const PRESET_LAYOUTS: Record<PresetLayoutName, PresetLayout> = {\n \"2x2\": {\n name: \"2x2\",\n columns: 2,\n rows: 2,\n slots: [\n { name: \"top-left\", col: 1, row: 1 },\n { name: \"top-right\", col: 2, row: 1 },\n { name: \"bottom-left\", col: 1, row: 2 },\n { name: \"bottom-right\", col: 2, row: 2 },\n ],\n },\n \"3x2\": {\n name: \"3x2\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n ],\n },\n \"3x3\": {\n name: \"3x3\",\n columns: 3,\n rows: 3,\n slots: [\n { name: \"r1-c1\", col: 1, row: 1 },\n { name: \"r1-c2\", col: 2, row: 1 },\n { name: \"r1-c3\", col: 3, row: 1 },\n { name: \"r2-c1\", col: 1, row: 2 },\n { name: \"r2-c2\", col: 2, row: 2 },\n { name: \"r2-c3\", col: 3, row: 2 },\n { name: \"r3-c1\", col: 1, row: 3 },\n { name: \"r3-c2\", col: 2, row: 3 },\n { name: \"r3-c3\", col: 3, row: 3 },\n ],\n },\n \"4x2\": {\n name: \"4x2\",\n columns: 4,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"top-4\", col: 4, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n { name: \"bottom-4\", col: 4, row: 2 },\n ],\n },\n \"2x1-hero-left\": {\n name: \"2x1-hero-left\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"hero\", col: 1, row: 1, colSpan: 2, rowSpan: 2 },\n { name: \"side-top\", col: 3, row: 1 },\n { name: \"side-bottom\", col: 3, row: 2 },\n ],\n },\n \"2x1-hero-right\": {\n name: \"2x1-hero-right\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"side-top\", col: 1, row: 1 },\n { name: \"side-bottom\", col: 1, row: 2 },\n { name: \"hero\", col: 2, row: 1, colSpan: 2, rowSpan: 2 },\n ],\n },\n \"dashboard-9\": {\n name: \"dashboard-9\",\n columns: 3,\n rows: 4,\n slots: [\n { name: \"header-wide\", col: 1, row: 1, colSpan: 2 },\n { name: \"header-right\", col: 3, row: 1 },\n { name: \"hero\", col: 1, row: 2, rowSpan: 2 },\n { name: \"mid-center\", col: 2, row: 2 },\n { name: \"mid-right\", col: 3, row: 2 },\n { name: \"lower-center\", col: 2, row: 3 },\n { name: \"lower-right\", col: 3, row: 3 },\n { name: \"footer-left\", col: 1, row: 4 },\n { name: \"footer-wide\", col: 2, row: 4, colSpan: 2 },\n ],\n },\n};\n\n/**\n * Convert a preset name to a full layout config with card IDs\n * Supports both legacy array-based assignment and explicit slot mapping\n */\nexport function presetToLayout(\n presetName: PresetLayoutName,\n cardIdsOrMapping: string[] | PresetSlotMapping[],\n): BentoLayoutConfig {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n\n let placements;\n\n // Check if it's explicit slot mapping or legacy array\n if (\n cardIdsOrMapping.length > 0 &&\n typeof cardIdsOrMapping[0] === \"object\" &&\n \"slot\" in cardIdsOrMapping[0]\n ) {\n // Explicit slot mapping\n const slotMapping = cardIdsOrMapping as PresetSlotMapping[];\n placements = slotMapping\n .map((mapping) => {\n const slotIndex =\n typeof mapping.slot === \"number\"\n ? mapping.slot\n : preset.slots.findIndex((s) => s.name === mapping.slot);\n\n if (slotIndex === -1 || slotIndex >= preset.slots.length) {\n console.warn(\n `Preset \"${presetName}\": slot \"${mapping.slot}\" not found`,\n );\n return null;\n }\n\n const slot = preset.slots[slotIndex];\n return {\n cardId: mapping.cardId,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n };\n })\n .filter((p): p is NonNullable<typeof p> => p !== null);\n } else {\n // Legacy array-based assignment\n const cardIds = cardIdsOrMapping as string[];\n placements = preset.slots.map((slot, index) => ({\n cardId: cardIds[index] ?? `card-${index}`,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n }));\n }\n\n return {\n columns: preset.columns,\n rows: preset.rows,\n placements,\n };\n}\n\n/**\n * Get available slot names for a preset layout\n * Useful for discovering what slots are available\n */\nexport function getPresetSlotNames(presetName: PresetLayoutName): string[] {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n return preset.slots.map((s, i) => s.name ?? `slot-${i}`);\n}\n\n/**\n * Check if a value is a preset layout name\n */\nexport function isPresetName(value: unknown): value is PresetLayoutName {\n return typeof value === \"string\" && value in PRESET_LAYOUTS;\n}\n","import React from \"react\";\nimport type { BentoCardProps } from \"./types.js\";\n\n/**\n * Default card wrapper component\n * Provides basic styling - users can override with their own wrapper\n * Uses CSS custom properties for easy theming\n */\nexport const BentoCard: React.FC<BentoCardProps> = ({\n children,\n className = \"\",\n style,\n}) => (\n <div\n className={`bento-card ${className}`}\n style={{\n backgroundColor: \"var(--bento-card-bg, transparent)\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n padding: \"var(--bento-card-padding, 16px)\",\n border: \"var(--bento-card-border, 1px solid rgba(128, 128, 128, 0.2))\",\n height: \"100%\",\n boxSizing: \"border-box\",\n ...style,\n }}\n >\n {children}\n </div>\n);\n","import type { BentoLayoutConfig, CardPlacement } from \"./types.js\";\n\n/**\n * Create a simple grid layout where cards are placed sequentially\n * Useful for quick prototyping\n *\n * @example\n * ```ts\n * const layout = createSimpleLayout(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]);\n * // Creates a 3-column grid with cards placed left-to-right, top-to-bottom\n * ```\n */\nexport function createSimpleLayout(\n columns: number,\n cardIds: string[],\n gap?: number,\n): BentoLayoutConfig {\n const placements: CardPlacement[] = cardIds.map((cardId, index) => ({\n cardId,\n col: (index % columns) + 1,\n row: Math.floor(index / columns) + 1,\n }));\n\n return {\n columns,\n gap,\n placements,\n };\n}\n\n/**\n * Layout builder for fluent API\n *\n * @example\n * ```ts\n * const layout = layoutBuilder(3)\n * .gap(16)\n * .columnGap(20)\n * .rowGap(12)\n * .place(\"hero\", 1, 1, { colSpan: 2, rowSpan: 2 })\n * .place(\"stats\", 3, 1)\n * .place(\"chart\", 3, 2)\n * .build();\n * ```\n */\nexport function layoutBuilder(columns: number) {\n const config: BentoLayoutConfig = {\n columns,\n placements: [],\n };\n\n const builder = {\n gap(value: number) {\n config.gap = value;\n return builder;\n },\n columnGap(value: number) {\n config.columnGap = value;\n return builder;\n },\n rowGap(value: number) {\n config.rowGap = value;\n return builder;\n },\n rows(value: number) {\n config.rows = value;\n return builder;\n },\n place(\n cardId: string,\n col: number,\n row: number,\n options?: { colSpan?: number; rowSpan?: number },\n ) {\n config.placements.push({\n cardId,\n col,\n row,\n ...options,\n });\n return builder;\n },\n build(): BentoLayoutConfig {\n return config;\n },\n };\n\n return builder;\n}\n\n/**\n * Validate a layout configuration\n * Returns array of validation errors (empty if valid)\n */\nexport function validateLayout(layout: BentoLayoutConfig): string[] {\n const errors: string[] = [];\n\n if (layout.columns < 1) {\n errors.push(\"columns must be at least 1\");\n }\n\n if (layout.rows !== undefined && layout.rows < 1) {\n errors.push(\"rows must be at least 1\");\n }\n\n if (layout.gap !== undefined && layout.gap < 0) {\n errors.push(\"gap cannot be negative\");\n }\n\n const occupied = new Set<string>();\n\n for (const placement of layout.placements) {\n const colSpan = placement.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? 1;\n\n // Check bounds\n if (placement.col < 1 || placement.col + colSpan - 1 > layout.columns) {\n errors.push(\n `Card \"${placement.cardId}\" exceeds column bounds (col: ${placement.col}, span: ${colSpan})`,\n );\n }\n\n if (placement.row < 1) {\n errors.push(\n `Card \"${placement.cardId}\" has invalid row: ${placement.row}`,\n );\n }\n\n // Check overlaps\n for (let c = placement.col; c < placement.col + colSpan; c++) {\n for (let r = placement.row; r < placement.row + rowSpan; r++) {\n const key = `${c},${r}`;\n if (occupied.has(key)) {\n errors.push(\n `Card \"${placement.cardId}\" overlaps at position (${c}, ${r})`,\n );\n }\n occupied.add(key);\n }\n }\n }\n\n return errors;\n}\n","import { useMemo, useRef, useState, useEffect, useCallback } from \"react\";\nimport type {\n BentoCardDefinition,\n CardDataMapping,\n BentoLayoutConfig,\n PresetLayoutName,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\n\n/**\n * Deep comparison for stable memoization of object inputs\n */\nfunction useStableValue<T>(value: T): T {\n const ref = useRef<T>(value);\n const prevJson = useRef<string>(\"\");\n\n // Compare by serializing - works for our use case of simple config objects\n // For components, we compare by reference using a custom replacer\n const json = JSON.stringify(value, (key, val) => {\n if (typeof val === \"function\") {\n return val.toString();\n }\n return val;\n });\n\n if (json !== prevJson.current) {\n ref.current = value;\n prevJson.current = json;\n }\n\n return ref.current;\n}\n\n/**\n * Check if a layout config is a responsive config\n */\nexport function isResponsiveConfig(\n layout: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): layout is ResponsiveLayoutConfig {\n return (\n typeof layout === \"object\" && \"default\" in layout && \"breakpoints\" in layout\n );\n}\n\n/**\n * Hook to handle responsive layouts based on viewport width\n * Returns the appropriate layout for the current viewport\n *\n * @example\n * ```tsx\n * const layout = useResponsiveLayout({\n * default: \"2x2\",\n * breakpoints: [\n * { minWidth: 768, layout: \"3x2\" },\n * { minWidth: 1024, layout: \"4x2\" },\n * ],\n * });\n * ```\n */\nexport function useResponsiveLayout(\n config: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): BentoLayoutConfig | PresetLayoutName {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const handleResize = () => setWidth(window.innerWidth);\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return useMemo(() => {\n if (!isResponsiveConfig(config)) {\n return config;\n }\n\n // Sort breakpoints by minWidth descending to find the largest matching one\n const sortedBreakpoints = [...config.breakpoints].sort(\n (a, b) => b.minWidth - a.minWidth,\n );\n\n for (const bp of sortedBreakpoints) {\n if (width >= bp.minWidth) {\n return bp.layout;\n }\n }\n\n return config.default;\n }, [config, width]);\n}\n\n/**\n * Hook to track window width with debouncing\n */\nexport function useWindowWidth(debounceMs = 100): number {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const handleResize = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => setWidth(window.innerWidth), debounceMs);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [debounceMs]);\n\n return width;\n}\n\n/**\n * Hook to create card definitions from an object map\n * Provides a cleaner API for defining cards\n *\n * @example\n * ```tsx\n * const cards = useCardDefinitions({\n * stats: { component: StatsCard, colSpan: 2 },\n * chart: { component: ChartCard },\n * list: { component: ListCard, rowSpan: 2 },\n * });\n * ```\n */\nexport function useCardDefinitions<\n T extends Record<string, Omit<BentoCardDefinition<any>, \"id\">>,\n>(definitions: T): BentoCardDefinition<any>[] {\n const stableDefinitions = useStableValue(definitions);\n\n return useMemo(() => {\n return Object.entries(stableDefinitions).map(([id, def]) => ({\n id,\n ...def,\n }));\n }, [stableDefinitions]);\n}\n\n/**\n * Hook to create data mappings from an object map\n * Provides a cleaner API for mapping data to cards\n *\n * @example\n * ```tsx\n * const dataMapping = useDataMapping<MyDataType>({\n * stats: (data) => ({ count: data.total, label: 'Items' }),\n * chart: (data) => ({ points: data.chartData }),\n * });\n * ```\n */\nexport function useDataMapping<TData>(\n mappings: Record<string, (data: TData) => Record<string, unknown>>,\n): CardDataMapping<TData>[] {\n const stableMappings = useStableValue(mappings);\n\n return useMemo(() => {\n return Object.entries(stableMappings).map(([cardId, propsSelector]) => ({\n cardId,\n propsSelector,\n }));\n }, [stableMappings]);\n}\n\n/**\n * Hook to create a layout configuration\n * Handles both preset names and custom configs\n *\n * @example\n * ```tsx\n * // Using preset\n * const layout = useLayout(\"3x3\", [\"stats\", \"chart\", \"list\", ...]);\n *\n * // Using custom config\n * const layout = useLayout({\n * columns: 3,\n * placements: [\n * { cardId: \"stats\", col: 1, row: 1, colSpan: 2 },\n * { cardId: \"chart\", col: 3, row: 1 },\n * ]\n * });\n * ```\n */\nexport function useLayout(\n config: PresetLayoutName | BentoLayoutConfig,\n cardIds?: string[],\n): BentoLayoutConfig {\n return useMemo(() => {\n if (isPresetName(config)) {\n if (!cardIds) {\n throw new Error(\"cardIds required when using preset layout name\");\n }\n return presetToLayout(config, cardIds);\n }\n return config;\n }, [config, cardIds]);\n}\n"],"mappings":"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","names":["useMemo","useEffect","jsx","useEffect","useMemo"]}
1
+ {"version":3,"sources":["../src/BentoGrid.tsx","../src/presets.ts","../src/BentoCard.tsx","../src/utils.ts","../src/hooks.ts"],"sourcesContent":["import React, { useMemo, useEffect } from \"react\";\nimport type {\n BentoGridProps,\n BentoLayoutConfig,\n BentoCardDefinition,\n CardDataMapping,\n CardWrapperProps,\n UnifiedBentoGridProps,\n UnifiedCardDefinition,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\nimport { BentoCard } from \"./BentoCard.js\";\nimport { validateLayout } from \"./utils.js\";\nimport { useResponsiveLayout } from \"./hooks.js\";\n\n/**\n * Default card wrapper - just uses BentoCard\n */\nconst DefaultCardWrapper: React.FC<CardWrapperProps> = ({\n children,\n className,\n style,\n}) => (\n <BentoCard className={className} style={style}>\n {children}\n </BentoCard>\n);\n\n/**\n * Default loading component - simple pulse animation\n */\nconst DefaultLoadingComponent: React.FC = () => (\n <div\n className=\"bento-card-loading\"\n style={{\n width: \"100%\",\n height: \"100%\",\n minHeight: 100,\n backgroundColor: \"var(--bento-loading-bg, rgba(128, 128, 128, 0.1))\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n animation: \"bento-pulse 1.5s ease-in-out infinite\",\n }}\n aria-label=\"Loading\"\n role=\"status\"\n />\n);\n\n/**\n * Inject base grid styles into the document\n * Uses CSS custom properties so Tailwind classes can override\n */\nfunction useGridStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-styles\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .bento-grid {\n display: grid;\n grid-template-columns: repeat(var(--bento-columns, 3), 1fr);\n grid-template-rows: var(--bento-row-heights, repeat(var(--bento-rows, 2), minmax(0, 1fr)));\n column-gap: var(--bento-column-gap, var(--bento-gap, 16px));\n row-gap: var(--bento-row-gap, var(--bento-gap, 16px));\n }\n .bento-cell {\n grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);\n grid-row: var(--bento-row, 1) / span var(--bento-row-span, 1);\n min-height: 0;\n overflow: hidden;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Inject animation keyframes into the document\n */\nfunction useAnimationStyles() {\n useEffect(() => {\n if (typeof document === \"undefined\") return;\n\n const styleId = \"bento-grid-animations\";\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n @keyframes bento-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n @keyframes bento-fade-in {\n from { opacity: 0; transform: scale(0.95); }\n to { opacity: 1; transform: scale(1); }\n }\n .bento-cell-animated {\n animation: bento-fade-in var(--bento-animation-duration, 300ms) ease-out;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\n/**\n * Error boundary for individual cards\n * Resets when cardId or children change\n */\nclass CardErrorBoundary extends React.Component<\n {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n },\n { hasError: boolean; errorKey: string }\n> {\n constructor(props: {\n cardId: string;\n onError?: (cardId: string, error: Error) => void;\n children: React.ReactNode;\n resetKey?: string | number;\n }) {\n super(props);\n this.state = {\n hasError: false,\n errorKey: `${props.cardId}-${props.resetKey ?? \"\"}`,\n };\n }\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n static getDerivedStateFromProps(\n props: { cardId: string; resetKey?: string | number },\n state: { errorKey: string },\n ) {\n const newKey = `${props.cardId}-${props.resetKey ?? \"\"}`;\n // Reset error state when key changes\n if (newKey !== state.errorKey) {\n return { hasError: false, errorKey: newKey };\n }\n return null;\n }\n\n componentDidCatch(error: Error) {\n this.props.onError?.(this.props.cardId, error);\n }\n\n render() {\n if (this.state.hasError) {\n return (\n <div\n className=\"bento-card-error\"\n role=\"alert\"\n style={{ color: \"#ef4444\", padding: 16 }}\n >\n Failed to render card\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n/**\n * BentoGrid - A flexible, configurable bento grid layout system\n *\n * @example\n * ```tsx\n * <BentoGrid\n * layout=\"3x3\"\n * cards={[\n * { id: 'stats', component: StatsCard },\n * { id: 'chart', component: ChartCard },\n * ]}\n * data={myData}\n * dataMapping={[\n * { cardId: 'stats', propsSelector: (d) => ({ count: d.total }) },\n * { cardId: 'chart', propsSelector: (d) => ({ points: d.chartData }) },\n * ]}\n * />\n * ```\n */\nexport function BentoGrid<TData>({\n layout,\n cards,\n data,\n dataMapping,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n cellClassName,\n}: BentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = dataMapping.map((m) => m.cardId);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, dataMapping]);\n\n // Create lookup maps for cards and data mappings\n const cardMap = useMemo(() => {\n const map = new Map<string, BentoCardDefinition>();\n cards.forEach((card) => map.set(card.id, card));\n return map;\n }, [cards]);\n\n const dataMappingMap = useMemo(() => {\n const map = new Map<string, CardDataMapping<TData>>();\n dataMapping.forEach((mapping) => map.set(mapping.cardId, mapping));\n return map;\n }, [dataMapping]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"BentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!cards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n\n // Check for missing data mappings\n for (const placement of resolvedLayout.placements) {\n if (!dataMapping.some((m) => m.cardId === placement.cardId)) {\n console.warn(\n `BentoGrid: Card \"${placement.cardId}\" has no data mapping`,\n );\n }\n }\n }\n }, [resolvedLayout, cards, dataMapping]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n rowHeights,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Compute row template: use custom rowHeights if provided, otherwise equal 1fr rows\n const rowTemplate = rowHeights\n ? rowHeights.join(\" \")\n : `repeat(${calculatedRows}, minmax(0, 1fr))`;\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-row-heights\": rowTemplate,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n const mapping = dataMappingMap.get(placement.cardId);\n\n if (!card) {\n console.warn(`BentoGrid: Card \"${placement.cardId}\" not found`);\n return null;\n }\n\n // Get props from data mapping or empty object\n const cardProps = mapping ? mapping.propsSelector(data) : {};\n\n // Create a reset key for error boundary - changes when data changes\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n <CardComponent {...cardProps} />\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * Check if a card should be visible based on its visibility config\n */\nfunction isCardVisible<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.visible === undefined) return true;\n if (typeof card.visible === \"function\") return card.visible(data);\n return card.visible;\n}\n\n/**\n * Check if a card is in loading state\n */\nfunction isCardLoading<TData>(\n card: UnifiedCardDefinition<TData>,\n data: TData,\n): boolean {\n if (card.loading === undefined) return false;\n if (typeof card.loading === \"function\") return card.loading(data);\n return card.loading;\n}\n\n/**\n * UnifiedBentoGrid - Cleaner API that combines cards and data mapping\n *\n * This is the preferred way to use BentoGrid. Instead of separate `cards` and\n * `dataMapping` arrays, you define everything in one place.\n *\n * @example\n * ```tsx\n * <UnifiedBentoGrid\n * layout=\"3x2\"\n * cards={[\n * {\n * id: 'stats',\n * component: StatsCard,\n * propsSelector: (d) => ({ count: d.total, label: 'Users' }),\n * colSpan: 2,\n * },\n * {\n * id: 'chart',\n * component: ChartCard,\n * propsSelector: (d) => ({ data: d.chartData }),\n * visible: (d) => d.chartData.length > 0,\n * loading: (d) => d.isLoading,\n * },\n * ]}\n * data={myData}\n * animated\n * />\n * ```\n */\nexport function UnifiedBentoGrid<TData>({\n layout,\n cards,\n data,\n className = \"\",\n style,\n cardWrapper,\n onCardError,\n ariaLabel,\n ariaLabelledBy,\n animated = false,\n animationDuration = 300,\n loadingComponent: GlobalLoadingComponent = DefaultLoadingComponent,\n cellClassName,\n}: UnifiedBentoGridProps<TData>): React.ReactElement {\n // Inject styles\n useGridStyles();\n useAnimationStyles();\n\n // Handle responsive layouts\n const responsiveLayout = useResponsiveLayout(layout);\n\n // Choose card wrapper\n const CardWrapper = cardWrapper ?? DefaultCardWrapper;\n\n // Filter visible cards\n const visibleCards = useMemo(() => {\n return cards.filter((card) => isCardVisible(card, data));\n }, [cards, data]);\n\n // Resolve layout config from preset or use directly\n const resolvedLayout = useMemo((): BentoLayoutConfig => {\n if (isPresetName(responsiveLayout)) {\n const cardIds = visibleCards.map((c) => c.id);\n return presetToLayout(responsiveLayout, cardIds);\n }\n return responsiveLayout as BentoLayoutConfig;\n }, [responsiveLayout, visibleCards]);\n\n // Create lookup map for cards\n const cardMap = useMemo(() => {\n const map = new Map<string, UnifiedCardDefinition<TData>>();\n visibleCards.forEach((card) => map.set(card.id, card));\n return map;\n }, [visibleCards]);\n\n // Validate layout in development\n useMemo(() => {\n if (process.env.NODE_ENV !== \"production\") {\n const errors = validateLayout(resolvedLayout);\n if (errors.length > 0) {\n console.warn(\"UnifiedBentoGrid layout validation errors:\", errors);\n }\n\n // Check for missing card definitions\n for (const placement of resolvedLayout.placements) {\n if (!visibleCards.some((c) => c.id === placement.cardId)) {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" in layout but not in cards array`,\n );\n }\n }\n }\n }, [resolvedLayout, visibleCards]);\n\n // Calculate grid dimensions\n const {\n columns,\n rows,\n gap = 16,\n columnGap,\n rowGap,\n rowHeights,\n placements,\n } = resolvedLayout;\n const calculatedRows =\n rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);\n\n // Compute row template: use custom rowHeights if provided, otherwise equal 1fr rows\n const rowTemplate = rowHeights\n ? rowHeights.join(\" \")\n : `repeat(${calculatedRows}, minmax(0, 1fr))`;\n\n // Grid uses CSS custom properties - Tailwind classes can override the CSS rules\n const gridStyle: React.CSSProperties = {\n \"--bento-columns\": columns,\n \"--bento-rows\": calculatedRows,\n \"--bento-row-heights\": rowTemplate,\n \"--bento-gap\": `${gap}px`,\n \"--bento-column-gap\": `${columnGap ?? gap}px`,\n \"--bento-row-gap\": `${rowGap ?? gap}px`,\n ...(animated && { \"--bento-animation-duration\": `${animationDuration}ms` }),\n ...style,\n } as React.CSSProperties;\n\n // Helper to get cell class name\n const getCellClassName = (cardId: string) => {\n const baseClass = `bento-cell ${animated ? \"bento-cell-animated\" : \"\"}`;\n if (!cellClassName) return baseClass;\n if (typeof cellClassName === \"function\")\n return `${baseClass} ${cellClassName(cardId)}`;\n return `${baseClass} ${cellClassName}`;\n };\n\n return (\n <div\n className={`bento-grid ${className}`}\n style={gridStyle}\n role=\"region\"\n aria-label={ariaLabel ?? (ariaLabelledBy ? undefined : \"Dashboard grid\")}\n aria-labelledby={ariaLabelledBy}\n >\n {placements.map((placement) => {\n const card = cardMap.get(placement.cardId);\n\n if (!card) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n `UnifiedBentoGrid: Card \"${placement.cardId}\" not found`,\n );\n }\n return null;\n }\n\n // Check loading state\n const loading = isCardLoading(card, data);\n\n // Get props from card's propsSelector\n const cardProps = card.propsSelector(data);\n\n // Create a reset key for error boundary\n const resetKey = JSON.stringify(cardProps);\n\n // Calculate span (placement overrides card defaults)\n const colSpan = placement.colSpan ?? card.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? card.rowSpan ?? 1;\n\n // Cell uses CSS custom properties for positioning\n const cellStyle: React.CSSProperties = {\n \"--bento-col\": placement.col,\n \"--bento-row\": placement.row,\n \"--bento-col-span\": colSpan,\n \"--bento-row-span\": rowSpan,\n } as React.CSSProperties;\n\n const CardComponent = card.component;\n const LoadingComponent =\n card.loadingComponent ?? GlobalLoadingComponent;\n\n return (\n <div\n key={`${placement.cardId}-${placement.col}-${placement.row}`}\n className={getCellClassName(placement.cardId)}\n style={cellStyle}\n data-card-id={placement.cardId}\n >\n <CardErrorBoundary\n cardId={placement.cardId}\n onError={onCardError}\n resetKey={resetKey}\n >\n <CardWrapper cardId={placement.cardId}>\n {loading ? (\n <LoadingComponent />\n ) : (\n <CardComponent {...cardProps} />\n )}\n </CardWrapper>\n </CardErrorBoundary>\n </div>\n );\n })}\n </div>\n );\n}\n","import type {\n PresetLayout,\n PresetLayoutName,\n BentoLayoutConfig,\n PresetSlotMapping,\n} from \"./types.js\";\n\n/**\n * Preset layout definitions\n * Users can use these by name instead of defining custom layouts\n */\nexport const PRESET_LAYOUTS: Record<PresetLayoutName, PresetLayout> = {\n \"2x2\": {\n name: \"2x2\",\n columns: 2,\n rows: 2,\n slots: [\n { name: \"top-left\", col: 1, row: 1 },\n { name: \"top-right\", col: 2, row: 1 },\n { name: \"bottom-left\", col: 1, row: 2 },\n { name: \"bottom-right\", col: 2, row: 2 },\n ],\n },\n \"3x2\": {\n name: \"3x2\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n ],\n },\n \"3x3\": {\n name: \"3x3\",\n columns: 3,\n rows: 3,\n slots: [\n { name: \"r1-c1\", col: 1, row: 1 },\n { name: \"r1-c2\", col: 2, row: 1 },\n { name: \"r1-c3\", col: 3, row: 1 },\n { name: \"r2-c1\", col: 1, row: 2 },\n { name: \"r2-c2\", col: 2, row: 2 },\n { name: \"r2-c3\", col: 3, row: 2 },\n { name: \"r3-c1\", col: 1, row: 3 },\n { name: \"r3-c2\", col: 2, row: 3 },\n { name: \"r3-c3\", col: 3, row: 3 },\n ],\n },\n \"4x2\": {\n name: \"4x2\",\n columns: 4,\n rows: 2,\n slots: [\n { name: \"top-1\", col: 1, row: 1 },\n { name: \"top-2\", col: 2, row: 1 },\n { name: \"top-3\", col: 3, row: 1 },\n { name: \"top-4\", col: 4, row: 1 },\n { name: \"bottom-1\", col: 1, row: 2 },\n { name: \"bottom-2\", col: 2, row: 2 },\n { name: \"bottom-3\", col: 3, row: 2 },\n { name: \"bottom-4\", col: 4, row: 2 },\n ],\n },\n \"2x1-hero-left\": {\n name: \"2x1-hero-left\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"hero\", col: 1, row: 1, colSpan: 2, rowSpan: 2 },\n { name: \"side-top\", col: 3, row: 1 },\n { name: \"side-bottom\", col: 3, row: 2 },\n ],\n },\n \"2x1-hero-right\": {\n name: \"2x1-hero-right\",\n columns: 3,\n rows: 2,\n slots: [\n { name: \"side-top\", col: 1, row: 1 },\n { name: \"side-bottom\", col: 1, row: 2 },\n { name: \"hero\", col: 2, row: 1, colSpan: 2, rowSpan: 2 },\n ],\n },\n \"dashboard-9\": {\n name: \"dashboard-9\",\n columns: 3,\n rows: 4,\n slots: [\n { name: \"header-wide\", col: 1, row: 1, colSpan: 2 },\n { name: \"header-right\", col: 3, row: 1 },\n { name: \"hero\", col: 1, row: 2, rowSpan: 2 },\n { name: \"mid-center\", col: 2, row: 2 },\n { name: \"mid-right\", col: 3, row: 2 },\n { name: \"lower-center\", col: 2, row: 3 },\n { name: \"lower-right\", col: 3, row: 3 },\n { name: \"footer-left\", col: 1, row: 4 },\n { name: \"footer-wide\", col: 2, row: 4, colSpan: 2 },\n ],\n },\n};\n\n/**\n * Convert a preset name to a full layout config with card IDs\n * Supports both legacy array-based assignment and explicit slot mapping\n */\nexport function presetToLayout(\n presetName: PresetLayoutName,\n cardIdsOrMapping: string[] | PresetSlotMapping[],\n): BentoLayoutConfig {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n\n let placements;\n\n // Check if it's explicit slot mapping or legacy array\n if (\n cardIdsOrMapping.length > 0 &&\n typeof cardIdsOrMapping[0] === \"object\" &&\n \"slot\" in cardIdsOrMapping[0]\n ) {\n // Explicit slot mapping\n const slotMapping = cardIdsOrMapping as PresetSlotMapping[];\n placements = slotMapping\n .map((mapping) => {\n const slotIndex =\n typeof mapping.slot === \"number\"\n ? mapping.slot\n : preset.slots.findIndex((s) => s.name === mapping.slot);\n\n if (slotIndex === -1 || slotIndex >= preset.slots.length) {\n console.warn(\n `Preset \"${presetName}\": slot \"${mapping.slot}\" not found`,\n );\n return null;\n }\n\n const slot = preset.slots[slotIndex];\n return {\n cardId: mapping.cardId,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n };\n })\n .filter((p): p is NonNullable<typeof p> => p !== null);\n } else {\n // Legacy array-based assignment\n const cardIds = cardIdsOrMapping as string[];\n placements = preset.slots.map((slot, index) => ({\n cardId: cardIds[index] ?? `card-${index}`,\n col: slot.col,\n row: slot.row,\n colSpan: slot.colSpan,\n rowSpan: slot.rowSpan,\n }));\n }\n\n return {\n columns: preset.columns,\n rows: preset.rows,\n placements,\n };\n}\n\n/**\n * Get available slot names for a preset layout\n * Useful for discovering what slots are available\n */\nexport function getPresetSlotNames(presetName: PresetLayoutName): string[] {\n const preset = PRESET_LAYOUTS[presetName];\n if (!preset) {\n throw new Error(`Unknown preset layout: ${presetName}`);\n }\n return preset.slots.map((s, i) => s.name ?? `slot-${i}`);\n}\n\n/**\n * Check if a value is a preset layout name\n */\nexport function isPresetName(value: unknown): value is PresetLayoutName {\n return typeof value === \"string\" && value in PRESET_LAYOUTS;\n}\n","import React from \"react\";\nimport type { BentoCardProps } from \"./types.js\";\n\n/**\n * Default card wrapper component\n * Provides basic styling - users can override with their own wrapper\n * Uses CSS custom properties for easy theming\n */\nexport const BentoCard: React.FC<BentoCardProps> = ({\n children,\n className = \"\",\n style,\n}) => (\n <div\n className={`bento-card ${className}`}\n style={{\n backgroundColor: \"var(--bento-card-bg, transparent)\",\n borderRadius: \"var(--bento-card-radius, 12px)\",\n padding: \"var(--bento-card-padding, 16px)\",\n border: \"var(--bento-card-border, 1px solid rgba(128, 128, 128, 0.2))\",\n height: \"100%\",\n boxSizing: \"border-box\",\n ...style,\n }}\n >\n {children}\n </div>\n);\n","import type { BentoLayoutConfig, CardPlacement } from \"./types.js\";\n\n/**\n * Create a simple grid layout where cards are placed sequentially\n * Useful for quick prototyping\n *\n * @example\n * ```ts\n * const layout = createSimpleLayout(3, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\"]);\n * // Creates a 3-column grid with cards placed left-to-right, top-to-bottom\n * ```\n */\nexport function createSimpleLayout(\n columns: number,\n cardIds: string[],\n gap?: number,\n): BentoLayoutConfig {\n const placements: CardPlacement[] = cardIds.map((cardId, index) => ({\n cardId,\n col: (index % columns) + 1,\n row: Math.floor(index / columns) + 1,\n }));\n\n return {\n columns,\n gap,\n placements,\n };\n}\n\n/**\n * Layout builder for fluent API\n *\n * @example\n * ```ts\n * const layout = layoutBuilder(3)\n * .gap(16)\n * .columnGap(20)\n * .rowGap(12)\n * .place(\"hero\", 1, 1, { colSpan: 2, rowSpan: 2 })\n * .place(\"stats\", 3, 1)\n * .place(\"chart\", 3, 2)\n * .build();\n * ```\n */\nexport function layoutBuilder(columns: number) {\n const config: BentoLayoutConfig = {\n columns,\n placements: [],\n };\n\n const builder = {\n gap(value: number) {\n config.gap = value;\n return builder;\n },\n columnGap(value: number) {\n config.columnGap = value;\n return builder;\n },\n rowGap(value: number) {\n config.rowGap = value;\n return builder;\n },\n rows(value: number) {\n config.rows = value;\n return builder;\n },\n rowHeights(heights: string[]) {\n config.rowHeights = heights;\n return builder;\n },\n place(\n cardId: string,\n col: number,\n row: number,\n options?: { colSpan?: number; rowSpan?: number },\n ) {\n config.placements.push({\n cardId,\n col,\n row,\n ...options,\n });\n return builder;\n },\n build(): BentoLayoutConfig {\n return config;\n },\n };\n\n return builder;\n}\n\n/**\n * Validate a layout configuration\n * Returns array of validation errors (empty if valid)\n */\nexport function validateLayout(layout: BentoLayoutConfig): string[] {\n const errors: string[] = [];\n\n if (layout.columns < 1) {\n errors.push(\"columns must be at least 1\");\n }\n\n if (layout.rows !== undefined && layout.rows < 1) {\n errors.push(\"rows must be at least 1\");\n }\n\n if (layout.gap !== undefined && layout.gap < 0) {\n errors.push(\"gap cannot be negative\");\n }\n\n const occupied = new Set<string>();\n\n for (const placement of layout.placements) {\n const colSpan = placement.colSpan ?? 1;\n const rowSpan = placement.rowSpan ?? 1;\n\n // Check bounds\n if (placement.col < 1 || placement.col + colSpan - 1 > layout.columns) {\n errors.push(\n `Card \"${placement.cardId}\" exceeds column bounds (col: ${placement.col}, span: ${colSpan})`,\n );\n }\n\n if (placement.row < 1) {\n errors.push(\n `Card \"${placement.cardId}\" has invalid row: ${placement.row}`,\n );\n }\n\n // Check overlaps\n for (let c = placement.col; c < placement.col + colSpan; c++) {\n for (let r = placement.row; r < placement.row + rowSpan; r++) {\n const key = `${c},${r}`;\n if (occupied.has(key)) {\n errors.push(\n `Card \"${placement.cardId}\" overlaps at position (${c}, ${r})`,\n );\n }\n occupied.add(key);\n }\n }\n }\n\n return errors;\n}\n","import { useMemo, useRef, useState, useEffect, useCallback } from \"react\";\nimport type {\n BentoCardDefinition,\n CardDataMapping,\n BentoLayoutConfig,\n PresetLayoutName,\n ResponsiveLayoutConfig,\n BreakpointConfig,\n} from \"./types.js\";\nimport { isPresetName, presetToLayout } from \"./presets.js\";\n\n/**\n * Deep comparison for stable memoization of object inputs\n */\nfunction useStableValue<T>(value: T): T {\n const ref = useRef<T>(value);\n const prevJson = useRef<string>(\"\");\n\n // Compare by serializing - works for our use case of simple config objects\n // For components, we compare by reference using a custom replacer\n const json = JSON.stringify(value, (key, val) => {\n if (typeof val === \"function\") {\n return val.toString();\n }\n return val;\n });\n\n if (json !== prevJson.current) {\n ref.current = value;\n prevJson.current = json;\n }\n\n return ref.current;\n}\n\n/**\n * Check if a layout config is a responsive config\n */\nexport function isResponsiveConfig(\n layout: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): layout is ResponsiveLayoutConfig {\n return (\n typeof layout === \"object\" && \"default\" in layout && \"breakpoints\" in layout\n );\n}\n\n/**\n * Hook to handle responsive layouts based on viewport width\n * Returns the appropriate layout for the current viewport\n *\n * @example\n * ```tsx\n * const layout = useResponsiveLayout({\n * default: \"2x2\",\n * breakpoints: [\n * { minWidth: 768, layout: \"3x2\" },\n * { minWidth: 1024, layout: \"4x2\" },\n * ],\n * });\n * ```\n */\nexport function useResponsiveLayout(\n config: BentoLayoutConfig | PresetLayoutName | ResponsiveLayoutConfig,\n): BentoLayoutConfig | PresetLayoutName {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n const handleResize = () => setWidth(window.innerWidth);\n window.addEventListener(\"resize\", handleResize);\n return () => window.removeEventListener(\"resize\", handleResize);\n }, []);\n\n return useMemo(() => {\n if (!isResponsiveConfig(config)) {\n return config;\n }\n\n // Sort breakpoints by minWidth descending to find the largest matching one\n const sortedBreakpoints = [...config.breakpoints].sort(\n (a, b) => b.minWidth - a.minWidth,\n );\n\n for (const bp of sortedBreakpoints) {\n if (width >= bp.minWidth) {\n return bp.layout;\n }\n }\n\n return config.default;\n }, [config, width]);\n}\n\n/**\n * Hook to track window width with debouncing\n */\nexport function useWindowWidth(debounceMs = 100): number {\n const [width, setWidth] = useState(() =>\n typeof window !== \"undefined\" ? window.innerWidth : 0,\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n let timeoutId: ReturnType<typeof setTimeout>;\n const handleResize = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => setWidth(window.innerWidth), debounceMs);\n };\n\n window.addEventListener(\"resize\", handleResize);\n return () => {\n clearTimeout(timeoutId);\n window.removeEventListener(\"resize\", handleResize);\n };\n }, [debounceMs]);\n\n return width;\n}\n\n/**\n * Hook to create card definitions from an object map\n * Provides a cleaner API for defining cards\n *\n * @example\n * ```tsx\n * const cards = useCardDefinitions({\n * stats: { component: StatsCard, colSpan: 2 },\n * chart: { component: ChartCard },\n * list: { component: ListCard, rowSpan: 2 },\n * });\n * ```\n */\nexport function useCardDefinitions<\n T extends Record<string, Omit<BentoCardDefinition<any>, \"id\">>,\n>(definitions: T): BentoCardDefinition<any>[] {\n const stableDefinitions = useStableValue(definitions);\n\n return useMemo(() => {\n return Object.entries(stableDefinitions).map(([id, def]) => ({\n id,\n ...def,\n }));\n }, [stableDefinitions]);\n}\n\n/**\n * Hook to create data mappings from an object map\n * Provides a cleaner API for mapping data to cards\n *\n * @example\n * ```tsx\n * const dataMapping = useDataMapping<MyDataType>({\n * stats: (data) => ({ count: data.total, label: 'Items' }),\n * chart: (data) => ({ points: data.chartData }),\n * });\n * ```\n */\nexport function useDataMapping<TData>(\n mappings: Record<string, (data: TData) => Record<string, unknown>>,\n): CardDataMapping<TData>[] {\n const stableMappings = useStableValue(mappings);\n\n return useMemo(() => {\n return Object.entries(stableMappings).map(([cardId, propsSelector]) => ({\n cardId,\n propsSelector,\n }));\n }, [stableMappings]);\n}\n\n/**\n * Hook to create a layout configuration\n * Handles both preset names and custom configs\n *\n * @example\n * ```tsx\n * // Using preset\n * const layout = useLayout(\"3x3\", [\"stats\", \"chart\", \"list\", ...]);\n *\n * // Using custom config\n * const layout = useLayout({\n * columns: 3,\n * placements: [\n * { cardId: \"stats\", col: 1, row: 1, colSpan: 2 },\n * { cardId: \"chart\", col: 3, row: 1 },\n * ]\n * });\n * ```\n */\nexport function useLayout(\n config: PresetLayoutName | BentoLayoutConfig,\n cardIds?: string[],\n): BentoLayoutConfig {\n return useMemo(() => {\n if (isPresetName(config)) {\n if (!cardIds) {\n throw new Error(\"cardIds required when using preset layout name\");\n }\n return presetToLayout(config, cardIds);\n }\n return config;\n }, [config, cardIds]);\n}\n"],"mappings":"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","names":["useMemo","useEffect","jsx","useEffect","useMemo"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bento-grid-builder",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "A flexible, configurable bento grid layout system for React",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",