@tonyarbor/components 0.9.0 → 0.9.2

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.mjs CHANGED
@@ -64,7 +64,7 @@ import {
64
64
  } from "./chunk-G5NVKF2G.mjs";
65
65
  import {
66
66
  Table
67
- } from "./chunk-AI2U34CF.mjs";
67
+ } from "./chunk-GDOCRKBF.mjs";
68
68
  import {
69
69
  Avatar
70
70
  } from "./chunk-JSG27ZZS.mjs";
@@ -123,11 +123,38 @@ import {
123
123
  Checkbox
124
124
  } from "./chunk-CUTYEIFE.mjs";
125
125
 
126
- // src/SideNavItem/SideNavItem.tsx
126
+ // src/TableContainer/TableContainer.tsx
127
127
  import * as React from "react";
128
+ import { clsx } from "clsx";
129
+ import { jsx } from "react/jsx-runtime";
130
+ var containerStyles = {
131
+ backgroundColor: "#ffffff",
132
+ padding: "8px",
133
+ borderRadius: "8px",
134
+ width: "100%",
135
+ boxSizing: "border-box"
136
+ };
137
+ var TableContainer = React.forwardRef(
138
+ ({ children, className, style, "data-testid": dataTestId }, ref) => {
139
+ return /* @__PURE__ */ jsx(
140
+ "div",
141
+ {
142
+ ref,
143
+ className: clsx("arbor-table-container", className),
144
+ style: { ...containerStyles, ...style },
145
+ "data-testid": dataTestId,
146
+ children
147
+ }
148
+ );
149
+ }
150
+ );
151
+ TableContainer.displayName = "TableContainer";
152
+
153
+ // src/SideNavItem/SideNavItem.tsx
154
+ import * as React2 from "react";
128
155
  import { Star, ChevronRight, ChevronDown } from "lucide-react";
129
- import { jsx, jsxs } from "react/jsx-runtime";
130
- var SideNavItem = React.forwardRef(
156
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
157
+ var SideNavItem = React2.forwardRef(
131
158
  ({
132
159
  label,
133
160
  tier = 1,
@@ -142,8 +169,8 @@ var SideNavItem = React.forwardRef(
142
169
  className,
143
170
  style
144
171
  }, ref) => {
145
- const [isHovered, setIsHovered] = React.useState(false);
146
- const [isStarHovered, setIsStarHovered] = React.useState(false);
172
+ const [isHovered, setIsHovered] = React2.useState(false);
173
+ const [isStarHovered, setIsStarHovered] = React2.useState(false);
147
174
  const basePadding = 24;
148
175
  const tierIndent = (tier - 1) * 12;
149
176
  const chevronSpace = hasChildren ? 20 : 0;
@@ -167,7 +194,7 @@ var SideNavItem = React.forwardRef(
167
194
  if (isStarHovered) return "#2f2f2f";
168
195
  return "#0e8a0e";
169
196
  };
170
- const containerStyles = {
197
+ const containerStyles2 = {
171
198
  display: "flex",
172
199
  alignItems: "center",
173
200
  gap: "8px",
@@ -237,7 +264,7 @@ var SideNavItem = React.forwardRef(
237
264
  {
238
265
  ref,
239
266
  className,
240
- style: containerStyles,
267
+ style: containerStyles2,
241
268
  onClick: handleClick,
242
269
  onMouseEnter: () => setIsHovered(true),
243
270
  onMouseLeave: () => {
@@ -250,18 +277,18 @@ var SideNavItem = React.forwardRef(
250
277
  "aria-expanded": hasChildren ? expanded : void 0,
251
278
  "aria-label": label,
252
279
  children: [
253
- hasChildren && /* @__PURE__ */ jsx(
280
+ hasChildren && /* @__PURE__ */ jsx2(
254
281
  "div",
255
282
  {
256
283
  style: chevronStyles,
257
284
  onClick: handleChevronClick,
258
285
  role: "button",
259
286
  "aria-label": expanded ? "Collapse" : "Expand",
260
- children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { size: 14, color: "#7e7e7e", strokeWidth: 2 }) : /* @__PURE__ */ jsx(ChevronRight, { size: 14, color: "#7e7e7e", strokeWidth: 2 })
287
+ children: expanded ? /* @__PURE__ */ jsx2(ChevronDown, { size: 14, color: "#7e7e7e", strokeWidth: 2 }) : /* @__PURE__ */ jsx2(ChevronRight, { size: 14, color: "#7e7e7e", strokeWidth: 2 })
261
288
  }
262
289
  ),
263
- /* @__PURE__ */ jsx("span", { style: labelStyles, children: label }),
264
- /* @__PURE__ */ jsx(
290
+ /* @__PURE__ */ jsx2("span", { style: labelStyles, children: label }),
291
+ /* @__PURE__ */ jsx2(
265
292
  "div",
266
293
  {
267
294
  style: starContainerStyles,
@@ -271,7 +298,7 @@ var SideNavItem = React.forwardRef(
271
298
  role: "button",
272
299
  "aria-label": favourited ? "Remove from favourites" : "Add to favourites",
273
300
  "aria-pressed": favourited,
274
- children: /* @__PURE__ */ jsx(
301
+ children: /* @__PURE__ */ jsx2(
275
302
  Star,
276
303
  {
277
304
  size: 15,
@@ -322,6 +349,7 @@ export {
322
349
  SubSectionHeading,
323
350
  SubSectionInteractive,
324
351
  Table,
352
+ TableContainer,
325
353
  TableControls,
326
354
  TableFooterPagination,
327
355
  Tabs,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/SideNavItem/SideNavItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Star, ChevronRight, ChevronDown } from 'lucide-react';\n\nexport type SideNavItemTier = 1 | 2 | 3 | 4 | 5;\n\nexport interface SideNavItemProps {\n /**\n * The text label for the navigation item\n */\n label: string;\n /**\n * The tier/depth level (1-5). Each tier adds 12px indentation.\n * Tier 1 = 24px left padding (base)\n * @default 1\n */\n tier?: SideNavItemTier;\n /**\n * Whether the item is currently active/selected\n * @default false\n */\n active?: boolean;\n /**\n * Whether the item has child items (shows expand/collapse chevron)\n * @default false\n */\n hasChildren?: boolean;\n /**\n * Whether the item is expanded (only relevant when hasChildren is true)\n * @default false\n */\n expanded?: boolean;\n /**\n * Whether the item is favourited (star is filled)\n * @default false\n */\n favourited?: boolean;\n /**\n * Whether the item is focused (shows green ring)\n * @default false\n */\n focused?: boolean;\n /**\n * Click handler for the item\n */\n onClick?: () => void;\n /**\n * Click handler for the expand/collapse chevron\n */\n onExpandClick?: () => void;\n /**\n * Click handler for the favourite star\n */\n onFavouriteClick?: () => void;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n}\n\n/**\n * SideNavItem component - Arbor Design System\n *\n * A navigation list item used in the side navigation panel.\n * Supports multiple tiers for nested navigation, favourite functionality,\n * and expand/collapse for parent items with children.\n */\nexport const SideNavItem = React.forwardRef<HTMLDivElement, SideNavItemProps>(\n (\n {\n label,\n tier = 1,\n active = false,\n hasChildren = false,\n expanded = false,\n favourited = false,\n focused = false,\n onClick,\n onExpandClick,\n onFavouriteClick,\n className,\n style,\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = React.useState(false);\n const [isStarHovered, setIsStarHovered] = React.useState(false);\n\n // Calculate left padding based on tier\n // Tier 1 = 24px, each additional tier adds 12px\n // If hasChildren, reduce padding to make room for chevron\n const basePadding = 24;\n const tierIndent = (tier - 1) * 12;\n const chevronSpace = hasChildren ? 20 : 0;\n const leftPadding = basePadding + tierIndent - chevronSpace;\n\n // Determine text color based on state\n const getTextColor = () => {\n if (active) return '#005700';\n if (isHovered) return '#2f2f2f';\n return '#333333';\n };\n\n // Determine background color based on state\n const getBackgroundColor = () => {\n if (active) return '#f0faf3';\n if (isHovered) return '#f8f8f8';\n return 'transparent';\n };\n\n // Determine font weight\n const getFontWeight = () => {\n return active ? 600 : 400;\n };\n\n // Show star when hovered or active\n const showStar = isHovered || active;\n\n // Star icon color\n const getStarColor = () => {\n if (favourited) return '#0e8a0e';\n if (isStarHovered) return '#2f2f2f';\n return '#0e8a0e';\n };\n\n const containerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n width: '168px',\n paddingTop: '8px',\n paddingBottom: '8px',\n paddingLeft: `${leftPadding}px`,\n paddingRight: '8px',\n borderRadius: '99px',\n backgroundColor: getBackgroundColor(),\n boxShadow: focused ? '0px 0px 0px 3px #3cad51' : 'none',\n cursor: 'pointer',\n boxSizing: 'border-box',\n transition: 'background-color 150ms ease',\n outline: 'none',\n ...style,\n };\n\n const chevronStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '16px',\n height: '16px',\n marginLeft: '-4px',\n };\n\n const labelStyles: React.CSSProperties = {\n flex: 1,\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: '13px',\n fontWeight: getFontWeight(),\n color: getTextColor(),\n lineHeight: 1.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n };\n\n const starContainerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '16px',\n height: '16px',\n opacity: showStar ? 1 : 0,\n transition: 'opacity 150ms ease',\n };\n\n const handleClick = () => {\n onClick?.();\n };\n\n const handleChevronClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onExpandClick?.();\n };\n\n const handleStarClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onFavouriteClick?.();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.();\n }\n };\n\n return (\n <div\n ref={ref}\n className={className}\n style={containerStyles}\n onClick={handleClick}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => {\n setIsHovered(false);\n setIsStarHovered(false);\n }}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"button\"\n aria-expanded={hasChildren ? expanded : undefined}\n aria-label={label}\n >\n {/* Expand/Collapse Chevron */}\n {hasChildren && (\n <div\n style={chevronStyles}\n onClick={handleChevronClick}\n role=\"button\"\n aria-label={expanded ? 'Collapse' : 'Expand'}\n >\n {expanded ? (\n <ChevronDown size={14} color=\"#7e7e7e\" strokeWidth={2} />\n ) : (\n <ChevronRight size={14} color=\"#7e7e7e\" strokeWidth={2} />\n )}\n </div>\n )}\n\n {/* Label */}\n <span style={labelStyles}>{label}</span>\n\n {/* Favourite Star */}\n <div\n style={starContainerStyles}\n onClick={handleStarClick}\n onMouseEnter={() => setIsStarHovered(true)}\n onMouseLeave={() => setIsStarHovered(false)}\n role=\"button\"\n aria-label={favourited ? 'Remove from favourites' : 'Add to favourites'}\n aria-pressed={favourited}\n >\n <Star\n size={15}\n color={getStarColor()}\n fill={favourited ? '#0e8a0e' : 'none'}\n strokeWidth={2}\n />\n </div>\n </div>\n );\n }\n);\n\nSideNavItem.displayName = 'SideNavItem';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/TableContainer/TableContainer.tsx","../src/SideNavItem/SideNavItem.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\n\nexport interface TableContainerProps {\n /**\n * Children to render inside the container (TableControls, Table, TableFooterPagination)\n */\n children: React.ReactNode;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n}\n\nconst containerStyles: React.CSSProperties = {\n backgroundColor: '#ffffff',\n padding: '8px',\n borderRadius: '8px',\n width: '100%',\n boxSizing: 'border-box',\n};\n\n/**\n * TableContainer component - Arbor Design System\n *\n * A wrapper container for the full table experience.\n * Use to wrap TableControls, Table, and TableFooterPagination together\n * in a white box with 8px padding and 8px border radius.\n *\n * @example\n * ```tsx\n * <TableContainer>\n * <TableControls {...controlsProps} />\n * <Table {...tableProps} />\n * <TableFooterPagination {...paginationProps} />\n * </TableContainer>\n * ```\n */\nexport const TableContainer = React.forwardRef<HTMLDivElement, TableContainerProps>(\n ({ children, className, style, 'data-testid': dataTestId }, ref) => {\n return (\n <div\n ref={ref}\n className={clsx('arbor-table-container', className)}\n style={{ ...containerStyles, ...style }}\n data-testid={dataTestId}\n >\n {children}\n </div>\n );\n }\n);\n\nTableContainer.displayName = 'TableContainer';\n","import * as React from 'react';\nimport { Star, ChevronRight, ChevronDown } from 'lucide-react';\n\nexport type SideNavItemTier = 1 | 2 | 3 | 4 | 5;\n\nexport interface SideNavItemProps {\n /**\n * The text label for the navigation item\n */\n label: string;\n /**\n * The tier/depth level (1-5). Each tier adds 12px indentation.\n * Tier 1 = 24px left padding (base)\n * @default 1\n */\n tier?: SideNavItemTier;\n /**\n * Whether the item is currently active/selected\n * @default false\n */\n active?: boolean;\n /**\n * Whether the item has child items (shows expand/collapse chevron)\n * @default false\n */\n hasChildren?: boolean;\n /**\n * Whether the item is expanded (only relevant when hasChildren is true)\n * @default false\n */\n expanded?: boolean;\n /**\n * Whether the item is favourited (star is filled)\n * @default false\n */\n favourited?: boolean;\n /**\n * Whether the item is focused (shows green ring)\n * @default false\n */\n focused?: boolean;\n /**\n * Click handler for the item\n */\n onClick?: () => void;\n /**\n * Click handler for the expand/collapse chevron\n */\n onExpandClick?: () => void;\n /**\n * Click handler for the favourite star\n */\n onFavouriteClick?: () => void;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n}\n\n/**\n * SideNavItem component - Arbor Design System\n *\n * A navigation list item used in the side navigation panel.\n * Supports multiple tiers for nested navigation, favourite functionality,\n * and expand/collapse for parent items with children.\n */\nexport const SideNavItem = React.forwardRef<HTMLDivElement, SideNavItemProps>(\n (\n {\n label,\n tier = 1,\n active = false,\n hasChildren = false,\n expanded = false,\n favourited = false,\n focused = false,\n onClick,\n onExpandClick,\n onFavouriteClick,\n className,\n style,\n },\n ref\n ) => {\n const [isHovered, setIsHovered] = React.useState(false);\n const [isStarHovered, setIsStarHovered] = React.useState(false);\n\n // Calculate left padding based on tier\n // Tier 1 = 24px, each additional tier adds 12px\n // If hasChildren, reduce padding to make room for chevron\n const basePadding = 24;\n const tierIndent = (tier - 1) * 12;\n const chevronSpace = hasChildren ? 20 : 0;\n const leftPadding = basePadding + tierIndent - chevronSpace;\n\n // Determine text color based on state\n const getTextColor = () => {\n if (active) return '#005700';\n if (isHovered) return '#2f2f2f';\n return '#333333';\n };\n\n // Determine background color based on state\n const getBackgroundColor = () => {\n if (active) return '#f0faf3';\n if (isHovered) return '#f8f8f8';\n return 'transparent';\n };\n\n // Determine font weight\n const getFontWeight = () => {\n return active ? 600 : 400;\n };\n\n // Show star when hovered or active\n const showStar = isHovered || active;\n\n // Star icon color\n const getStarColor = () => {\n if (favourited) return '#0e8a0e';\n if (isStarHovered) return '#2f2f2f';\n return '#0e8a0e';\n };\n\n const containerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n width: '168px',\n paddingTop: '8px',\n paddingBottom: '8px',\n paddingLeft: `${leftPadding}px`,\n paddingRight: '8px',\n borderRadius: '99px',\n backgroundColor: getBackgroundColor(),\n boxShadow: focused ? '0px 0px 0px 3px #3cad51' : 'none',\n cursor: 'pointer',\n boxSizing: 'border-box',\n transition: 'background-color 150ms ease',\n outline: 'none',\n ...style,\n };\n\n const chevronStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '16px',\n height: '16px',\n marginLeft: '-4px',\n };\n\n const labelStyles: React.CSSProperties = {\n flex: 1,\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n fontSize: '13px',\n fontWeight: getFontWeight(),\n color: getTextColor(),\n lineHeight: 1.5,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n };\n\n const starContainerStyles: React.CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n width: '16px',\n height: '16px',\n opacity: showStar ? 1 : 0,\n transition: 'opacity 150ms ease',\n };\n\n const handleClick = () => {\n onClick?.();\n };\n\n const handleChevronClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onExpandClick?.();\n };\n\n const handleStarClick = (e: React.MouseEvent) => {\n e.stopPropagation();\n onFavouriteClick?.();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.();\n }\n };\n\n return (\n <div\n ref={ref}\n className={className}\n style={containerStyles}\n onClick={handleClick}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => {\n setIsHovered(false);\n setIsStarHovered(false);\n }}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"button\"\n aria-expanded={hasChildren ? expanded : undefined}\n aria-label={label}\n >\n {/* Expand/Collapse Chevron */}\n {hasChildren && (\n <div\n style={chevronStyles}\n onClick={handleChevronClick}\n role=\"button\"\n aria-label={expanded ? 'Collapse' : 'Expand'}\n >\n {expanded ? (\n <ChevronDown size={14} color=\"#7e7e7e\" strokeWidth={2} />\n ) : (\n <ChevronRight size={14} color=\"#7e7e7e\" strokeWidth={2} />\n )}\n </div>\n )}\n\n {/* Label */}\n <span style={labelStyles}>{label}</span>\n\n {/* Favourite Star */}\n <div\n style={starContainerStyles}\n onClick={handleStarClick}\n onMouseEnter={() => setIsStarHovered(true)}\n onMouseLeave={() => setIsStarHovered(false)}\n role=\"button\"\n aria-label={favourited ? 'Remove from favourites' : 'Add to favourites'}\n aria-pressed={favourited}\n >\n <Star\n size={15}\n color={getStarColor()}\n fill={favourited ? '#0e8a0e' : 'none'}\n strokeWidth={2}\n />\n </div>\n </div>\n );\n }\n);\n\nSideNavItem.displayName = 'SideNavItem';\n"],"mappings":"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","names":["React","jsx","containerStyles"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyarbor/components",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "React components for Arbor Design System",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/Table/Table.tsx"],"sourcesContent":["import * as React from 'react';\nimport { clsx } from 'clsx';\nimport { MoreVertical } from 'lucide-react';\nimport { Checkbox } from '../Checkbox';\n\nexport interface TableColumn {\n /**\n * Unique key for the column\n */\n key: string;\n /**\n * Column header label\n */\n label: string;\n /**\n * Whether to show the menu icon in the header\n */\n showMenu?: boolean;\n /**\n * Custom width for the column\n */\n width?: string;\n}\n\nexport interface TableRow {\n /**\n * Unique ID for the row\n */\n id: string;\n /**\n * Cell data keyed by column key\n */\n cells: Record<string, React.ReactNode>;\n /**\n * Whether the row is selected\n */\n selected?: boolean;\n}\n\nexport interface TableProps {\n /**\n * Table columns configuration\n */\n columns: TableColumn[];\n /**\n * Table rows data\n */\n rows: TableRow[];\n /**\n * Callback when row selection changes\n */\n onRowSelectionChange?: (rowId: string, selected: boolean) => void;\n /**\n * Callback when select all is toggled\n */\n onSelectAllChange?: (selected: boolean) => void;\n /**\n * Whether all rows are selected\n */\n allSelected?: boolean;\n /**\n * Whether some rows are selected (indeterminate state)\n */\n someSelected?: boolean;\n /**\n * Custom className\n */\n className?: string;\n /**\n * Custom style\n */\n style?: React.CSSProperties;\n /**\n * Test ID for testing\n */\n 'data-testid'?: string;\n}\n\nconst tableStyles: React.CSSProperties = {\n width: '100%',\n borderCollapse: 'separate',\n borderSpacing: 0,\n fontFamily: \"'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n};\n\nconst headerCellStyles: React.CSSProperties = {\n height: '44px',\n paddingLeft: '16px',\n paddingRight: '16px',\n paddingTop: 0,\n paddingBottom: 0,\n backgroundColor: '#f8f8f8',\n borderBottom: '1px solid #efefef',\n fontSize: '13px',\n fontWeight: 600,\n color: '#2f2f2f',\n textAlign: 'left',\n position: 'relative',\n};\n\nconst checkboxCellStyles: React.CSSProperties = {\n width: '48px',\n paddingLeft: '16px',\n paddingRight: '8px',\n};\n\nconst bodyCellStyles: React.CSSProperties = {\n height: '41px',\n paddingLeft: '16px',\n paddingRight: '16px',\n paddingTop: '8px',\n paddingBottom: '8px',\n borderBottom: '1px solid #efefef',\n fontSize: '13px',\n color: '#2f2f2f',\n};\n\nconst menuButtonStyles: React.CSSProperties = {\n width: '24px',\n height: '24px',\n border: 'none',\n backgroundColor: 'transparent',\n cursor: 'pointer',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: 0,\n marginLeft: '8px',\n borderRadius: '4px',\n transition: 'background-color 0.2s ease-in-out',\n};\n\nconst rowStyles: React.CSSProperties = {\n transition: 'background-color 0.1s ease-in-out',\n};\n\n/**\n * Table component - Arbor Design System\n *\n * A data table component with selectable rows and column headers.\n */\nexport const Table = React.forwardRef<HTMLTableElement, TableProps>(\n (\n {\n columns,\n rows,\n onRowSelectionChange,\n onSelectAllChange,\n allSelected = false,\n someSelected = false,\n className,\n style,\n 'data-testid': dataTestId,\n },\n ref\n ) => {\n const [hoveredRow, setHoveredRow] = React.useState<string | null>(null);\n const [hoveredMenuButton, setHoveredMenuButton] = React.useState<string | null>(null);\n\n return (\n <table\n ref={ref}\n className={clsx('arbor-table', className)}\n style={{ ...tableStyles, ...style }}\n data-testid={dataTestId}\n >\n <thead>\n <tr>\n {/* Checkbox header cell */}\n <th style={{ ...headerCellStyles, ...checkboxCellStyles }}>\n <Checkbox\n checked={allSelected}\n indeterminate={someSelected && !allSelected}\n onChange={onSelectAllChange}\n aria-label=\"Select all rows\"\n />\n </th>\n\n {/* Column headers */}\n {columns.map((column) => (\n <th\n key={column.key}\n style={{\n ...headerCellStyles,\n ...(column.width ? { width: column.width } : {}),\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center' }}>\n <span>{column.label}</span>\n {column.showMenu !== false && (\n <button\n type=\"button\"\n onMouseEnter={() => setHoveredMenuButton(`header-${column.key}`)}\n onMouseLeave={() => setHoveredMenuButton(null)}\n style={{\n ...menuButtonStyles,\n backgroundColor:\n hoveredMenuButton === `header-${column.key}` ? '#f5f5f5' : 'transparent',\n }}\n aria-label={`${column.label} options`}\n >\n <MoreVertical size={16} color=\"#595959\" />\n </button>\n )}\n </div>\n </th>\n ))}\n </tr>\n </thead>\n\n <tbody>\n {rows.map((row, index) => {\n const isOdd = index % 2 === 0;\n const isHovered = hoveredRow === row.id;\n\n return (\n <tr\n key={row.id}\n onMouseEnter={() => setHoveredRow(row.id)}\n onMouseLeave={() => setHoveredRow(null)}\n style={{\n ...rowStyles,\n backgroundColor: isHovered\n ? '#fafafa'\n : isOdd\n ? 'white'\n : '#f8f8f8',\n }}\n >\n {/* Checkbox cell */}\n <td style={{ ...bodyCellStyles, ...checkboxCellStyles }}>\n <Checkbox\n checked={row.selected || false}\n onChange={(checked) => onRowSelectionChange?.(row.id, checked)}\n aria-label={`Select row ${row.id}`}\n />\n </td>\n\n {/* Data cells */}\n {columns.map((column) => (\n <td key={column.key} style={bodyCellStyles}>\n {row.cells[column.key]}\n </td>\n ))}\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n }\n);\n\nTable.displayName = 'Table';\n"],"mappings":"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","names":[]}