@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.js CHANGED
@@ -1,4 +1,4 @@
1
- import React, { createContext, useState, useEffect, useCallback, useMemo, useContext, createElement, useRef, useLayoutEffect, isValidElement, cloneElement, useId, Fragment as Fragment$1 } from 'react';
1
+ import React, { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext, createElement, useLayoutEffect, isValidElement, cloneElement, useId, Fragment as Fragment$1 } from 'react';
2
2
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import * as TablerIcons from '@tabler/icons-react';
4
4
  import { createPortal } from 'react-dom';
@@ -1984,6 +1984,10 @@ var Button = React.forwardRef(
1984
1984
  ({
1985
1985
  children,
1986
1986
  onClick,
1987
+ onMouseEnter,
1988
+ onMouseLeave,
1989
+ onMouseDown,
1990
+ onBlur,
1987
1991
  ariaLabel,
1988
1992
  disabled = false,
1989
1993
  type = "button",
@@ -2060,6 +2064,10 @@ var Button = React.forwardRef(
2060
2064
  ref,
2061
2065
  type,
2062
2066
  onClick,
2067
+ onMouseEnter,
2068
+ onMouseLeave,
2069
+ onMouseDown,
2070
+ onBlur,
2063
2071
  "aria-label": ariaLabel,
2064
2072
  disabled: disabled || loading,
2065
2073
  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}`,
@@ -2223,9 +2231,73 @@ function useScrollReset(deps, container) {
2223
2231
  }
2224
2232
  var useScrollReset_default = useScrollReset;
2225
2233
  var IconButton = React.forwardRef(
2226
- ({ icon, iconSize = "md", iconColor = "currentColor", buttonStyle, ariaLabel, ...rest }, ref) => {
2227
- const iconNode = icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: iconSize, color: iconColor }) : null;
2228
- return /* @__PURE__ */ jsx(button_default, { ref, icon: iconNode, style: buttonStyle, ariaLabel, ...rest });
2234
+ ({
2235
+ icon,
2236
+ iconSize = "md",
2237
+ iconColor = "currentColor",
2238
+ buttonStyle,
2239
+ ariaLabel,
2240
+ hoverIcon,
2241
+ onMouseEnter,
2242
+ onMouseLeave,
2243
+ onClick,
2244
+ ...rest
2245
+ }, ref) => {
2246
+ const [isHovered, setIsHovered] = useState(false);
2247
+ const buttonRef = useRef(null);
2248
+ const mergedRef = useCallback(
2249
+ (node) => {
2250
+ buttonRef.current = node;
2251
+ if (typeof ref === "function") {
2252
+ ref(node);
2253
+ } else if (ref) {
2254
+ ref.current = node;
2255
+ }
2256
+ },
2257
+ [ref]
2258
+ );
2259
+ const handleMouseEnter = (e) => {
2260
+ setIsHovered(true);
2261
+ onMouseEnter?.(e);
2262
+ };
2263
+ const handleMouseLeave = (e) => {
2264
+ setIsHovered(false);
2265
+ onMouseLeave?.(e);
2266
+ };
2267
+ const handleClick = (e) => {
2268
+ setIsHovered(false);
2269
+ onClick?.(e);
2270
+ };
2271
+ useEffect(() => {
2272
+ if (!hoverIcon || !isHovered) return;
2273
+ const handleGlobalMouseMove = (e) => {
2274
+ if (!buttonRef.current) return;
2275
+ const rect = buttonRef.current.getBoundingClientRect();
2276
+ const isOutside = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
2277
+ if (isOutside) {
2278
+ setIsHovered(false);
2279
+ }
2280
+ };
2281
+ document.addEventListener("mousemove", handleGlobalMouseMove);
2282
+ return () => {
2283
+ document.removeEventListener("mousemove", handleGlobalMouseMove);
2284
+ };
2285
+ }, [hoverIcon, isHovered]);
2286
+ const displayIcon = isHovered && hoverIcon ? hoverIcon : icon;
2287
+ const iconNode = displayIcon ? /* @__PURE__ */ jsx(Icon, { name: displayIcon, size: iconSize, color: iconColor }) : null;
2288
+ return /* @__PURE__ */ jsx(
2289
+ button_default,
2290
+ {
2291
+ ref: mergedRef,
2292
+ icon: iconNode,
2293
+ style: buttonStyle,
2294
+ ariaLabel,
2295
+ onMouseEnter: handleMouseEnter,
2296
+ onMouseLeave: handleMouseLeave,
2297
+ onClick: handleClick,
2298
+ ...rest
2299
+ }
2300
+ );
2229
2301
  }
2230
2302
  );
2231
2303
  IconButton.displayName = "IconButton";
@@ -2319,7 +2391,8 @@ function LeftNavLayout({
2319
2391
  /* @__PURE__ */ jsx(
2320
2392
  icon_button_default,
2321
2393
  {
2322
- icon: collapsed ? "chevron-right" : "chevron-left",
2394
+ icon: collapsed ? "layout-sidebar-left-expand" : "layout-sidebar-left-collapse",
2395
+ hoverIcon: collapsed ? "layout-sidebar-left-expand-filled" : "layout-sidebar-left-collapse-filled",
2323
2396
  ariaLabel: collapsed ? "Expand sidebar" : "Collapse sidebar",
2324
2397
  buttonStyle: "ghost",
2325
2398
  variant: "neutral",
@@ -3872,6 +3945,110 @@ function CodeBlock({ code, className = "", showCopy = true }) {
3872
3945
  }
3873
3946
  CodeBlock.displayName = "CodeBlock";
3874
3947
  var code_block_default = CodeBlock;
3948
+ function Input({
3949
+ value,
3950
+ defaultValue,
3951
+ onChange,
3952
+ onFocus,
3953
+ onBlur,
3954
+ placeholder,
3955
+ disabled = false,
3956
+ type = "text",
3957
+ ariaLabel,
3958
+ ref,
3959
+ id,
3960
+ name,
3961
+ required = false,
3962
+ size = "md",
3963
+ width,
3964
+ validationState = "default",
3965
+ autoComplete,
3966
+ maxLength,
3967
+ minLength,
3968
+ pattern,
3969
+ title,
3970
+ readOnly = false
3971
+ }) {
3972
+ const widthClass = width ? inputWidthSizes[width] : "w-full";
3973
+ const inputClasses = `${getInputClasses(size, validationState)} ${widthClass}`.trim();
3974
+ return /* @__PURE__ */ jsx(
3975
+ "input",
3976
+ {
3977
+ type,
3978
+ value,
3979
+ defaultValue,
3980
+ ref,
3981
+ onChange,
3982
+ onFocus,
3983
+ onBlur,
3984
+ placeholder,
3985
+ autoComplete,
3986
+ disabled,
3987
+ "aria-label": ariaLabel,
3988
+ id,
3989
+ name,
3990
+ required,
3991
+ readOnly,
3992
+ maxLength,
3993
+ minLength,
3994
+ pattern,
3995
+ title,
3996
+ "aria-invalid": validationState === "error",
3997
+ className: inputClasses
3998
+ }
3999
+ );
4000
+ }
4001
+ Input.displayName = "Input";
4002
+ var input_default = Input;
4003
+ 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";
4004
+ var inputResetClasses = [
4005
+ "[&>input]:border-0 [&>input]:shadow-none [&>input]:rounded-none [&>input]:ring-0",
4006
+ "[&>input]:focus:ring-0 [&>input]:focus:border-0 [&>input]:bg-transparent",
4007
+ "[&>input]:flex-1 [&>input]:min-w-0"
4008
+ ].join(" ");
4009
+ var buttonResetClasses = [
4010
+ "[&_button]:rounded-none [&_button]:border-0 [&_button]:shadow-none [&_button]:m-0",
4011
+ "[&_button]:h-full"
4012
+ ].join(" ");
4013
+ function InputGroup({
4014
+ children,
4015
+ prefix,
4016
+ suffix,
4017
+ validationState = "default",
4018
+ disabled = false,
4019
+ className
4020
+ }) {
4021
+ const isTextPrefix = typeof prefix === "string" || typeof prefix === "number";
4022
+ const isTextSuffix = typeof suffix === "string" || typeof suffix === "number";
4023
+ const borderClass = validationState === "default" ? "border-input focus-within:border-ring" : validationBorderClasses[validationState].split(" ")[0];
4024
+ const disabledClass = disabled ? "opacity-50 cursor-not-allowed" : "";
4025
+ const enhancedChild = isValidElement(children) && disabled ? cloneElement(children, { disabled: true }) : children;
4026
+ return /* @__PURE__ */ jsxs(
4027
+ "div",
4028
+ {
4029
+ className: `${containerBaseClasses} ${borderClass} ${inputResetClasses} ${buttonResetClasses} ${disabledClass} ${className ?? ""}`.trim(),
4030
+ children: [
4031
+ prefix && /* @__PURE__ */ jsx(
4032
+ "div",
4033
+ {
4034
+ className: `flex items-center shrink-0 ${isTextPrefix ? "px-3 bg-muted/50 text-muted-foreground text-sm" : "px-3 text-muted-foreground"}`,
4035
+ children: prefix
4036
+ }
4037
+ ),
4038
+ enhancedChild,
4039
+ suffix && /* @__PURE__ */ jsx(
4040
+ "div",
4041
+ {
4042
+ className: isTextSuffix ? "flex items-center px-3 bg-muted/50 text-muted-foreground text-sm shrink-0" : "flex items-stretch shrink-0",
4043
+ children: suffix
4044
+ }
4045
+ )
4046
+ ]
4047
+ }
4048
+ );
4049
+ }
4050
+ InputGroup.displayName = "InputGroup";
4051
+ var input_group_default = InputGroup;
3875
4052
  function Table({
3876
4053
  children,
3877
4054
  className = "",
@@ -4002,15 +4179,41 @@ function EmptyState({ title, description, icon, action, className = "" }) {
4002
4179
  }
4003
4180
  EmptyState.displayName = "EmptyState";
4004
4181
  var empty_state_default = EmptyState;
4005
- function useTable({ data, initialSort, pageSize = 10 }) {
4182
+ function useTable({
4183
+ data,
4184
+ initialSort,
4185
+ pageSize = 10,
4186
+ searchQuery = "",
4187
+ searchKeys
4188
+ }) {
4006
4189
  const [sortConfig, setSortConfig] = useState(
4007
4190
  initialSort ? { key: initialSort.key, direction: initialSort.direction } : null
4008
4191
  );
4009
4192
  const [currentPage, setCurrentPage] = useState(1);
4010
4193
  const [selectedRows, setSelectedRows] = useState(/* @__PURE__ */ new Set());
4194
+ useEffect(() => {
4195
+ setCurrentPage(1);
4196
+ }, [searchQuery]);
4197
+ const filteredData = useMemo(() => {
4198
+ if (!searchQuery || searchQuery.trim() === "") return data;
4199
+ const query = searchQuery.toLowerCase();
4200
+ return data.filter((row) => {
4201
+ if (searchKeys && searchKeys.length > 0) {
4202
+ return searchKeys.some((key) => {
4203
+ const value = row[key];
4204
+ if (value == null) return false;
4205
+ return String(value).toLowerCase().includes(query);
4206
+ });
4207
+ }
4208
+ return Object.values(row).some((value) => {
4209
+ if (value == null) return false;
4210
+ return String(value).toLowerCase().includes(query);
4211
+ });
4212
+ });
4213
+ }, [data, searchQuery, searchKeys]);
4011
4214
  const sortedData = useMemo(() => {
4012
- if (!sortConfig) return data;
4013
- const sorted = [...data].sort((a, b) => {
4215
+ if (!sortConfig) return filteredData;
4216
+ const sorted = [...filteredData].sort((a, b) => {
4014
4217
  const aValue = a[sortConfig.key];
4015
4218
  const bValue = b[sortConfig.key];
4016
4219
  if (aValue === bValue) return 0;
@@ -4022,7 +4225,7 @@ function useTable({ data, initialSort, pageSize = 10 }) {
4022
4225
  return sortConfig.direction === "asc" ? 1 : -1;
4023
4226
  });
4024
4227
  return sorted;
4025
- }, [data, sortConfig]);
4228
+ }, [filteredData, sortConfig]);
4026
4229
  const totalPages = Math.ceil(sortedData.length / pageSize);
4027
4230
  const startIndex = (currentPage - 1) * pageSize;
4028
4231
  const endIndex = startIndex + pageSize;
@@ -4072,6 +4275,7 @@ function useTable({ data, initialSort, pageSize = 10 }) {
4072
4275
  return {
4073
4276
  currentData,
4074
4277
  sortedData,
4278
+ filteredData,
4075
4279
  sortConfig,
4076
4280
  handleSort,
4077
4281
  currentPage,
@@ -4103,6 +4307,10 @@ function DataTable({
4103
4307
  paginated = false,
4104
4308
  pageSize = 10,
4105
4309
  selectable = false,
4310
+ searchable = false,
4311
+ searchKeys,
4312
+ searchPlaceholder = "Search...",
4313
+ onSearchChange,
4106
4314
  actions,
4107
4315
  actionsLabel = "Actions",
4108
4316
  actionsWidth = "w-32",
@@ -4114,14 +4322,24 @@ function DataTable({
4114
4322
  title,
4115
4323
  initialSort
4116
4324
  }) {
4325
+ const [searchQuery, setSearchQuery] = useState("");
4326
+ const handleSearchChange = (value) => {
4327
+ setSearchQuery(value);
4328
+ if (onSearchChange) {
4329
+ onSearchChange(value);
4330
+ }
4331
+ };
4117
4332
  const tableOptions = {
4118
4333
  data,
4119
4334
  initialSort,
4120
- pageSize
4335
+ pageSize,
4336
+ searchQuery,
4337
+ searchKeys
4121
4338
  };
4122
4339
  const {
4123
4340
  currentData,
4124
4341
  sortedData,
4342
+ filteredData,
4125
4343
  sortConfig,
4126
4344
  handleSort,
4127
4345
  currentPage,
@@ -4137,7 +4355,7 @@ function DataTable({
4137
4355
  isAllSelected
4138
4356
  } = useTable(tableOptions);
4139
4357
  const displayData = paginated ? currentData : sortedData;
4140
- const hasHeader = Boolean(title && String(title).length > 0 || headerActions);
4358
+ const hasHeader = Boolean(title && String(title).length > 0 || headerActions || searchable);
4141
4359
  const handleToggleRow = (index) => {
4142
4360
  toggleRow(index);
4143
4361
  if (onSelectionChange) {
@@ -4222,125 +4440,152 @@ function DataTable({
4222
4440
  return /* @__PURE__ */ jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsx(empty_state_default, { title: emptyMessage, icon: emptyIcon, className: "py-12" }) });
4223
4441
  }
4224
4442
  return /* @__PURE__ */ jsxs("div", { className, children: [
4225
- hasHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
4226
- /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: title }),
4227
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: Array.isArray(headerActions) && headerActions.map((act, idx) => /* @__PURE__ */ jsxs(
4228
- button_default,
4229
- {
4230
- onClick: act.onClick,
4231
- variant: act.variant,
4232
- style: act.style,
4233
- size: act.size,
4234
- className: act.className,
4235
- ariaLabel: act.label && act.icon && !act.label ? act.label : void 0,
4236
- children: [
4237
- act.icon ? /* @__PURE__ */ jsx(Icon, { name: act.icon, size: "sm" }) : null,
4238
- act.label
4239
- ]
4240
- },
4241
- idx
4242
- )) })
4243
- ] }),
4244
- /* @__PURE__ */ jsx("div", { className: `${stickyHeader ? "overflow-auto max-h-[600px]" : ""} overflow-x-auto`, children: /* @__PURE__ */ jsxs(Table, { striped, bordered, hoverable, compact, children: [
4245
- /* @__PURE__ */ jsx(TableHeader, { className: stickyHeader ? "sticky top-0 z-10 bg-background shadow-sm" : "", children: /* @__PURE__ */ jsxs(TableRow, { children: [
4246
- selectable && /* @__PURE__ */ jsx(TableHeadCell, { className: "w-12", children: /* @__PURE__ */ jsx(checkbox_default, { checked: isAllSelected, onChange: handleToggleAll, ariaLabel: "Select all rows" }) }),
4247
- columns.map((column) => /* @__PURE__ */ jsx(
4248
- TableHeadCell,
4443
+ hasHeader && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 mb-3", children: [
4444
+ title && /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-foreground", children: title }),
4445
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
4446
+ searchable && /* @__PURE__ */ jsx("div", { className: "flex-1 max-w-md", children: /* @__PURE__ */ jsx(input_group_default, { prefix: /* @__PURE__ */ jsx(Icon, { name: "search", size: "sm" }), className: "w-full", children: /* @__PURE__ */ jsx(
4447
+ input_default,
4249
4448
  {
4250
- align: column.align,
4251
- className: column.width ? `w-[${column.width}]` : "",
4252
- children: column.sortable !== false && sortable ? /* @__PURE__ */ jsxs(
4253
- "button",
4254
- {
4255
- onClick: () => handleSort(column.key),
4256
- className: "flex items-center gap-1 hover:text-foreground transition-colors font-medium",
4257
- type: "button",
4258
- children: [
4259
- column.label,
4260
- renderSortIcon(column.key)
4261
- ]
4262
- }
4263
- ) : column.label
4264
- },
4265
- String(column.key)
4266
- )),
4267
- actions && /* @__PURE__ */ jsx(TableHeadCell, { align: "center", className: actionsWidth, children: actionsLabel })
4268
- ] }) }),
4269
- /* @__PURE__ */ jsx(TableBody, { children: displayData.map((row, rowIndex) => {
4270
- const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;
4271
- const isSelected = isRowSelected(actualIndex);
4272
- return /* @__PURE__ */ jsxs(
4273
- TableRow,
4449
+ type: "text",
4450
+ value: searchQuery,
4451
+ onChange: (e) => handleSearchChange(e.target.value),
4452
+ placeholder: searchPlaceholder
4453
+ }
4454
+ ) }) }),
4455
+ Array.isArray(headerActions) && headerActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: headerActions.map((act, idx) => /* @__PURE__ */ jsxs(
4456
+ button_default,
4274
4457
  {
4275
- selected: isSelected,
4276
- onClick: onRowClick ? () => onRowClick(row, actualIndex) : void 0,
4277
- className: onRowClick ? "cursor-pointer" : "",
4458
+ onClick: act.onClick,
4459
+ variant: act.variant,
4460
+ style: act.style,
4461
+ size: act.size,
4462
+ className: act.className,
4463
+ ariaLabel: act.label && act.icon && !act.label ? act.label : void 0,
4278
4464
  children: [
4279
- selectable && /* @__PURE__ */ jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
4280
- checkbox_default,
4465
+ act.icon ? /* @__PURE__ */ jsx(Icon, { name: act.icon, size: "sm" }) : null,
4466
+ act.label
4467
+ ]
4468
+ },
4469
+ idx
4470
+ )) })
4471
+ ] })
4472
+ ] }),
4473
+ filteredData.length === 0 && searchQuery.trim() ? /* @__PURE__ */ jsx("div", { className: "border border-border rounded-lg", children: /* @__PURE__ */ jsx(
4474
+ empty_state_default,
4475
+ {
4476
+ title: "No results found",
4477
+ description: `No items match "${searchQuery}". Try adjusting your search.`,
4478
+ icon: "search",
4479
+ className: "py-12"
4480
+ }
4481
+ ) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
4482
+ /* @__PURE__ */ jsx("div", { className: `${stickyHeader ? "overflow-auto max-h-[600px]" : ""} overflow-x-auto`, children: /* @__PURE__ */ jsxs(Table, { striped, bordered, hoverable, compact, children: [
4483
+ /* @__PURE__ */ jsx(TableHeader, { className: stickyHeader ? "sticky top-0 z-10 bg-background shadow-sm" : "", children: /* @__PURE__ */ jsxs(TableRow, { children: [
4484
+ selectable && /* @__PURE__ */ jsx(TableHeadCell, { className: "w-12", children: /* @__PURE__ */ jsx(checkbox_default, { checked: isAllSelected, onChange: handleToggleAll, ariaLabel: "Select all rows" }) }),
4485
+ columns.map((column) => /* @__PURE__ */ jsx(
4486
+ TableHeadCell,
4487
+ {
4488
+ align: column.align,
4489
+ className: column.width ? `w-[${column.width}]` : "",
4490
+ children: column.sortable !== false && sortable ? /* @__PURE__ */ jsxs(
4491
+ "button",
4281
4492
  {
4282
- checked: isSelected,
4283
- onChange: () => handleToggleRow(actualIndex),
4284
- ariaLabel: `Select row ${actualIndex + 1}`
4493
+ onClick: () => handleSort(column.key),
4494
+ className: "flex items-center gap-1 hover:text-foreground transition-colors font-medium",
4495
+ type: "button",
4496
+ children: [
4497
+ column.label,
4498
+ renderSortIcon(column.key)
4499
+ ]
4285
4500
  }
4286
- ) }),
4287
- columns.map((column) => {
4288
- const value = row[column.key];
4289
- const content = renderCellContent(value, column, row, actualIndex);
4290
- return /* @__PURE__ */ jsx(TableCell, { align: column.align, wrapText: column.wrapText, children: content }, String(column.key));
4291
- }),
4292
- actions && /* @__PURE__ */ jsx(TableCell, { align: "center", onClick: (e) => e.stopPropagation(), children: (() => {
4293
- let rowActions;
4294
- if (Array.isArray(actions)) {
4295
- rowActions = actions;
4296
- } else {
4297
- const result = actions(row, actualIndex);
4298
- if (Array.isArray(result)) {
4299
- rowActions = result;
4300
- } else {
4301
- return result;
4501
+ ) : column.label
4502
+ },
4503
+ String(column.key)
4504
+ )),
4505
+ actions && /* @__PURE__ */ jsx(TableHeadCell, { align: "center", className: actionsWidth, children: actionsLabel })
4506
+ ] }) }),
4507
+ /* @__PURE__ */ jsx(TableBody, { children: displayData.map((row, rowIndex) => {
4508
+ const actualIndex = paginated ? (currentPage - 1) * pageSize + rowIndex : rowIndex;
4509
+ const isSelected = isRowSelected(actualIndex);
4510
+ return /* @__PURE__ */ jsxs(
4511
+ TableRow,
4512
+ {
4513
+ selected: isSelected,
4514
+ onClick: onRowClick ? () => onRowClick(row, actualIndex) : void 0,
4515
+ className: onRowClick ? "cursor-pointer" : "",
4516
+ children: [
4517
+ selectable && /* @__PURE__ */ jsx(TableCell, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
4518
+ checkbox_default,
4519
+ {
4520
+ checked: isSelected,
4521
+ onChange: () => handleToggleRow(actualIndex),
4522
+ ariaLabel: `Select row ${actualIndex + 1}`
4302
4523
  }
4303
- }
4304
- return /* @__PURE__ */ jsx(stack_default, { direction: "horizontal", spacing: "sm", justify: "center", children: rowActions.map((action, actionIndex) => {
4305
- if (action && typeof action === "object" && "onClick" in action) {
4306
- const actionConfig = action;
4307
- return /* @__PURE__ */ jsx(
4308
- icon_button_default,
4309
- {
4310
- icon: actionConfig.icon,
4311
- iconSize: actionConfig.iconSize || "md",
4312
- buttonStyle: "ghost",
4313
- variant: actionConfig.variant || "neutral",
4314
- iconColor: actionConfig.iconColor,
4315
- ariaLabel: actionConfig.label,
4316
- onClick: () => actionConfig.onClick(row, actualIndex)
4317
- },
4318
- actionIndex
4319
- );
4524
+ ) }),
4525
+ columns.map((column) => {
4526
+ const value = row[column.key];
4527
+ const content = renderCellContent(value, column, row, actualIndex);
4528
+ return /* @__PURE__ */ jsx(TableCell, { align: column.align, wrapText: column.wrapText, children: content }, String(column.key));
4529
+ }),
4530
+ actions && /* @__PURE__ */ jsx(TableCell, { align: "center", onClick: (e) => e.stopPropagation(), children: (() => {
4531
+ let rowActions;
4532
+ if (Array.isArray(actions)) {
4533
+ rowActions = actions;
4320
4534
  } else {
4321
- return /* @__PURE__ */ jsx("div", { children: action }, actionIndex);
4535
+ const result = actions(row, actualIndex);
4536
+ if (Array.isArray(result)) {
4537
+ rowActions = result;
4538
+ } else {
4539
+ return result;
4540
+ }
4322
4541
  }
4323
- }) });
4324
- })() })
4325
- ]
4326
- },
4327
- actualIndex
4328
- );
4329
- }) })
4330
- ] }) }),
4331
- paginated && totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-border", children: [
4332
- /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
4333
- "Page ",
4334
- currentPage,
4335
- " of ",
4336
- totalPages,
4337
- " (",
4338
- data.length,
4339
- " total rows)"
4340
- ] }),
4341
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
4342
- /* @__PURE__ */ jsx(button_default, { size: "sm", style: "outline", onClick: prevPage, disabled: !canPrevPage, children: "Previous" }),
4343
- /* @__PURE__ */ jsx(button_default, { size: "sm", style: "outline", onClick: nextPage, disabled: !canNextPage, children: "Next" })
4542
+ return /* @__PURE__ */ jsx(stack_default, { direction: "horizontal", spacing: "sm", justify: "center", children: rowActions.map((action, actionIndex) => {
4543
+ if (action && typeof action === "object" && "onClick" in action) {
4544
+ const actionConfig = action;
4545
+ const button = /* @__PURE__ */ jsx(
4546
+ icon_button_default,
4547
+ {
4548
+ icon: actionConfig.icon,
4549
+ iconSize: actionConfig.iconSize || "md",
4550
+ buttonStyle: "ghost",
4551
+ variant: actionConfig.variant || "neutral",
4552
+ iconColor: actionConfig.iconColor,
4553
+ ariaLabel: actionConfig.label,
4554
+ onClick: () => actionConfig.onClick(row, actualIndex)
4555
+ },
4556
+ actionIndex
4557
+ );
4558
+ return actionConfig.tooltip ? /* @__PURE__ */ jsx(tooltip_default, { content: actionConfig.tooltip, children: button }, actionIndex) : button;
4559
+ } else {
4560
+ return /* @__PURE__ */ jsx("div", { children: action }, actionIndex);
4561
+ }
4562
+ }) });
4563
+ })() })
4564
+ ]
4565
+ },
4566
+ actualIndex
4567
+ );
4568
+ }) })
4569
+ ] }) }),
4570
+ paginated && totalPages > 1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-border", children: [
4571
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
4572
+ "Page ",
4573
+ currentPage,
4574
+ " of ",
4575
+ totalPages,
4576
+ " (",
4577
+ filteredData.length,
4578
+ " ",
4579
+ searchQuery.trim() ? "filtered" : "total",
4580
+ " ",
4581
+ "rows",
4582
+ searchQuery.trim() && data.length !== filteredData.length ? ` of ${data.length}` : "",
4583
+ ")"
4584
+ ] }),
4585
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
4586
+ /* @__PURE__ */ jsx(button_default, { size: "sm", style: "outline", onClick: prevPage, disabled: !canPrevPage, children: "Previous" }),
4587
+ /* @__PURE__ */ jsx(button_default, { size: "sm", style: "outline", onClick: nextPage, disabled: !canNextPage, children: "Next" })
4588
+ ] })
4344
4589
  ] })
4345
4590
  ] })
4346
4591
  ] });
@@ -5538,61 +5783,6 @@ function FormField({
5538
5783
  }
5539
5784
  FormField.displayName = "FormField";
5540
5785
  var form_field_default = FormField;
5541
- function Input({
5542
- value,
5543
- defaultValue,
5544
- onChange,
5545
- onFocus,
5546
- onBlur,
5547
- placeholder,
5548
- disabled = false,
5549
- type = "text",
5550
- ariaLabel,
5551
- ref,
5552
- id,
5553
- name,
5554
- required = false,
5555
- size = "md",
5556
- width,
5557
- validationState = "default",
5558
- autoComplete,
5559
- maxLength,
5560
- minLength,
5561
- pattern,
5562
- title,
5563
- readOnly = false
5564
- }) {
5565
- const widthClass = width ? inputWidthSizes[width] : "w-full";
5566
- const inputClasses = `${getInputClasses(size, validationState)} ${widthClass}`.trim();
5567
- return /* @__PURE__ */ jsx(
5568
- "input",
5569
- {
5570
- type,
5571
- value,
5572
- defaultValue,
5573
- ref,
5574
- onChange,
5575
- onFocus,
5576
- onBlur,
5577
- placeholder,
5578
- autoComplete,
5579
- disabled,
5580
- "aria-label": ariaLabel,
5581
- id,
5582
- name,
5583
- required,
5584
- readOnly,
5585
- maxLength,
5586
- minLength,
5587
- pattern,
5588
- title,
5589
- "aria-invalid": validationState === "error",
5590
- className: inputClasses
5591
- }
5592
- );
5593
- }
5594
- Input.displayName = "Input";
5595
- var input_default = Input;
5596
5786
  function FormInput({
5597
5787
  // FormField props
5598
5788
  label,
@@ -5792,55 +5982,6 @@ function FormTextarea({
5792
5982
  }
5793
5983
  FormTextarea.displayName = "FormTextarea";
5794
5984
  var form_textarea_default = FormTextarea;
5795
- 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";
5796
- var inputResetClasses = [
5797
- "[&>input]:border-0 [&>input]:shadow-none [&>input]:rounded-none [&>input]:ring-0",
5798
- "[&>input]:focus:ring-0 [&>input]:focus:border-0 [&>input]:bg-transparent",
5799
- "[&>input]:flex-1 [&>input]:min-w-0"
5800
- ].join(" ");
5801
- var buttonResetClasses = [
5802
- "[&_button]:rounded-none [&_button]:border-0 [&_button]:shadow-none [&_button]:m-0",
5803
- "[&_button]:h-full"
5804
- ].join(" ");
5805
- function InputGroup({
5806
- children,
5807
- prefix,
5808
- suffix,
5809
- validationState = "default",
5810
- disabled = false,
5811
- className
5812
- }) {
5813
- const isTextPrefix = typeof prefix === "string" || typeof prefix === "number";
5814
- const isTextSuffix = typeof suffix === "string" || typeof suffix === "number";
5815
- const borderClass = validationState === "default" ? "border-input focus-within:border-ring" : validationBorderClasses[validationState].split(" ")[0];
5816
- const disabledClass = disabled ? "opacity-50 cursor-not-allowed" : "";
5817
- const enhancedChild = isValidElement(children) && disabled ? cloneElement(children, { disabled: true }) : children;
5818
- return /* @__PURE__ */ jsxs(
5819
- "div",
5820
- {
5821
- className: `${containerBaseClasses} ${borderClass} ${inputResetClasses} ${buttonResetClasses} ${disabledClass} ${className ?? ""}`.trim(),
5822
- children: [
5823
- prefix && /* @__PURE__ */ jsx(
5824
- "div",
5825
- {
5826
- className: `flex items-center shrink-0 ${isTextPrefix ? "px-3 bg-muted/50 text-muted-foreground text-sm" : "px-3 text-muted-foreground"}`,
5827
- children: prefix
5828
- }
5829
- ),
5830
- enhancedChild,
5831
- suffix && /* @__PURE__ */ jsx(
5832
- "div",
5833
- {
5834
- className: isTextSuffix ? "flex items-center px-3 bg-muted/50 text-muted-foreground text-sm shrink-0" : "flex items-stretch shrink-0",
5835
- children: suffix
5836
- }
5837
- )
5838
- ]
5839
- }
5840
- );
5841
- }
5842
- InputGroup.displayName = "InputGroup";
5843
- var input_group_default = InputGroup;
5844
5985
  function MultiSelect({
5845
5986
  options,
5846
5987
  value = [],