@hyddenlabs/hydn-ui 0.3.0-alpha.187 → 0.3.0-alpha.189

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.cjs CHANGED
@@ -2009,6 +2009,10 @@ var Button = React__default.default.forwardRef(
2009
2009
  ({
2010
2010
  children,
2011
2011
  onClick,
2012
+ onMouseEnter,
2013
+ onMouseLeave,
2014
+ onMouseDown,
2015
+ onBlur,
2012
2016
  ariaLabel,
2013
2017
  disabled = false,
2014
2018
  type = "button",
@@ -2085,6 +2089,10 @@ var Button = React__default.default.forwardRef(
2085
2089
  ref,
2086
2090
  type,
2087
2091
  onClick,
2092
+ onMouseEnter,
2093
+ onMouseLeave,
2094
+ onMouseDown,
2095
+ onBlur,
2088
2096
  "aria-label": ariaLabel,
2089
2097
  disabled: disabled || loading,
2090
2098
  className: `${baseDisplayClass} items-center justify-center ${alignmentClass} ${roundedClasses[rounded]} font-medium transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50 ${styleClasses} ${sizeClasses} ${isIconOnly ? "p-0" : ""} ${widthClasses} ${activeClasses} ${className}`,
@@ -2248,9 +2256,73 @@ function useScrollReset(deps, container) {
2248
2256
  }
2249
2257
  var useScrollReset_default = useScrollReset;
2250
2258
  var IconButton = React__default.default.forwardRef(
2251
- ({ icon, iconSize = "md", iconColor = "currentColor", buttonStyle, ariaLabel, ...rest }, ref) => {
2252
- const iconNode = icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, size: iconSize, color: iconColor }) : null;
2253
- return /* @__PURE__ */ jsxRuntime.jsx(button_default, { ref, icon: iconNode, style: buttonStyle, ariaLabel, ...rest });
2259
+ ({
2260
+ icon,
2261
+ iconSize = "md",
2262
+ iconColor = "currentColor",
2263
+ buttonStyle,
2264
+ ariaLabel,
2265
+ hoverIcon,
2266
+ onMouseEnter,
2267
+ onMouseLeave,
2268
+ onClick,
2269
+ ...rest
2270
+ }, ref) => {
2271
+ const [isHovered, setIsHovered] = React.useState(false);
2272
+ const buttonRef = React.useRef(null);
2273
+ const mergedRef = React.useCallback(
2274
+ (node) => {
2275
+ buttonRef.current = node;
2276
+ if (typeof ref === "function") {
2277
+ ref(node);
2278
+ } else if (ref) {
2279
+ ref.current = node;
2280
+ }
2281
+ },
2282
+ [ref]
2283
+ );
2284
+ const handleMouseEnter = (e) => {
2285
+ setIsHovered(true);
2286
+ onMouseEnter?.(e);
2287
+ };
2288
+ const handleMouseLeave = (e) => {
2289
+ setIsHovered(false);
2290
+ onMouseLeave?.(e);
2291
+ };
2292
+ const handleClick = (e) => {
2293
+ setIsHovered(false);
2294
+ onClick?.(e);
2295
+ };
2296
+ React.useEffect(() => {
2297
+ if (!hoverIcon || !isHovered) return;
2298
+ const handleGlobalMouseMove = (e) => {
2299
+ if (!buttonRef.current) return;
2300
+ const rect = buttonRef.current.getBoundingClientRect();
2301
+ const isOutside = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
2302
+ if (isOutside) {
2303
+ setIsHovered(false);
2304
+ }
2305
+ };
2306
+ document.addEventListener("mousemove", handleGlobalMouseMove);
2307
+ return () => {
2308
+ document.removeEventListener("mousemove", handleGlobalMouseMove);
2309
+ };
2310
+ }, [hoverIcon, isHovered]);
2311
+ const displayIcon = isHovered && hoverIcon ? hoverIcon : icon;
2312
+ const iconNode = displayIcon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: displayIcon, size: iconSize, color: iconColor }) : null;
2313
+ return /* @__PURE__ */ jsxRuntime.jsx(
2314
+ button_default,
2315
+ {
2316
+ ref: mergedRef,
2317
+ icon: iconNode,
2318
+ style: buttonStyle,
2319
+ ariaLabel,
2320
+ onMouseEnter: handleMouseEnter,
2321
+ onMouseLeave: handleMouseLeave,
2322
+ onClick: handleClick,
2323
+ ...rest
2324
+ }
2325
+ );
2254
2326
  }
2255
2327
  );
2256
2328
  IconButton.displayName = "IconButton";
@@ -2344,7 +2416,8 @@ function LeftNavLayout({
2344
2416
  /* @__PURE__ */ jsxRuntime.jsx(
2345
2417
  icon_button_default,
2346
2418
  {
2347
- icon: collapsed ? "chevron-right" : "chevron-left",
2419
+ icon: collapsed ? "layout-sidebar-left-expand" : "layout-sidebar-left-collapse",
2420
+ hoverIcon: collapsed ? "layout-sidebar-left-expand-filled" : "layout-sidebar-left-collapse-filled",
2348
2421
  ariaLabel: collapsed ? "Expand sidebar" : "Collapse sidebar",
2349
2422
  buttonStyle: "ghost",
2350
2423
  variant: "neutral",
@@ -3897,6 +3970,110 @@ function CodeBlock({ code, className = "", showCopy = true }) {
3897
3970
  }
3898
3971
  CodeBlock.displayName = "CodeBlock";
3899
3972
  var code_block_default = CodeBlock;
3973
+ function Input({
3974
+ value,
3975
+ defaultValue,
3976
+ onChange,
3977
+ onFocus,
3978
+ onBlur,
3979
+ placeholder,
3980
+ disabled = false,
3981
+ type = "text",
3982
+ ariaLabel,
3983
+ ref,
3984
+ id,
3985
+ name,
3986
+ required = false,
3987
+ size = "md",
3988
+ width,
3989
+ validationState = "default",
3990
+ autoComplete,
3991
+ maxLength,
3992
+ minLength,
3993
+ pattern,
3994
+ title,
3995
+ readOnly = false
3996
+ }) {
3997
+ const widthClass = width ? inputWidthSizes[width] : "w-full";
3998
+ const inputClasses = `${getInputClasses(size, validationState)} ${widthClass}`.trim();
3999
+ return /* @__PURE__ */ jsxRuntime.jsx(
4000
+ "input",
4001
+ {
4002
+ type,
4003
+ value,
4004
+ defaultValue,
4005
+ ref,
4006
+ onChange,
4007
+ onFocus,
4008
+ onBlur,
4009
+ placeholder,
4010
+ autoComplete,
4011
+ disabled,
4012
+ "aria-label": ariaLabel,
4013
+ id,
4014
+ name,
4015
+ required,
4016
+ readOnly,
4017
+ maxLength,
4018
+ minLength,
4019
+ pattern,
4020
+ title,
4021
+ "aria-invalid": validationState === "error",
4022
+ className: inputClasses
4023
+ }
4024
+ );
4025
+ }
4026
+ Input.displayName = "Input";
4027
+ var input_default = Input;
4028
+ var containerBaseClasses = "inline-flex items-stretch rounded-lg border shadow-sm bg-background focus-within:ring-2 focus-within:ring-ring/20 transition-colors duration-150 overflow-hidden";
4029
+ var inputResetClasses = [
4030
+ "[&>input]:border-0 [&>input]:shadow-none [&>input]:rounded-none [&>input]:ring-0",
4031
+ "[&>input]:focus:ring-0 [&>input]:focus:border-0 [&>input]:bg-transparent",
4032
+ "[&>input]:flex-1 [&>input]:min-w-0"
4033
+ ].join(" ");
4034
+ var buttonResetClasses = [
4035
+ "[&_button]:rounded-none [&_button]:border-0 [&_button]:shadow-none [&_button]:m-0",
4036
+ "[&_button]:h-full"
4037
+ ].join(" ");
4038
+ function InputGroup({
4039
+ children,
4040
+ prefix,
4041
+ suffix,
4042
+ validationState = "default",
4043
+ disabled = false,
4044
+ className
4045
+ }) {
4046
+ const isTextPrefix = typeof prefix === "string" || typeof prefix === "number";
4047
+ const isTextSuffix = typeof suffix === "string" || typeof suffix === "number";
4048
+ const borderClass = validationState === "default" ? "border-input focus-within:border-ring" : validationBorderClasses[validationState].split(" ")[0];
4049
+ const disabledClass = disabled ? "opacity-50 cursor-not-allowed" : "";
4050
+ const enhancedChild = React.isValidElement(children) && disabled ? React.cloneElement(children, { disabled: true }) : children;
4051
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4052
+ "div",
4053
+ {
4054
+ className: `${containerBaseClasses} ${borderClass} ${inputResetClasses} ${buttonResetClasses} ${disabledClass} ${className ?? ""}`.trim(),
4055
+ children: [
4056
+ prefix && /* @__PURE__ */ jsxRuntime.jsx(
4057
+ "div",
4058
+ {
4059
+ className: `flex items-center shrink-0 ${isTextPrefix ? "px-3 bg-muted/50 text-muted-foreground text-sm" : "px-3 text-muted-foreground"}`,
4060
+ children: prefix
4061
+ }
4062
+ ),
4063
+ enhancedChild,
4064
+ suffix && /* @__PURE__ */ jsxRuntime.jsx(
4065
+ "div",
4066
+ {
4067
+ className: isTextSuffix ? "flex items-center px-3 bg-muted/50 text-muted-foreground text-sm shrink-0" : "flex items-stretch shrink-0",
4068
+ children: suffix
4069
+ }
4070
+ )
4071
+ ]
4072
+ }
4073
+ );
4074
+ }
4075
+ InputGroup.displayName = "InputGroup";
4076
+ var input_group_default = InputGroup;
3900
4077
  function Table({
3901
4078
  children,
3902
4079
  className = "",
@@ -4027,15 +4204,41 @@ function EmptyState({ title, description, icon, action, className = "" }) {
4027
4204
  }
4028
4205
  EmptyState.displayName = "EmptyState";
4029
4206
  var empty_state_default = EmptyState;
4030
- function useTable({ data, initialSort, pageSize = 10 }) {
4207
+ function useTable({
4208
+ data,
4209
+ initialSort,
4210
+ pageSize = 10,
4211
+ searchQuery = "",
4212
+ searchKeys
4213
+ }) {
4031
4214
  const [sortConfig, setSortConfig] = React.useState(
4032
4215
  initialSort ? { key: initialSort.key, direction: initialSort.direction } : null
4033
4216
  );
4034
4217
  const [currentPage, setCurrentPage] = React.useState(1);
4035
4218
  const [selectedRows, setSelectedRows] = React.useState(/* @__PURE__ */ new Set());
4219
+ React.useEffect(() => {
4220
+ setCurrentPage(1);
4221
+ }, [searchQuery]);
4222
+ const filteredData = React.useMemo(() => {
4223
+ if (!searchQuery || searchQuery.trim() === "") return data;
4224
+ const query = searchQuery.toLowerCase();
4225
+ return data.filter((row) => {
4226
+ if (searchKeys && searchKeys.length > 0) {
4227
+ return searchKeys.some((key) => {
4228
+ const value = row[key];
4229
+ if (value == null) return false;
4230
+ return String(value).toLowerCase().includes(query);
4231
+ });
4232
+ }
4233
+ return Object.values(row).some((value) => {
4234
+ if (value == null) return false;
4235
+ return String(value).toLowerCase().includes(query);
4236
+ });
4237
+ });
4238
+ }, [data, searchQuery, searchKeys]);
4036
4239
  const sortedData = React.useMemo(() => {
4037
- if (!sortConfig) return data;
4038
- const sorted = [...data].sort((a, b) => {
4240
+ if (!sortConfig) return filteredData;
4241
+ const sorted = [...filteredData].sort((a, b) => {
4039
4242
  const aValue = a[sortConfig.key];
4040
4243
  const bValue = b[sortConfig.key];
4041
4244
  if (aValue === bValue) return 0;
@@ -4047,7 +4250,7 @@ function useTable({ data, initialSort, pageSize = 10 }) {
4047
4250
  return sortConfig.direction === "asc" ? 1 : -1;
4048
4251
  });
4049
4252
  return sorted;
4050
- }, [data, sortConfig]);
4253
+ }, [filteredData, sortConfig]);
4051
4254
  const totalPages = Math.ceil(sortedData.length / pageSize);
4052
4255
  const startIndex = (currentPage - 1) * pageSize;
4053
4256
  const endIndex = startIndex + pageSize;
@@ -4097,6 +4300,7 @@ function useTable({ data, initialSort, pageSize = 10 }) {
4097
4300
  return {
4098
4301
  currentData,
4099
4302
  sortedData,
4303
+ filteredData,
4100
4304
  sortConfig,
4101
4305
  handleSort,
4102
4306
  currentPage,
@@ -4128,6 +4332,10 @@ function DataTable({
4128
4332
  paginated = false,
4129
4333
  pageSize = 10,
4130
4334
  selectable = false,
4335
+ searchable = false,
4336
+ searchKeys,
4337
+ searchPlaceholder = "Search...",
4338
+ onSearchChange,
4131
4339
  actions,
4132
4340
  actionsLabel = "Actions",
4133
4341
  actionsWidth = "w-32",
@@ -4139,14 +4347,24 @@ function DataTable({
4139
4347
  title,
4140
4348
  initialSort
4141
4349
  }) {
4350
+ const [searchQuery, setSearchQuery] = React.useState("");
4351
+ const handleSearchChange = (value) => {
4352
+ setSearchQuery(value);
4353
+ if (onSearchChange) {
4354
+ onSearchChange(value);
4355
+ }
4356
+ };
4142
4357
  const tableOptions = {
4143
4358
  data,
4144
4359
  initialSort,
4145
- pageSize
4360
+ pageSize,
4361
+ searchQuery,
4362
+ searchKeys
4146
4363
  };
4147
4364
  const {
4148
4365
  currentData,
4149
4366
  sortedData,
4367
+ filteredData,
4150
4368
  sortConfig,
4151
4369
  handleSort,
4152
4370
  currentPage,
@@ -4162,7 +4380,7 @@ function DataTable({
4162
4380
  isAllSelected
4163
4381
  } = useTable(tableOptions);
4164
4382
  const displayData = paginated ? currentData : sortedData;
4165
- const hasHeader = Boolean(title && String(title).length > 0 || headerActions);
4383
+ const hasHeader = Boolean(title && String(title).length > 0 || headerActions || searchable);
4166
4384
  const handleToggleRow = (index) => {
4167
4385
  toggleRow(index);
4168
4386
  if (onSelectionChange) {
@@ -4247,125 +4465,152 @@ function DataTable({
4247
4465
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(empty_state_default, { title: emptyMessage, icon: emptyIcon, className: "py-12" }) });
4248
4466
  }
4249
4467
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
4250
- hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
4251
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-foreground", children: title }),
4252
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: Array.isArray(headerActions) && headerActions.map((act, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
4253
- button_default,
4254
- {
4255
- onClick: act.onClick,
4256
- variant: act.variant,
4257
- style: act.style,
4258
- size: act.size,
4259
- className: act.className,
4260
- ariaLabel: act.label && act.icon && !act.label ? act.label : void 0,
4261
- children: [
4262
- act.icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: act.icon, size: "sm" }) : null,
4263
- act.label
4264
- ]
4265
- },
4266
- idx
4267
- )) })
4268
- ] }),
4269
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${stickyHeader ? "overflow-auto max-h-[600px]" : ""} overflow-x-auto`, children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { striped, bordered, hoverable, compact, children: [
4270
- /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { className: stickyHeader ? "sticky top-0 z-10 bg-background shadow-sm" : "", children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
4271
- selectable && /* @__PURE__ */ jsxRuntime.jsx(TableHeadCell, { className: "w-12", children: /* @__PURE__ */ jsxRuntime.jsx(checkbox_default, { checked: isAllSelected, onChange: handleToggleAll, ariaLabel: "Select all rows" }) }),
4272
- columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
4273
- TableHeadCell,
4468
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 mb-3", children: [
4469
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-foreground", children: title }),
4470
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3", children: [
4471
+ searchable && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 max-w-md", children: /* @__PURE__ */ jsxRuntime.jsx(input_group_default, { prefix: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "search", size: "sm" }), className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
4472
+ input_default,
4274
4473
  {
4275
- align: column.align,
4276
- className: column.width ? `w-[${column.width}]` : "",
4277
- children: column.sortable !== false && sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
4278
- "button",
4279
- {
4280
- onClick: () => handleSort(column.key),
4281
- className: "flex items-center gap-1 hover:text-foreground transition-colors font-medium",
4282
- type: "button",
4283
- children: [
4284
- column.label,
4285
- renderSortIcon(column.key)
4286
- ]
4287
- }
4288
- ) : column.label
4289
- },
4290
- String(column.key)
4291
- )),
4292
- actions && /* @__PURE__ */ jsxRuntime.jsx(TableHeadCell, { align: "center", className: actionsWidth, children: actionsLabel })
4293
- ] }) }),
4294
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: displayData.map((row, rowIndex) => {
4295
- const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;
4296
- const isSelected = isRowSelected(actualIndex);
4297
- return /* @__PURE__ */ jsxRuntime.jsxs(
4298
- TableRow,
4474
+ type: "text",
4475
+ value: searchQuery,
4476
+ onChange: (e) => handleSearchChange(e.target.value),
4477
+ placeholder: searchPlaceholder
4478
+ }
4479
+ ) }) }),
4480
+ Array.isArray(headerActions) && headerActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: headerActions.map((act, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
4481
+ button_default,
4299
4482
  {
4300
- selected: isSelected,
4301
- onClick: onRowClick ? () => onRowClick(row, actualIndex) : void 0,
4302
- className: onRowClick ? "cursor-pointer" : "",
4483
+ onClick: act.onClick,
4484
+ variant: act.variant,
4485
+ style: act.style,
4486
+ size: act.size,
4487
+ className: act.className,
4488
+ ariaLabel: act.label && act.icon && !act.label ? act.label : void 0,
4303
4489
  children: [
4304
- selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(
4305
- checkbox_default,
4490
+ act.icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: act.icon, size: "sm" }) : null,
4491
+ act.label
4492
+ ]
4493
+ },
4494
+ idx
4495
+ )) })
4496
+ ] })
4497
+ ] }),
4498
+ filteredData.length === 0 && searchQuery.trim() ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
4499
+ empty_state_default,
4500
+ {
4501
+ title: "No results found",
4502
+ description: `No items match "${searchQuery}". Try adjusting your search.`,
4503
+ icon: "search",
4504
+ className: "py-12"
4505
+ }
4506
+ ) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4507
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${stickyHeader ? "overflow-auto max-h-[600px]" : ""} overflow-x-auto`, children: /* @__PURE__ */ jsxRuntime.jsxs(Table, { striped, bordered, hoverable, compact, children: [
4508
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { className: stickyHeader ? "sticky top-0 z-10 bg-background shadow-sm" : "", children: /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
4509
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableHeadCell, { className: "w-12", children: /* @__PURE__ */ jsxRuntime.jsx(checkbox_default, { checked: isAllSelected, onChange: handleToggleAll, ariaLabel: "Select all rows" }) }),
4510
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
4511
+ TableHeadCell,
4512
+ {
4513
+ align: column.align,
4514
+ className: column.width ? `w-[${column.width}]` : "",
4515
+ children: column.sortable !== false && sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
4516
+ "button",
4306
4517
  {
4307
- checked: isSelected,
4308
- onChange: () => handleToggleRow(actualIndex),
4309
- ariaLabel: `Select row ${actualIndex + 1}`
4518
+ onClick: () => handleSort(column.key),
4519
+ className: "flex items-center gap-1 hover:text-foreground transition-colors font-medium",
4520
+ type: "button",
4521
+ children: [
4522
+ column.label,
4523
+ renderSortIcon(column.key)
4524
+ ]
4310
4525
  }
4311
- ) }),
4312
- columns.map((column) => {
4313
- const value = row[column.key];
4314
- const content = renderCellContent(value, column, row, actualIndex);
4315
- return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { align: column.align, wrapText: column.wrapText, children: content }, String(column.key));
4316
- }),
4317
- actions && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { align: "center", onClick: (e) => e.stopPropagation(), children: (() => {
4318
- let rowActions;
4319
- if (Array.isArray(actions)) {
4320
- rowActions = actions;
4321
- } else {
4322
- const result = actions(row, actualIndex);
4323
- if (Array.isArray(result)) {
4324
- rowActions = result;
4325
- } else {
4326
- return result;
4526
+ ) : column.label
4527
+ },
4528
+ String(column.key)
4529
+ )),
4530
+ actions && /* @__PURE__ */ jsxRuntime.jsx(TableHeadCell, { align: "center", className: actionsWidth, children: actionsLabel })
4531
+ ] }) }),
4532
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { children: displayData.map((row, rowIndex) => {
4533
+ const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;
4534
+ const isSelected = isRowSelected(actualIndex);
4535
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4536
+ TableRow,
4537
+ {
4538
+ selected: isSelected,
4539
+ onClick: onRowClick ? () => onRowClick(row, actualIndex) : void 0,
4540
+ className: onRowClick ? "cursor-pointer" : "",
4541
+ children: [
4542
+ selectable && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsx(
4543
+ checkbox_default,
4544
+ {
4545
+ checked: isSelected,
4546
+ onChange: () => handleToggleRow(actualIndex),
4547
+ ariaLabel: `Select row ${actualIndex + 1}`
4327
4548
  }
4328
- }
4329
- return /* @__PURE__ */ jsxRuntime.jsx(stack_default, { direction: "horizontal", spacing: "sm", justify: "center", children: rowActions.map((action, actionIndex) => {
4330
- if (action && typeof action === "object" && "onClick" in action) {
4331
- const actionConfig = action;
4332
- return /* @__PURE__ */ jsxRuntime.jsx(
4333
- icon_button_default,
4334
- {
4335
- icon: actionConfig.icon,
4336
- iconSize: actionConfig.iconSize || "md",
4337
- buttonStyle: "ghost",
4338
- variant: actionConfig.variant || "neutral",
4339
- iconColor: actionConfig.iconColor,
4340
- ariaLabel: actionConfig.label,
4341
- onClick: () => actionConfig.onClick(row, actualIndex)
4342
- },
4343
- actionIndex
4344
- );
4549
+ ) }),
4550
+ columns.map((column) => {
4551
+ const value = row[column.key];
4552
+ const content = renderCellContent(value, column, row, actualIndex);
4553
+ return /* @__PURE__ */ jsxRuntime.jsx(TableCell, { align: column.align, wrapText: column.wrapText, children: content }, String(column.key));
4554
+ }),
4555
+ actions && /* @__PURE__ */ jsxRuntime.jsx(TableCell, { align: "center", onClick: (e) => e.stopPropagation(), children: (() => {
4556
+ let rowActions;
4557
+ if (Array.isArray(actions)) {
4558
+ rowActions = actions;
4345
4559
  } else {
4346
- return /* @__PURE__ */ jsxRuntime.jsx("div", { children: action }, actionIndex);
4560
+ const result = actions(row, actualIndex);
4561
+ if (Array.isArray(result)) {
4562
+ rowActions = result;
4563
+ } else {
4564
+ return result;
4565
+ }
4347
4566
  }
4348
- }) });
4349
- })() })
4350
- ]
4351
- },
4352
- actualIndex
4353
- );
4354
- }) })
4355
- ] }) }),
4356
- paginated && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-border", children: [
4357
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
4358
- "Page ",
4359
- currentPage,
4360
- " of ",
4361
- totalPages,
4362
- " (",
4363
- data.length,
4364
- " total rows)"
4365
- ] }),
4366
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
4367
- /* @__PURE__ */ jsxRuntime.jsx(button_default, { size: "sm", style: "outline", onClick: prevPage, disabled: !canPrevPage, children: "Previous" }),
4368
- /* @__PURE__ */ jsxRuntime.jsx(button_default, { size: "sm", style: "outline", onClick: nextPage, disabled: !canNextPage, children: "Next" })
4567
+ return /* @__PURE__ */ jsxRuntime.jsx(stack_default, { direction: "horizontal", spacing: "sm", justify: "center", children: rowActions.map((action, actionIndex) => {
4568
+ if (action && typeof action === "object" && "onClick" in action) {
4569
+ const actionConfig = action;
4570
+ const button = /* @__PURE__ */ jsxRuntime.jsx(
4571
+ icon_button_default,
4572
+ {
4573
+ icon: actionConfig.icon,
4574
+ iconSize: actionConfig.iconSize || "md",
4575
+ buttonStyle: "ghost",
4576
+ variant: actionConfig.variant || "neutral",
4577
+ iconColor: actionConfig.iconColor,
4578
+ ariaLabel: actionConfig.label,
4579
+ onClick: () => actionConfig.onClick(row, actualIndex)
4580
+ },
4581
+ actionIndex
4582
+ );
4583
+ return actionConfig.tooltip ? /* @__PURE__ */ jsxRuntime.jsx(tooltip_default, { content: actionConfig.tooltip, children: button }, actionIndex) : button;
4584
+ } else {
4585
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: action }, actionIndex);
4586
+ }
4587
+ }) });
4588
+ })() })
4589
+ ]
4590
+ },
4591
+ actualIndex
4592
+ );
4593
+ }) })
4594
+ ] }) }),
4595
+ paginated && totalPages > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-border", children: [
4596
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm text-muted-foreground", children: [
4597
+ "Page ",
4598
+ currentPage,
4599
+ " of ",
4600
+ totalPages,
4601
+ " (",
4602
+ filteredData.length,
4603
+ " ",
4604
+ searchQuery.trim() ? "filtered" : "total",
4605
+ " ",
4606
+ "rows",
4607
+ searchQuery.trim() && data.length !== filteredData.length ? ` of ${data.length}` : "",
4608
+ ")"
4609
+ ] }),
4610
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
4611
+ /* @__PURE__ */ jsxRuntime.jsx(button_default, { size: "sm", style: "outline", onClick: prevPage, disabled: !canPrevPage, children: "Previous" }),
4612
+ /* @__PURE__ */ jsxRuntime.jsx(button_default, { size: "sm", style: "outline", onClick: nextPage, disabled: !canNextPage, children: "Next" })
4613
+ ] })
4369
4614
  ] })
4370
4615
  ] })
4371
4616
  ] });
@@ -5563,61 +5808,6 @@ function FormField({
5563
5808
  }
5564
5809
  FormField.displayName = "FormField";
5565
5810
  var form_field_default = FormField;
5566
- function Input({
5567
- value,
5568
- defaultValue,
5569
- onChange,
5570
- onFocus,
5571
- onBlur,
5572
- placeholder,
5573
- disabled = false,
5574
- type = "text",
5575
- ariaLabel,
5576
- ref,
5577
- id,
5578
- name,
5579
- required = false,
5580
- size = "md",
5581
- width,
5582
- validationState = "default",
5583
- autoComplete,
5584
- maxLength,
5585
- minLength,
5586
- pattern,
5587
- title,
5588
- readOnly = false
5589
- }) {
5590
- const widthClass = width ? inputWidthSizes[width] : "w-full";
5591
- const inputClasses = `${getInputClasses(size, validationState)} ${widthClass}`.trim();
5592
- return /* @__PURE__ */ jsxRuntime.jsx(
5593
- "input",
5594
- {
5595
- type,
5596
- value,
5597
- defaultValue,
5598
- ref,
5599
- onChange,
5600
- onFocus,
5601
- onBlur,
5602
- placeholder,
5603
- autoComplete,
5604
- disabled,
5605
- "aria-label": ariaLabel,
5606
- id,
5607
- name,
5608
- required,
5609
- readOnly,
5610
- maxLength,
5611
- minLength,
5612
- pattern,
5613
- title,
5614
- "aria-invalid": validationState === "error",
5615
- className: inputClasses
5616
- }
5617
- );
5618
- }
5619
- Input.displayName = "Input";
5620
- var input_default = Input;
5621
5811
  function FormInput({
5622
5812
  // FormField props
5623
5813
  label,
@@ -5817,55 +6007,6 @@ function FormTextarea({
5817
6007
  }
5818
6008
  FormTextarea.displayName = "FormTextarea";
5819
6009
  var form_textarea_default = FormTextarea;
5820
- var containerBaseClasses = "inline-flex items-stretch rounded-lg border shadow-sm bg-background focus-within:ring-2 focus-within:ring-ring/20 transition-colors duration-150 overflow-hidden";
5821
- var inputResetClasses = [
5822
- "[&>input]:border-0 [&>input]:shadow-none [&>input]:rounded-none [&>input]:ring-0",
5823
- "[&>input]:focus:ring-0 [&>input]:focus:border-0 [&>input]:bg-transparent",
5824
- "[&>input]:flex-1 [&>input]:min-w-0"
5825
- ].join(" ");
5826
- var buttonResetClasses = [
5827
- "[&_button]:rounded-none [&_button]:border-0 [&_button]:shadow-none [&_button]:m-0",
5828
- "[&_button]:h-full"
5829
- ].join(" ");
5830
- function InputGroup({
5831
- children,
5832
- prefix,
5833
- suffix,
5834
- validationState = "default",
5835
- disabled = false,
5836
- className
5837
- }) {
5838
- const isTextPrefix = typeof prefix === "string" || typeof prefix === "number";
5839
- const isTextSuffix = typeof suffix === "string" || typeof suffix === "number";
5840
- const borderClass = validationState === "default" ? "border-input focus-within:border-ring" : validationBorderClasses[validationState].split(" ")[0];
5841
- const disabledClass = disabled ? "opacity-50 cursor-not-allowed" : "";
5842
- const enhancedChild = React.isValidElement(children) && disabled ? React.cloneElement(children, { disabled: true }) : children;
5843
- return /* @__PURE__ */ jsxRuntime.jsxs(
5844
- "div",
5845
- {
5846
- className: `${containerBaseClasses} ${borderClass} ${inputResetClasses} ${buttonResetClasses} ${disabledClass} ${className ?? ""}`.trim(),
5847
- children: [
5848
- prefix && /* @__PURE__ */ jsxRuntime.jsx(
5849
- "div",
5850
- {
5851
- className: `flex items-center shrink-0 ${isTextPrefix ? "px-3 bg-muted/50 text-muted-foreground text-sm" : "px-3 text-muted-foreground"}`,
5852
- children: prefix
5853
- }
5854
- ),
5855
- enhancedChild,
5856
- suffix && /* @__PURE__ */ jsxRuntime.jsx(
5857
- "div",
5858
- {
5859
- className: isTextSuffix ? "flex items-center px-3 bg-muted/50 text-muted-foreground text-sm shrink-0" : "flex items-stretch shrink-0",
5860
- children: suffix
5861
- }
5862
- )
5863
- ]
5864
- }
5865
- );
5866
- }
5867
- InputGroup.displayName = "InputGroup";
5868
- var input_group_default = InputGroup;
5869
6010
  function MultiSelect({
5870
6011
  options,
5871
6012
  value = [],