bento-grid-builder 0.1.0 → 0.2.0

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,9 +443,10 @@ 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));
449
+ height: var(--bento-height, auto);
445
450
  }
446
451
  .bento-cell {
447
452
  grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);
@@ -574,12 +579,15 @@ function BentoGrid({
574
579
  gap = 16,
575
580
  columnGap,
576
581
  rowGap,
582
+ rowHeights,
577
583
  placements
578
584
  } = resolvedLayout;
579
585
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
586
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
580
587
  const gridStyle = {
581
588
  "--bento-columns": columns,
582
589
  "--bento-rows": calculatedRows,
590
+ "--bento-row-heights": rowTemplate,
583
591
  "--bento-gap": `${gap}px`,
584
592
  "--bento-column-gap": `${columnGap ?? gap}px`,
585
593
  "--bento-row-gap": `${rowGap ?? gap}px`,
@@ -706,12 +714,15 @@ function UnifiedBentoGrid({
706
714
  gap = 16,
707
715
  columnGap,
708
716
  rowGap,
717
+ rowHeights,
709
718
  placements
710
719
  } = resolvedLayout;
711
720
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
721
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
712
722
  const gridStyle = {
713
723
  "--bento-columns": columns,
714
724
  "--bento-rows": calculatedRows,
725
+ "--bento-row-heights": rowTemplate,
715
726
  "--bento-gap": `${gap}px`,
716
727
  "--bento-column-gap": `${columnGap ?? gap}px`,
717
728
  "--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 height: var(--bento-height, auto);\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 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,9 +392,10 @@ 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));
398
+ height: var(--bento-height, auto);
394
399
  }
395
400
  .bento-cell {
396
401
  grid-column: var(--bento-col, 1) / span var(--bento-col-span, 1);
@@ -523,12 +528,15 @@ function BentoGrid({
523
528
  gap = 16,
524
529
  columnGap,
525
530
  rowGap,
531
+ rowHeights,
526
532
  placements
527
533
  } = resolvedLayout;
528
534
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
535
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
529
536
  const gridStyle = {
530
537
  "--bento-columns": columns,
531
538
  "--bento-rows": calculatedRows,
539
+ "--bento-row-heights": rowTemplate,
532
540
  "--bento-gap": `${gap}px`,
533
541
  "--bento-column-gap": `${columnGap ?? gap}px`,
534
542
  "--bento-row-gap": `${rowGap ?? gap}px`,
@@ -655,12 +663,15 @@ function UnifiedBentoGrid({
655
663
  gap = 16,
656
664
  columnGap,
657
665
  rowGap,
666
+ rowHeights,
658
667
  placements
659
668
  } = resolvedLayout;
660
669
  const calculatedRows = rows ?? Math.max(...placements.map((p) => p.row + (p.rowSpan ?? 1) - 1), 1);
670
+ const rowTemplate = rowHeights ? rowHeights.join(" ") : `repeat(${calculatedRows}, minmax(0, 1fr))`;
661
671
  const gridStyle = {
662
672
  "--bento-columns": columns,
663
673
  "--bento-rows": calculatedRows,
674
+ "--bento-row-heights": rowTemplate,
664
675
  "--bento-gap": `${gap}px`,
665
676
  "--bento-column-gap": `${columnGap ?? gap}px`,
666
677
  "--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 height: var(--bento-height, auto);\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 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.0",
4
4
  "description": "A flexible, configurable bento grid layout system for React",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",