@hyddenlabs/hydn-ui 0.3.0-alpha.186 → 0.3.0-alpha.188

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.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
- import React__default, { ReactNode, ComponentProps, MouseEvent, HTMLAttributes, CSSProperties, FormEvent, RefObject } from 'react';
3
+ import React__default, { ReactNode, ComponentProps, MouseEvent, ComponentType, HTMLAttributes, CSSProperties, FormEvent, RefObject } from 'react';
4
4
 
5
5
  declare const colors: {
6
6
  background: string;
@@ -1595,6 +1595,14 @@ type ButtonProps = {
1595
1595
  children?: React__default.ReactNode;
1596
1596
  /** Click event handler */
1597
1597
  onClick?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1598
+ /** Mouse enter event handler */
1599
+ onMouseEnter?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1600
+ /** Mouse leave event handler */
1601
+ onMouseLeave?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1602
+ /** Mouse down event handler */
1603
+ onMouseDown?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1604
+ /** Blur event handler */
1605
+ onBlur?: (e: React__default.FocusEvent<HTMLButtonElement>) => void;
1598
1606
  /** Accessible label for icon-only buttons (required when no children) */
1599
1607
  ariaLabel?: string;
1600
1608
  /** Disables button interaction and applies disabled styling */
@@ -2020,6 +2028,10 @@ type BreadcrumbItem = {
2020
2028
  label: string;
2021
2029
  /** Optional navigation link (last item typically has no href) */
2022
2030
  href?: string;
2031
+ /** Optional click handler for client-side navigation */
2032
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
2033
+ /** Additional props passed to the link component (e.g., 'to' for React Router Link) */
2034
+ [key: string]: unknown;
2023
2035
  };
2024
2036
  type BreadcrumbsProps = {
2025
2037
  /** Array of breadcrumb items to display in hierarchical order */
@@ -2028,11 +2040,40 @@ type BreadcrumbsProps = {
2028
2040
  separator?: ReactNode;
2029
2041
  /** Additional CSS classes for the breadcrumb container */
2030
2042
  className?: string;
2043
+ /** Custom link component (e.g., React Router Link) for client-side navigation */
2044
+ linkComponent?: ComponentType<{
2045
+ className?: string;
2046
+ onClick?: (e: MouseEvent<HTMLAnchorElement>) => void;
2047
+ [key: string]: unknown;
2048
+ }>;
2031
2049
  };
2032
2050
  /**
2033
2051
  * Breadcrumbs - Hierarchical path display
2052
+ *
2053
+ * @example
2054
+ * // With onClick handlers
2055
+ * <Breadcrumbs
2056
+ * items={[
2057
+ * { label: 'Home', href: '/', onClick: () => navigate('/') },
2058
+ * { label: 'Products', href: '/products', onClick: () => navigate('/products') },
2059
+ * { label: 'Item' }
2060
+ * ]}
2061
+ * />
2062
+ *
2063
+ * @example
2064
+ * // With React Router Link component
2065
+ * import { Link } from 'react-router-dom';
2066
+ *
2067
+ * <Breadcrumbs
2068
+ * linkComponent={Link}
2069
+ * items={[
2070
+ * { label: 'Home', to: '/' },
2071
+ * { label: 'Products', to: '/products' },
2072
+ * { label: 'Item' }
2073
+ * ]}
2074
+ * />
2034
2075
  */
2035
- declare function Breadcrumbs({ items, separator, className }: Readonly<BreadcrumbsProps>): react_jsx_runtime.JSX.Element;
2076
+ declare function Breadcrumbs({ items, separator, className, linkComponent }: Readonly<BreadcrumbsProps>): react_jsx_runtime.JSX.Element;
2036
2077
  declare namespace Breadcrumbs {
2037
2078
  var displayName: string;
2038
2079
  }
@@ -2551,6 +2592,8 @@ type DataTableAction<T> = {
2551
2592
  iconColor?: StatusColorProp;
2552
2593
  /** Accessible label for the action (shown in tooltip or screen readers) */
2553
2594
  label: string;
2595
+ /** Tooltip text to display on hover. If not provided, label will be used for aria-label only. */
2596
+ tooltip?: string;
2554
2597
  /** Callback when the action is clicked */
2555
2598
  onClick: (row: T, index: number) => void;
2556
2599
  /** Visual variant for the action button */
@@ -2589,6 +2632,8 @@ type ColumnDef<T> = {
2589
2632
  chipVariant?: StatusColorProp;
2590
2633
  /** Size for badge or chip rendering */
2591
2634
  componentSize?: 'sm' | 'md' | 'lg';
2635
+ /** Fallback value to display when cell value is null, undefined, or empty string */
2636
+ fallback?: string;
2592
2637
  };
2593
2638
  type DataTableProps<T> = {
2594
2639
  /** Array of data objects to display in the table */
@@ -3344,6 +3389,8 @@ interface IconButtonProps extends Omit<ButtonProps, 'icon' | 'style' | 'children
3344
3389
  iconSize?: IconSize;
3345
3390
  iconColor?: StatusColorProp | 'currentColor';
3346
3391
  buttonStyle?: ButtonProps['style'];
3392
+ /** Icon to display on hover (if not provided, hover will keep the same icon) */
3393
+ hoverIcon?: string;
3347
3394
  children?: never;
3348
3395
  }
3349
3396
  /**
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
- import React__default, { ReactNode, ComponentProps, MouseEvent, HTMLAttributes, CSSProperties, FormEvent, RefObject } from 'react';
3
+ import React__default, { ReactNode, ComponentProps, MouseEvent, ComponentType, HTMLAttributes, CSSProperties, FormEvent, RefObject } from 'react';
4
4
 
5
5
  declare const colors: {
6
6
  background: string;
@@ -1595,6 +1595,14 @@ type ButtonProps = {
1595
1595
  children?: React__default.ReactNode;
1596
1596
  /** Click event handler */
1597
1597
  onClick?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1598
+ /** Mouse enter event handler */
1599
+ onMouseEnter?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1600
+ /** Mouse leave event handler */
1601
+ onMouseLeave?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1602
+ /** Mouse down event handler */
1603
+ onMouseDown?: (e: React__default.MouseEvent<HTMLButtonElement>) => void;
1604
+ /** Blur event handler */
1605
+ onBlur?: (e: React__default.FocusEvent<HTMLButtonElement>) => void;
1598
1606
  /** Accessible label for icon-only buttons (required when no children) */
1599
1607
  ariaLabel?: string;
1600
1608
  /** Disables button interaction and applies disabled styling */
@@ -2020,6 +2028,10 @@ type BreadcrumbItem = {
2020
2028
  label: string;
2021
2029
  /** Optional navigation link (last item typically has no href) */
2022
2030
  href?: string;
2031
+ /** Optional click handler for client-side navigation */
2032
+ onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
2033
+ /** Additional props passed to the link component (e.g., 'to' for React Router Link) */
2034
+ [key: string]: unknown;
2023
2035
  };
2024
2036
  type BreadcrumbsProps = {
2025
2037
  /** Array of breadcrumb items to display in hierarchical order */
@@ -2028,11 +2040,40 @@ type BreadcrumbsProps = {
2028
2040
  separator?: ReactNode;
2029
2041
  /** Additional CSS classes for the breadcrumb container */
2030
2042
  className?: string;
2043
+ /** Custom link component (e.g., React Router Link) for client-side navigation */
2044
+ linkComponent?: ComponentType<{
2045
+ className?: string;
2046
+ onClick?: (e: MouseEvent<HTMLAnchorElement>) => void;
2047
+ [key: string]: unknown;
2048
+ }>;
2031
2049
  };
2032
2050
  /**
2033
2051
  * Breadcrumbs - Hierarchical path display
2052
+ *
2053
+ * @example
2054
+ * // With onClick handlers
2055
+ * <Breadcrumbs
2056
+ * items={[
2057
+ * { label: 'Home', href: '/', onClick: () => navigate('/') },
2058
+ * { label: 'Products', href: '/products', onClick: () => navigate('/products') },
2059
+ * { label: 'Item' }
2060
+ * ]}
2061
+ * />
2062
+ *
2063
+ * @example
2064
+ * // With React Router Link component
2065
+ * import { Link } from 'react-router-dom';
2066
+ *
2067
+ * <Breadcrumbs
2068
+ * linkComponent={Link}
2069
+ * items={[
2070
+ * { label: 'Home', to: '/' },
2071
+ * { label: 'Products', to: '/products' },
2072
+ * { label: 'Item' }
2073
+ * ]}
2074
+ * />
2034
2075
  */
2035
- declare function Breadcrumbs({ items, separator, className }: Readonly<BreadcrumbsProps>): react_jsx_runtime.JSX.Element;
2076
+ declare function Breadcrumbs({ items, separator, className, linkComponent }: Readonly<BreadcrumbsProps>): react_jsx_runtime.JSX.Element;
2036
2077
  declare namespace Breadcrumbs {
2037
2078
  var displayName: string;
2038
2079
  }
@@ -2551,6 +2592,8 @@ type DataTableAction<T> = {
2551
2592
  iconColor?: StatusColorProp;
2552
2593
  /** Accessible label for the action (shown in tooltip or screen readers) */
2553
2594
  label: string;
2595
+ /** Tooltip text to display on hover. If not provided, label will be used for aria-label only. */
2596
+ tooltip?: string;
2554
2597
  /** Callback when the action is clicked */
2555
2598
  onClick: (row: T, index: number) => void;
2556
2599
  /** Visual variant for the action button */
@@ -2589,6 +2632,8 @@ type ColumnDef<T> = {
2589
2632
  chipVariant?: StatusColorProp;
2590
2633
  /** Size for badge or chip rendering */
2591
2634
  componentSize?: 'sm' | 'md' | 'lg';
2635
+ /** Fallback value to display when cell value is null, undefined, or empty string */
2636
+ fallback?: string;
2592
2637
  };
2593
2638
  type DataTableProps<T> = {
2594
2639
  /** Array of data objects to display in the table */
@@ -3344,6 +3389,8 @@ interface IconButtonProps extends Omit<ButtonProps, 'icon' | 'style' | 'children
3344
3389
  iconSize?: IconSize;
3345
3390
  iconColor?: StatusColorProp | 'currentColor';
3346
3391
  buttonStyle?: ButtonProps['style'];
3392
+ /** Icon to display on hover (if not provided, hover will keep the same icon) */
3393
+ hoverIcon?: string;
3347
3394
  children?: never;
3348
3395
  }
3349
3396
  /**
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",
@@ -2813,15 +2886,21 @@ var PageTransition = ({
2813
2886
  };
2814
2887
  PageTransition.displayName = "PageTransition";
2815
2888
  var page_transition_default = PageTransition;
2816
- function Breadcrumbs({ items, separator = "/", className = "" }) {
2889
+ function Breadcrumbs({ items, separator = "/", className = "", linkComponent }) {
2890
+ const LinkComponent = linkComponent || "a";
2817
2891
  return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx("ol", { className: "flex items-center space-x-2 text-sm", children: items.map((item, index) => {
2818
2892
  const isLast = index === items.length - 1;
2819
2893
  const key = item.href || item.label;
2894
+ const { label: _label, onClick, href, ...linkProps } = item;
2895
+ const hasLinkProps = href || onClick || Object.keys(linkProps).length > 0;
2896
+ const shouldRenderLink = hasLinkProps && !isLast;
2820
2897
  return /* @__PURE__ */ jsxs("li", { className: "flex items-center", children: [
2821
- item.href && !isLast ? /* @__PURE__ */ jsx(
2822
- "a",
2898
+ shouldRenderLink ? /* @__PURE__ */ jsx(
2899
+ LinkComponent,
2823
2900
  {
2824
- href: item.href,
2901
+ ...href ? { href } : {},
2902
+ ...linkProps,
2903
+ onClick,
2825
2904
  className: "text-primary hover:text-primary/80 hover:underline cursor-pointer transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-ring rounded px-1 -mx-1",
2826
2905
  children: item.label
2827
2906
  }
@@ -4181,6 +4260,10 @@ function DataTable({
4181
4260
  }
4182
4261
  };
4183
4262
  const renderCellContent = (value, column, row, rowIndex) => {
4263
+ const isEmpty = value == null || value === "";
4264
+ if (isEmpty && column.fallback !== void 0) {
4265
+ return column.fallback;
4266
+ }
4184
4267
  if (column.render) {
4185
4268
  return column.render(value, row, rowIndex);
4186
4269
  }
@@ -4294,7 +4377,7 @@ function DataTable({
4294
4377
  return /* @__PURE__ */ jsx(stack_default, { direction: "horizontal", spacing: "sm", justify: "center", children: rowActions.map((action, actionIndex) => {
4295
4378
  if (action && typeof action === "object" && "onClick" in action) {
4296
4379
  const actionConfig = action;
4297
- return /* @__PURE__ */ jsx(
4380
+ const button = /* @__PURE__ */ jsx(
4298
4381
  icon_button_default,
4299
4382
  {
4300
4383
  icon: actionConfig.icon,
@@ -4307,6 +4390,7 @@ function DataTable({
4307
4390
  },
4308
4391
  actionIndex
4309
4392
  );
4393
+ return actionConfig.tooltip ? /* @__PURE__ */ jsx(tooltip_default, { content: actionConfig.tooltip, children: button }, actionIndex) : button;
4310
4394
  } else {
4311
4395
  return /* @__PURE__ */ jsx("div", { children: action }, actionIndex);
4312
4396
  }