@donotdev/components 0.0.16 → 0.0.18

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.
Files changed (97) hide show
  1. package/dist/advanced/Bento/Bento.d.ts +1 -1
  2. package/dist/advanced/Bento/Bento.js +1 -1
  3. package/dist/advanced/Code/CodeContent.d.ts.map +1 -1
  4. package/dist/advanced/Code/CodeContent.js +23 -6
  5. package/dist/advanced/Code/CodeSkeleton.js +4 -4
  6. package/dist/advanced/ImageGallery/ImageGallery.d.ts.map +1 -1
  7. package/dist/advanced/ImageGallery/ImageGallery.js +11 -5
  8. package/dist/advanced/JsonViewer/JsonViewer.d.ts +1 -1
  9. package/dist/advanced/JsonViewer/JsonViewer.d.ts.map +1 -1
  10. package/dist/advanced/JsonViewer/JsonViewer.js +9 -3
  11. package/dist/atomic/ActionButton/index.js +2 -2
  12. package/dist/atomic/ActionButton/useAction.d.ts.map +1 -1
  13. package/dist/atomic/ActionButton/useAction.js +18 -5
  14. package/dist/atomic/Alert/index.d.ts +1 -1
  15. package/dist/atomic/Alert/index.d.ts.map +1 -1
  16. package/dist/atomic/Alert/index.js +1 -1
  17. package/dist/atomic/Badge/index.d.ts +1 -1
  18. package/dist/atomic/Button/index.d.ts +2 -2
  19. package/dist/atomic/Button/index.d.ts.map +1 -1
  20. package/dist/atomic/CallToAction/index.d.ts +2 -1
  21. package/dist/atomic/CallToAction/index.d.ts.map +1 -1
  22. package/dist/atomic/CallToAction/index.js +2 -1
  23. package/dist/atomic/Combobox/index.d.ts.map +1 -1
  24. package/dist/atomic/Combobox/index.js +3 -3
  25. package/dist/atomic/CopyToClipboard/index.d.ts.map +1 -1
  26. package/dist/atomic/CopyToClipboard/index.js +20 -4
  27. package/dist/atomic/Dialog/index.js +1 -1
  28. package/dist/atomic/DropdownMenu/DropdownMenuPrimitive.d.ts.map +1 -1
  29. package/dist/atomic/DropdownMenu/DropdownMenuPrimitive.js +5 -21
  30. package/dist/atomic/DropdownMenu/index.d.ts.map +1 -1
  31. package/dist/atomic/DropdownMenu/index.js +7 -17
  32. package/dist/atomic/Grid/GridArea.d.ts +2 -2
  33. package/dist/atomic/Grid/GridArea.js +2 -2
  34. package/dist/atomic/Grid/index.d.ts +39 -22
  35. package/dist/atomic/Grid/index.d.ts.map +1 -1
  36. package/dist/atomic/Grid/index.js +56 -27
  37. package/dist/atomic/HeroSection/index.d.ts +3 -0
  38. package/dist/atomic/HeroSection/index.d.ts.map +1 -1
  39. package/dist/atomic/HeroSection/index.js +5 -2
  40. package/dist/atomic/HoverCard/HoverCardPrimitive.d.ts.map +1 -1
  41. package/dist/atomic/HoverCard/HoverCardPrimitive.js +1 -1
  42. package/dist/atomic/HoverCard/index.d.ts +19 -4
  43. package/dist/atomic/HoverCard/index.d.ts.map +1 -1
  44. package/dist/atomic/HoverCard/index.js +24 -5
  45. package/dist/atomic/Icons/Icon.d.ts.map +1 -1
  46. package/dist/atomic/Icons/Icon.js +11 -10
  47. package/dist/atomic/InfiniteScroll/index.d.ts +4 -2
  48. package/dist/atomic/InfiniteScroll/index.d.ts.map +1 -1
  49. package/dist/atomic/InfiniteScroll/index.js +2 -2
  50. package/dist/atomic/Pagination/index.js +1 -1
  51. package/dist/atomic/Popover/PopoverPrimitive.d.ts +1 -1
  52. package/dist/atomic/Popover/PopoverPrimitive.d.ts.map +1 -1
  53. package/dist/atomic/Popover/PopoverPrimitive.js +2 -2
  54. package/dist/atomic/Popover/index.d.ts +2 -2
  55. package/dist/atomic/Popover/index.d.ts.map +1 -1
  56. package/dist/atomic/Rating/index.d.ts +1 -1
  57. package/dist/atomic/Rating/index.d.ts.map +1 -1
  58. package/dist/atomic/Section/index.d.ts +9 -6
  59. package/dist/atomic/Section/index.d.ts.map +1 -1
  60. package/dist/atomic/Section/index.js +3 -2
  61. package/dist/atomic/Select/index.d.ts.map +1 -1
  62. package/dist/atomic/Select/index.js +2 -3
  63. package/dist/atomic/Stack/index.d.ts +2 -2
  64. package/dist/atomic/Stack/index.js +2 -2
  65. package/dist/atomic/Stepper/index.d.ts +5 -1
  66. package/dist/atomic/Stepper/index.d.ts.map +1 -1
  67. package/dist/atomic/Stepper/index.js +9 -6
  68. package/dist/atomic/Table/index.d.ts +27 -5
  69. package/dist/atomic/Table/index.d.ts.map +1 -1
  70. package/dist/atomic/Table/index.js +55 -6
  71. package/dist/atomic/Tabs/index.d.ts +1 -1
  72. package/dist/atomic/Tag/index.d.ts +1 -1
  73. package/dist/atomic/Text/index.d.ts +2 -0
  74. package/dist/atomic/Text/index.d.ts.map +1 -1
  75. package/dist/atomic/Text/index.js +2 -1
  76. package/dist/atomic/Toaster/ToastPrimitive.d.ts +1 -1
  77. package/dist/atomic/Toaster/ToastPrimitive.d.ts.map +1 -1
  78. package/dist/atomic/Toaster/ToastPrimitive.js +1 -13
  79. package/dist/atomic/Toggle/index.d.ts +1 -1
  80. package/dist/atomic/index.d.ts +1 -1
  81. package/dist/atomic/index.d.ts.map +1 -1
  82. package/dist/hooks/useToast.d.ts.map +1 -1
  83. package/dist/hooks/useToast.js +18 -3
  84. package/dist/hooks/useViewportVisibility.d.ts.map +1 -1
  85. package/dist/hooks/useViewportVisibility.js +10 -12
  86. package/dist/index.d.ts +0 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +6 -4
  89. package/dist/styles/index.css +259 -96
  90. package/dist/types.d.ts +1 -1
  91. package/dist/utils/constants.d.ts +13 -0
  92. package/dist/utils/constants.d.ts.map +1 -1
  93. package/dist/utils/constants.js +12 -0
  94. package/dist/utils/intersectionObserver.d.ts.map +1 -1
  95. package/dist/utils/intersectionObserver.js +1 -11
  96. package/dist/utils/variants.d.ts +1 -1
  97. package/package.json +3 -3
@@ -11,7 +11,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
11
  * @author AMBROISE PARK Consulting
12
12
  */
13
13
  import { ChevronRight, Check } from 'lucide-react';
14
- import { Children, isValidElement } from 'react';
14
+ import { Children } from 'react';
15
15
  import { DropdownMenuPrimitive, DropdownMenuTriggerPrimitive, DropdownMenuContentPrimitive, DropdownMenuItemPrimitive, DropdownMenuSubPrimitive, DropdownMenuSubTriggerPrimitive, DropdownMenuSubContentPrimitive, DropdownMenuPortalPrimitive, DropdownMenuLabelPrimitive, DropdownMenuSeparatorPrimitive, } from './DropdownMenuPrimitive';
16
16
  import { cn } from '../../utils/helpers';
17
17
  import ScrollArea from '../ScrollArea';
@@ -48,22 +48,12 @@ const getIconOnlyAriaLabel = (hasIcon, hasLabel, label, fallback) => {
48
48
  const DropdownMenu = ({ trigger, items = [], children, contentWidth, contentAlign = 'start', open, onOpenChange, }) => {
49
49
  if (!trigger)
50
50
  return null;
51
- // Normalize children to ensure keys (React.Children.toArray handles this automatically)
52
51
  const normalizedChildren = children ? Children.toArray(children) : [];
53
- // Wrap children in DropdownMenuItemPrimitive so they trigger auto-close behavior
54
- // This ensures clicking any child (like GoTo button) closes the dropdown
55
- const wrappedChildren = normalizedChildren.map((child, index) => {
56
- // Check if child is already a menu item by checking for data-role attribute
57
- // (our DropdownMenuItemPrimitive sets data-role="menu-item")
58
- if (isValidElement(child) &&
59
- child.props?.['data-role'] === 'menu-item') {
60
- // Already a menu item, don't wrap
61
- return child;
62
- }
63
- // Wrap child in DropdownMenuItemPrimitive for auto-close behavior
64
- // Using asChild merges props correctly with the child component
65
- return (_jsx(DropdownMenuItemPrimitive, { className: "dndev-interactive", asChild: true, children: child }, index));
66
- });
52
+ // Wrap children in DropdownMenuItemPrimitive (without asChild).
53
+ // Radix renders its own wrapper element with proper onSelect auto-close.
54
+ // asChild doesn't work here because components (GoTo, ThemeToggle, etc.)
55
+ // don't forward Radix's merged event handlers to the DOM.
56
+ const wrappedChildren = normalizedChildren.map((child, index) => (_jsx(DropdownMenuItemPrimitive, { children: child }, index)));
67
57
  const content = (_jsxs(_Fragment, { children: [wrappedChildren, items.length > 0 &&
68
58
  items.map((item, index) => {
69
59
  // Label item
@@ -84,7 +74,7 @@ const DropdownMenu = ({ trigger, items = [], children, contentWidth, contentAlig
84
74
  !hasSubLabel && { 'data-display': 'compact' }), children: [Icon && _jsx(Icon, {}), _jsx("span", { children: submenuItem.label }), _jsx(ChevronRight, { className: "dndev-dropdown-menu-trailing" })] }), _jsx(DropdownMenuPortalPrimitive, { children: _jsx(DropdownMenuSubContentPrimitive, { className: cn('dndev-floating dndev-z-tooltip', submenuItem.subContent
85
75
  ? 'dndev-dropdown-sub-content-custom'
86
76
  : ''), children: submenuItem.subContent ||
87
- submenuItem.subItems.map((subItem, subIndex) => {
77
+ submenuItem.subItems?.map((subItem, subIndex) => {
88
78
  // Handle label/separator in submenu
89
79
  if (subItem.type === 'label') {
90
80
  return (_jsx(DropdownMenuLabelPrimitive, { className: cn('dndev-menu-label', subItem.className), children: subItem.label }, subIndex));
@@ -9,7 +9,7 @@
9
9
  * @example
10
10
  * ```tsx
11
11
  * // Generic grid areas (default)
12
- * <Grid areas="left center right" templateColumns="1fr auto 1fr">
12
+ * <Grid areas="left center right" cols=fr">
13
13
  * <GridArea name="left">{leftContent}</GridArea>
14
14
  * <GridArea name="center">{centerContent}</GridArea>
15
15
  * <GridArea name="right">{rightContent}</GridArea>
@@ -19,7 +19,7 @@
19
19
  * @example
20
20
  * ```tsx
21
21
  * // Semantic grid layout
22
- * <Grid areas="header main sidebar footer" templateColumns="1fr 3fr 1fr">
22
+ * <Grid areas="header main sidebar footer" cols=r">
23
23
  * <GridArea as="header" name="header">Header</GridArea>
24
24
  * <GridArea as="main" name="main">Main Content</GridArea>
25
25
  * <GridArea as="aside" name="sidebar">Sidebar</GridArea>
@@ -10,7 +10,7 @@
10
10
  * @example
11
11
  * ```tsx
12
12
  * // Generic grid areas (default)
13
- * <Grid areas="left center right" templateColumns="1fr auto 1fr">
13
+ * <Grid areas="left center right" cols=fr">
14
14
  * <GridArea name="left">{leftContent}</GridArea>
15
15
  * <GridArea name="center">{centerContent}</GridArea>
16
16
  * <GridArea name="right">{rightContent}</GridArea>
@@ -20,7 +20,7 @@
20
20
  * @example
21
21
  * ```tsx
22
22
  * // Semantic grid layout
23
- * <Grid areas="header main sidebar footer" templateColumns="1fr 3fr 1fr">
23
+ * <Grid areas="header main sidebar footer" cols=r">
24
24
  * <GridArea as="header" name="header">Header</GridArea>
25
25
  * <GridArea as="main" name="main">Main Content</GridArea>
26
26
  * <GridArea as="aside" name="sidebar">Sidebar</GridArea>
@@ -5,29 +5,37 @@
5
5
  * @example
6
6
  * ```tsx
7
7
  * // Fixed 3-column grid
8
- * <Grid cols={3} gap="medium">
8
+ * <Grid cols={3}>
9
9
  * <Card />
10
10
  * <Card />
11
11
  * <Card />
12
12
  * </Grid>
13
13
  *
14
- * // Responsive grid: [mobile, tablet, laptop, desktop]
15
- * // 1 col on mobile/tablet, 2 on laptop, 3 on desktop
16
- * <Grid cols={[1, 1, 2, 3]} gap="medium">
14
+ * // Responsive equal columns: [mobile, tablet, laptop, desktop]
15
+ * <Grid cols={[1, 1, 2, 3]}>
17
16
  * <Card />
18
17
  * <Card />
19
18
  * <Card />
20
19
  * </Grid>
21
20
  *
22
- * // Named grid areas
23
- * <Grid areas="left center right" templateColumns="1fr auto 1fr">
21
+ * // Custom column template (static)
22
+ * <Grid cols="1fr auto 1fr" areas="left center right">
24
23
  * <GridArea name="left">{left}</GridArea>
25
24
  * <GridArea name="center">{center}</GridArea>
26
25
  * <GridArea name="right">{right}</GridArea>
27
26
  * </Grid>
27
+ *
28
+ * // Custom column template (responsive) + responsive areas
29
+ * <Grid
30
+ * cols={["1fr", "1fr", "1fr 3fr", "1fr 3fr"]}
31
+ * areas={['"a" "b"', '"a" "b"', '"a b"', '"a b"']}
32
+ * >
33
+ * <GridArea name="a">{left}</GridArea>
34
+ * <GridArea name="b">{right}</GridArea>
35
+ * </Grid>
28
36
  * ```
29
37
  *
30
- * @version 0.0.4
38
+ * @version 0.0.5
31
39
  * @since 0.0.1
32
40
  * @author AMBROISE PARK Consulting
33
41
  */
@@ -38,6 +46,15 @@ import './Grid.css';
38
46
  * @example [1, 1, 2, 3] - 1 col on mobile/tablet, 2 on laptop, 3 on desktop
39
47
  */
40
48
  export type ResponsiveCols = [number, number, number, number];
49
+ /**
50
+ * Responsive template array: [mobile, tablet, laptop, desktop]
51
+ * @example ["1fr", "1fr", "1fr 3fr", "1fr 3fr"] - stacked on mobile/tablet, 1:3 ratio on laptop/desktop
52
+ */
53
+ export type ResponsiveTemplate = [string, string, string, string];
54
+ /**
55
+ * Unified column type: equal columns (number) or custom template (string), static or responsive
56
+ */
57
+ export type GridCols = number | string | ResponsiveCols | ResponsiveTemplate;
41
58
  /**
42
59
  * Grid-specific props (layout directives)
43
60
  */
@@ -49,15 +66,18 @@ interface GridOwnProps {
49
66
  */
50
67
  as?: ElementType;
51
68
  /**
52
- * Number of columns - fixed or responsive
53
- * - number: fixed columns (same on all breakpoints)
54
- * - [mobile, tablet, laptop, desktop]: responsive columns per breakpoint
69
+ * Column layout unified prop for all column patterns:
70
+ * - number: fixed equal columns → repeat(N, 1fr)
71
+ * - string: custom template raw grid-template-columns value
72
+ * - [number x4]: responsive equal columns per breakpoint
73
+ * - [string x4]: responsive custom template per breakpoint
55
74
  * @default 1
56
- * @example 3 - always 3 columns
57
- * @example [1, 1, 2, 3] - 1 col mobile/tablet, 2 laptop, 3 desktop
58
- * @example [1, 2, 3, 3] - 1 mobile, 2 tablet, 3 laptop/desktop
75
+ * @example 3 - always 3 equal columns
76
+ * @example "1fr 3fr" - custom ratio
77
+ * @example [1, 1, 2, 3] - responsive equal: 1 mobile/tablet, 2 laptop, 3 desktop
78
+ * @example ["1fr", "1fr", "1fr 3fr", "1fr 3fr"] - responsive template: stacked mobile, 1:3 desktop
59
79
  */
60
- cols?: number | ResponsiveCols;
80
+ cols?: GridCols;
61
81
  /**
62
82
  * Spacing between items
63
83
  * @default 'medium'
@@ -76,15 +96,12 @@ interface GridOwnProps {
76
96
  /**
77
97
  * Named grid areas (CSS grid-template-areas)
78
98
  * Use with GridArea component for semantic grid layouts
79
- * @example "left center right", "left right", "header header" / "sidebar main"
80
- */
81
- areas?: string;
82
- /**
83
- * Grid template columns (CSS grid-template-columns)
84
- * Required when using `areas` prop
85
- * @example "1fr auto 1fr", "1fr auto", "200px 1fr"
99
+ * - string: static areas (same on all breakpoints)
100
+ * - [mobile, tablet, laptop, desktop]: responsive areas per breakpoint
101
+ * @example "left center right"
102
+ * @example ['"a" "b"', '"a" "b"', '"a b"', '"a b"'] - stacked mobile, side-by-side desktop
86
103
  */
87
- templateColumns?: string;
104
+ areas?: string | ResponsiveTemplate;
88
105
  /** Content */
89
106
  children: ReactNode;
90
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Grid/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAIf,OAAO,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9D;;GAEG;AACH,UAAU,YAAY;IACpB;;;;OAIG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;IAEjB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,cAAc,CAAC;IAE/B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAE5C;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAE/C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAEjD;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,cAAc;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,KAAK,IAAI,YAAY,GACjE,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,MAAM,YAAY,CAAC,CAAC;AAErD;;;;;GAKG;AACH,QAAA,MAAM,IAAI,uHA2DT,CAAC;AAIF,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/Grid/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AAIf,OAAO,YAAY,CAAC;AAEpB;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAElE;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,GAAG,kBAAkB,CAAC;AAE7E;;GAEG;AACH,UAAU,YAAY;IACpB;;;;OAIG;IACH,EAAE,CAAC,EAAE,WAAW,CAAC;IAEjB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAE5C;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAE/C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;IAEjD;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAC;IAEpC,cAAc;IACd,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,KAAK,IAAI,YAAY,GACjE,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,MAAM,YAAY,CAAC,CAAC;AAErD;;;;;GAKG;AACH,QAAA,MAAM,IAAI,uHA8ET,CAAC;AAIF,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,eAAe,IAAI,CAAC"}
@@ -6,29 +6,37 @@
6
6
  * @example
7
7
  * ```tsx
8
8
  * // Fixed 3-column grid
9
- * <Grid cols={3} gap="medium">
9
+ * <Grid cols={3}>
10
10
  * <Card />
11
11
  * <Card />
12
12
  * <Card />
13
13
  * </Grid>
14
14
  *
15
- * // Responsive grid: [mobile, tablet, laptop, desktop]
16
- * // 1 col on mobile/tablet, 2 on laptop, 3 on desktop
17
- * <Grid cols={[1, 1, 2, 3]} gap="medium">
15
+ * // Responsive equal columns: [mobile, tablet, laptop, desktop]
16
+ * <Grid cols={[1, 1, 2, 3]}>
18
17
  * <Card />
19
18
  * <Card />
20
19
  * <Card />
21
20
  * </Grid>
22
21
  *
23
- * // Named grid areas
24
- * <Grid areas="left center right" templateColumns="1fr auto 1fr">
22
+ * // Custom column template (static)
23
+ * <Grid cols="1fr auto 1fr" areas="left center right">
25
24
  * <GridArea name="left">{left}</GridArea>
26
25
  * <GridArea name="center">{center}</GridArea>
27
26
  * <GridArea name="right">{right}</GridArea>
28
27
  * </Grid>
28
+ *
29
+ * // Custom column template (responsive) + responsive areas
30
+ * <Grid
31
+ * cols={["1fr", "1fr", "1fr 3fr", "1fr 3fr"]}
32
+ * areas={['"a" "b"', '"a" "b"', '"a b"', '"a b"']}
33
+ * >
34
+ * <GridArea name="a">{left}</GridArea>
35
+ * <GridArea name="b">{right}</GridArea>
36
+ * </Grid>
29
37
  * ```
30
38
  *
31
- * @version 0.0.4
39
+ * @version 0.0.5
32
40
  * @since 0.0.1
33
41
  * @author AMBROISE PARK Consulting
34
42
  */
@@ -42,38 +50,59 @@ import './Grid.css';
42
50
  * Polymorphic CSS Grid layout primitive.
43
51
  * Can render as any HTML element while maintaining grid layout.
44
52
  */
45
- const Grid = forwardRef(({ as = 'div', cols = 1, gap = GAP_VARIANT.MEDIUM, align = 'stretch', justify = 'stretch', areas, templateColumns, className, style, children, ...props }, ref) => {
53
+ const Grid = forwardRef(({ as = 'div', cols = 1, gap = GAP_VARIANT.MEDIUM, align = 'stretch', justify = 'stretch', areas, className, style, children, ...props }, ref) => {
46
54
  const Component = as;
47
- // Parse cols into responsive values
48
- const isResponsive = Array.isArray(cols);
49
- const [colsMobile, colsTablet, colsLaptop, colsDesktop] = isResponsive
50
- ? cols
51
- : [cols, cols, cols, cols];
55
+ // Detect which cols variant we're dealing with
56
+ const isArray = Array.isArray(cols);
57
+ const isResponsiveEqual = isArray && typeof cols[0] === 'number';
58
+ const isResponsiveTpl = isArray && typeof cols[0] === 'string';
59
+ const isStaticTpl = typeof cols === 'string';
60
+ const isResponsiveAreas = Array.isArray(areas);
52
61
  const customStyle = {
53
62
  display: 'grid',
54
63
  width: '100%',
55
- // Set CSS custom properties for responsive columns
56
- '--grid-cols-mobile': colsMobile,
57
- '--grid-cols-tablet': colsTablet,
58
- '--grid-cols-laptop': colsLaptop,
59
- '--grid-cols-desktop': colsDesktop,
60
64
  ...style,
61
- ...(areas
62
- ? {
63
- gridTemplateAreas: areas.trim().startsWith('"')
64
- ? areas
65
- : `"${areas}"`,
66
- }
67
- : {}),
68
- ...(templateColumns && { gridTemplateColumns: templateColumns }),
69
65
  };
66
+ if (isResponsiveTpl) {
67
+ const tpl = cols;
68
+ customStyle['--grid-tpl-mobile'] = tpl[0];
69
+ customStyle['--grid-tpl-tablet'] = tpl[1];
70
+ customStyle['--grid-tpl-laptop'] = tpl[2];
71
+ customStyle['--grid-tpl-desktop'] = tpl[3];
72
+ }
73
+ else if (isStaticTpl) {
74
+ customStyle.gridTemplateColumns = cols;
75
+ }
76
+ else {
77
+ const [m, t, l, d] = isResponsiveEqual
78
+ ? cols
79
+ : [cols, cols, cols, cols];
80
+ customStyle['--grid-cols-mobile'] = m;
81
+ customStyle['--grid-cols-tablet'] = t;
82
+ customStyle['--grid-cols-laptop'] = l;
83
+ customStyle['--grid-cols-desktop'] = d;
84
+ }
85
+ if (isResponsiveAreas) {
86
+ const fmt = (v) => (v.trim().startsWith('"') ? v : `"${v}"`);
87
+ customStyle['--grid-areas-mobile'] = fmt(areas[0]);
88
+ customStyle['--grid-areas-tablet'] = fmt(areas[1]);
89
+ customStyle['--grid-areas-laptop'] = fmt(areas[2]);
90
+ customStyle['--grid-areas-desktop'] = fmt(areas[3]);
91
+ }
92
+ else if (typeof areas === 'string') {
93
+ customStyle.gridTemplateAreas = areas.trim().startsWith('"')
94
+ ? areas
95
+ : `"${areas}"`;
96
+ }
70
97
  return createElement(Component, {
71
98
  ref,
72
99
  className: cn('dndev-grid-component', className),
73
100
  'data-gap': gap,
74
101
  'data-align': align,
75
102
  'data-justify': justify,
76
- 'data-responsive': isResponsive ? 'true' : undefined,
103
+ 'data-responsive': isResponsiveEqual ? 'true' : undefined,
104
+ 'data-responsive-tpl': isResponsiveTpl ? 'true' : undefined,
105
+ 'data-responsive-areas': isResponsiveAreas ? 'true' : undefined,
77
106
  style: customStyle,
78
107
  ...props,
79
108
  }, children);
@@ -22,6 +22,7 @@
22
22
  */
23
23
  import { type VariantProps } from 'class-variance-authority';
24
24
  import { type ElementType, type ComponentPropsWithRef, type ReactNode } from 'react';
25
+ import { type Tone } from '../../utils/constants';
25
26
  import './HeroSection.css';
26
27
  declare const heroSectionVariants: (props?: ({
27
28
  variant?: "primary" | "accent" | "subtle" | null | undefined;
@@ -39,6 +40,8 @@ interface HeroSectionOwnProps extends VariantProps<typeof heroSectionVariants> {
39
40
  fullHeight?: boolean;
40
41
  /** Content alignment @default 'center' */
41
42
  align?: 'start' | 'center' | 'end';
43
+ /** Tone system for background colors (matches Section/CallToAction) */
44
+ tone?: Tone;
42
45
  /** Content */
43
46
  children?: ReactNode;
44
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/HeroSection/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,OAAO,mBAAmB,CAAC;AAE3B,QAAA,MAAM,mBAAmB;;8EAWvB,CAAC;AAEH,UAAU,mBAAoB,SAAQ,YAAY,CAAC,OAAO,mBAAmB,CAAC;IAC5E,mDAAmD;IACnD,EAAE,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;IAClC,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2BAA2B;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,cAAc;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,WAAW,GAAG,SAAS,IAC5D,mBAAmB,GACjB,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,MAAM,mBAAmB,CAAC,CAAC;AAE9D,QAAA,MAAM,WAAW,kIA6DhB,CAAC;AAIF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/HeroSection/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EAAQ,KAAK,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAMxD,OAAO,mBAAmB,CAAC;AAE3B,QAAA,MAAM,mBAAmB;;8EAWvB,CAAC;AAEH,UAAU,mBAAoB,SAAQ,YAAY,CAAC,OAAO,mBAAmB,CAAC;IAC5E,mDAAmD;IACnD,EAAE,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,KAAK,CAAC;IAClC,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,2BAA2B;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,uEAAuE;IACvE,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,cAAc;IACd,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,SAAS,WAAW,GAAG,SAAS,IAC5D,mBAAmB,GACjB,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,MAAM,mBAAmB,CAAC,CAAC;AAE9D,QAAA,MAAM,WAAW,kIAgEhB,CAAC;AAIF,eAAe,WAAW,CAAC"}
@@ -24,6 +24,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
24
  */
25
25
  import { cva } from 'class-variance-authority';
26
26
  import { createElement, forwardRef, } from 'react';
27
+ import { TONE } from '../../utils/constants';
27
28
  import { cn } from '../../utils/helpers';
28
29
  import Badge, { BADGE_VARIANT } from '../Badge';
29
30
  import Stack from '../Stack';
@@ -41,11 +42,13 @@ const heroSectionVariants = cva('', {
41
42
  variant: 'primary',
42
43
  },
43
44
  });
44
- const HeroSection = forwardRef(function HeroSection({ as = 'section', badge, title, subtitle, variant, fullHeight = false, align = 'center', children, className, ...props }, ref) {
45
+ const HeroSection = forwardRef(function HeroSection({ as = 'section', badge, title, subtitle, variant, fullHeight = false, align = 'center', tone = TONE.GHOST, children, className, ...props }, ref) {
45
46
  return createElement(as, {
46
47
  ref,
47
48
  className: cn('dndev-hero-section', className),
48
49
  'data-text-align': align,
50
+ 'data-variant': variant || undefined,
51
+ 'data-tone': tone,
49
52
  style: {
50
53
  ...(fullHeight
51
54
  ? {
@@ -56,7 +59,7 @@ const HeroSection = forwardRef(function HeroSection({ as = 'section', badge, tit
56
59
  ...props.style,
57
60
  },
58
61
  ...props,
59
- }, _jsxs(Stack, { gap: "medium", children: [badge && _jsx(Badge, { variant: BADGE_VARIANT.ACCENT, children: badge }), title && (_jsx(Text, { as: "div", level: "h1", className: "dndev-hero-title", "data-gradient-text": variant === 'subtle' ? undefined : variant || 'primary', children: title })), subtitle && (_jsx(Text, { as: "p", level: "body", className: "dndev-hero-subtitle", children: subtitle })), children] }));
62
+ }, _jsxs(Stack, { children: [badge && _jsx(Badge, { variant: BADGE_VARIANT.ACCENT, children: badge }), title && (_jsx(Text, { as: "div", level: "h1", className: "dndev-hero-title", "data-gradient-text": variant === 'subtle' ? undefined : variant || 'primary', children: title })), subtitle && (_jsx(Text, { as: "p", level: "body", className: "dndev-hero-subtitle", children: subtitle })), children] }));
60
63
  });
61
64
  HeroSection.displayName = 'HeroSection';
62
65
  export default HeroSection;
@@ -1 +1 @@
1
- {"version":3,"file":"HoverCardPrimitive.d.ts","sourceRoot":"","sources":["../../../src/atomic/HoverCard/HoverCardPrimitive.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,cAAc,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,QAAA,MAAM,kBAAkB,GAAI,yBAGzB,cAAc,CAAC,cAAc,4CAE/B,CAAC;AAEF,QAAA,MAAM,gBAAgB,oIAAyB,CAAC;AAEhD,QAAA,MAAM,gBAAgB,GAAI,4CAKvB,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,4CAS/C,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"HoverCardPrimitive.d.ts","sourceRoot":"","sources":["../../../src/atomic/HoverCard/HoverCardPrimitive.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,cAAc,MAAM,4BAA4B,CAAC;AAI7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,QAAA,MAAM,kBAAkB,GAAI,yBAGzB,cAAc,CAAC,cAAc,4CAE/B,CAAC;AAEF,QAAA,MAAM,gBAAgB,oIAAyB,CAAC;AAEhD,QAAA,MAAM,gBAAgB,GAAI,4CAKvB,cAAc,CAAC,OAAO,cAAc,CAAC,OAAO,CAAC,4CAW/C,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,CAAC"}
@@ -13,7 +13,7 @@ import { cn } from '../../utils/helpers';
13
13
  const HoverCardPrimitive = ({ openDelay = 0, ...props }) => (_jsx(RadixHoverCard.Root, { openDelay: openDelay, ...props }));
14
14
  const HoverCardTrigger = RadixHoverCard.Trigger;
15
15
  const HoverCardContent = ({ className, align = 'center', sideOffset = 4, ...props }) => {
16
- return (_jsx(RadixHoverCard.Content, { align: align, sideOffset: sideOffset, className: cn(className), ...props }));
16
+ return (_jsx(RadixHoverCard.Portal, { children: _jsx(RadixHoverCard.Content, { align: align, sideOffset: sideOffset, className: cn(className), ...props }) }));
17
17
  };
18
18
  export { HoverCardPrimitive };
19
19
  export { HoverCardTrigger, HoverCardContent };
@@ -1,8 +1,9 @@
1
+ import { type CardProps } from '../Card';
1
2
  import type { ReactNode } from 'react';
2
- export interface HoverCardProps {
3
+ export interface HoverCardProps extends Pick<CardProps, 'title' | 'subtitle' | 'content' | 'footer' | 'icon' | 'variant'> {
3
4
  /** Trigger element (button, text, avatar, etc.) */
4
5
  trigger?: ReactNode;
5
- /** HoverCard content */
6
+ /** HoverCard content (alternative to content prop, for full control) */
6
7
  children?: ReactNode;
7
8
  /** Controlled open state */
8
9
  open?: boolean;
@@ -23,11 +24,25 @@ export interface HoverCardProps {
23
24
  }
24
25
  /**
25
26
  * Accessible hover card component.
26
- * Shows rich content on hover with smooth animations.
27
+ * Shows rich content on hover using Radix HoverCard primitive.
28
+ *
29
+ * ⚠️ **Desktop only**: This component uses hover events and does not support touch/click interactions.
30
+ * For mobile/click support, use {@link Popover} instead.
31
+ *
32
+ * Accepts Card props (title, subtitle, content, footer, variant, icon) and renders a Card internally.
27
33
  *
28
34
  * @component
29
35
  * @example
30
36
  * ```tsx
37
+ * // Using Card props
38
+ * <HoverCard
39
+ * trigger={<Avatar src="..." />}
40
+ * title="John Doe"
41
+ * subtitle="Software Engineer"
42
+ * content="Building amazing products"
43
+ * />
44
+ *
45
+ * // Using children for full control
31
46
  * <HoverCard trigger={<Avatar src="..." />}>
32
47
  * <Stack gap="tight">
33
48
  * <Text>John Doe</Text>
@@ -38,6 +53,6 @@ export interface HoverCardProps {
38
53
  * @param {HoverCardProps} props - The props for the hover card
39
54
  * @returns {JSX.Element} The rendered hover card
40
55
  */
41
- declare function HoverCard({ trigger, children, open, onOpenChange, openDelay, closeDelay, align, side, sideOffset, className, }: HoverCardProps): import("react/jsx-runtime").JSX.Element;
56
+ declare function HoverCard({ trigger, title, subtitle, content, footer, icon, variant, children, open, onOpenChange, openDelay, closeDelay, align, side, sideOffset, className, }: HoverCardProps): import("react/jsx-runtime").JSX.Element;
42
57
  export default HoverCard;
43
58
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/HoverCard/index.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,cAAc;IAC7B,mDAAmD;IACnD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,8BAA8B;IAC9B,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,iBAAS,SAAS,CAAC,EACjB,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,SAAa,EACb,UAAc,EACd,KAAgB,EAChB,IAAe,EACf,UAAc,EACd,SAAS,GACV,EAAE,cAAc,2CAsBhB;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/HoverCard/index.tsx"],"names":[],"mappings":"AAmBA,OAAa,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AAG/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,EACT,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CACjE;IACC,mDAAmD;IACnD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,uCAAuC;IACvC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,8BAA8B;IAC9B,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,iBAAS,SAAS,CAAC,EACjB,OAAO,EACP,KAAK,EACL,QAAQ,EACR,OAAO,EACP,MAAM,EACN,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,SAAa,EACb,UAAc,EACd,KAAgB,EAChB,IAAe,EACf,UAAc,EACd,SAAS,GACV,EAAE,cAAc,2CAqChB;AAED,eAAe,SAAS,CAAC"}
@@ -2,21 +2,38 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // packages/components/src/atomic/HoverCard/index.tsx
3
3
  /**
4
4
  * @fileoverview HoverCard component
5
- * @description Accessible hover card component built on Radix UI primitives
5
+ * @description Accessible hover card component built on Radix UI primitives.
6
+ * Accepts Card props and renders a Card internally.
6
7
  *
7
- * @version 0.0.1
8
+ * @version 0.0.2
8
9
  * @since 0.0.1
9
10
  * @author AMBROISE PARK Consulting
10
11
  */
12
+ import { useState } from 'react';
11
13
  import { HoverCardPrimitive, HoverCardTrigger, HoverCardContent, } from './HoverCardPrimitive';
14
+ import Card, {} from '../Card';
12
15
  import { cn } from '../../utils/helpers';
13
16
  /**
14
17
  * Accessible hover card component.
15
- * Shows rich content on hover with smooth animations.
18
+ * Shows rich content on hover using Radix HoverCard primitive.
19
+ *
20
+ * ⚠️ **Desktop only**: This component uses hover events and does not support touch/click interactions.
21
+ * For mobile/click support, use {@link Popover} instead.
22
+ *
23
+ * Accepts Card props (title, subtitle, content, footer, variant, icon) and renders a Card internally.
16
24
  *
17
25
  * @component
18
26
  * @example
19
27
  * ```tsx
28
+ * // Using Card props
29
+ * <HoverCard
30
+ * trigger={<Avatar src="..." />}
31
+ * title="John Doe"
32
+ * subtitle="Software Engineer"
33
+ * content="Building amazing products"
34
+ * />
35
+ *
36
+ * // Using children for full control
20
37
  * <HoverCard trigger={<Avatar src="..." />}>
21
38
  * <Stack gap="tight">
22
39
  * <Text>John Doe</Text>
@@ -27,7 +44,9 @@ import { cn } from '../../utils/helpers';
27
44
  * @param {HoverCardProps} props - The props for the hover card
28
45
  * @returns {JSX.Element} The rendered hover card
29
46
  */
30
- function HoverCard({ trigger, children, open, onOpenChange, openDelay = 0, closeDelay = 0, align = 'center', side = 'bottom', sideOffset = 4, className, }) {
31
- return (_jsxs(HoverCardPrimitive, { open: open, onOpenChange: onOpenChange, openDelay: openDelay, closeDelay: closeDelay, children: [trigger && _jsx(HoverCardTrigger, { asChild: true, children: trigger }), _jsx(HoverCardContent, { align: align, side: side, sideOffset: sideOffset, className: cn('dndev-surface dndev-z-tooltip dndev-hovercard-content', className), children: children })] }));
47
+ function HoverCard({ trigger, title, subtitle, content, footer, icon, variant, children, open, onOpenChange, openDelay = 0, closeDelay = 0, align = 'center', side = 'bottom', sideOffset = 4, className, }) {
48
+ const hasCardProps = !!(title || subtitle || content || footer || icon || variant);
49
+ const cardContent = hasCardProps ? (_jsx(Card, { title: title, subtitle: subtitle, content: content, footer: footer, icon: icon, variant: variant })) : (children);
50
+ return (_jsxs(HoverCardPrimitive, { open: open, onOpenChange: onOpenChange, openDelay: openDelay, closeDelay: closeDelay, children: [trigger && _jsx(HoverCardTrigger, { asChild: true, children: trigger }), _jsx(HoverCardContent, { align: align, side: side, sideOffset: sideOffset, className: cn('dndev-z-tooltip dndev-hovercard-content', !hasCardProps && 'dndev-surface', className), children: cardContent })] }));
32
51
  }
33
52
  export default HoverCard;
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../src/atomic/Icons/Icon.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,kEAAkE;IAClE,QAAQ,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3D,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,QAAA,MAAM,IAAI,EAAE,aAAa,CAAC,SAAS,CA2FlC,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Icon.d.ts","sourceRoot":"","sources":["../../../src/atomic/Icons/Icon.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IACvD,kEAAkE;IAClE,QAAQ,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAC3D,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,QAAA,MAAM,IAAI,EAAE,aAAa,CAAC,SAAS,CA4FlC,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -12,6 +12,14 @@ import { cn } from '../../utils/helpers';
12
12
  const Icon = ({ icon, fallback, className, ariaHidden = false, }) => {
13
13
  // Memoize icon resolution to avoid recalculation
14
14
  const iconToRender = useMemo(() => icon || fallback, [icon, fallback]);
15
+ // Memoize emoji check — must be unconditional (Rules of Hooks)
16
+ const isEmoji = useMemo(() => {
17
+ if (typeof iconToRender !== 'string')
18
+ return false;
19
+ // If it's a valid identifier pattern, it's NOT an emoji (it's a Lucide icon name)
20
+ const isValidIdentifier = /^[a-zA-Z0-9_-]+$/.test(iconToRender);
21
+ return !isValidIdentifier;
22
+ }, [iconToRender]);
15
23
  if (!iconToRender)
16
24
  return null;
17
25
  const sizeClass = 'dndev-size-md';
@@ -25,21 +33,14 @@ const Icon = ({ icon, fallback, className, ariaHidden = false, }) => {
25
33
  }
26
34
  // Type 2: String (emoji only - no dynamic icon name lookup for tree-shaking)
27
35
  if (typeof iconToRender === 'string') {
28
- // Check if string is an emoji (not a valid identifier)
29
- // Valid identifiers: alphanumeric, underscore, hyphen (Lucide icon names)
30
- // Emojis: anything else (Unicode symbols, emojis, etc.)
31
- // eslint-disable-next-line react-hooks/rules-of-hooks
32
- const isEmoji = useMemo(() => {
33
- // If it's a valid identifier pattern, it's NOT an emoji (it's a Lucide icon name)
34
- const isValidIdentifier = /^[a-zA-Z0-9_-]+$/.test(iconToRender);
35
- return !isValidIdentifier;
36
- }, [iconToRender]);
37
36
  if (isEmoji) {
38
37
  return (_jsx("span", { className: cn('dndev-inline-flex dndev-items-center dndev-justify-center', sizeClass, className), "aria-hidden": ariaHidden, children: iconToRender }));
39
38
  }
40
39
  // Non-emoji string: Not supported (would require full lucide-react import)
41
40
  // Use Icon from @donotdev/ui for dynamic string icon resolution
42
- console.warn(`Icon component from @donotdev/components does not support Lucide icon name strings. Use Icon from @donotdev/ui for dynamic string resolution, or import the icon component directly. Received: "${iconToRender}"`);
41
+ if (process.env.NODE_ENV === 'development') {
42
+ console.warn(`Icon component from @donotdev/components does not support Lucide icon name strings. Use Icon from @donotdev/ui for dynamic string resolution, or import the icon component directly. Received: "${iconToRender}"`);
43
+ }
43
44
  return null;
44
45
  }
45
46
  // Type 3: ReactNode (custom content)
@@ -11,7 +11,9 @@ import './InfiniteScroll.css';
11
11
  export interface InfiniteScrollProps<T> {
12
12
  items: T[];
13
13
  renderItem: (item: T, index: number) => ReactNode;
14
- loadMore: () => void;
14
+ /** Extract a stable key for each item. Falls back to index when not provided. */
15
+ keyExtractor?: (item: T, index: number) => string | number;
16
+ loadMore: () => void | Promise<void>;
15
17
  hasMore: boolean;
16
18
  loading?: boolean;
17
19
  loadingComponent?: ReactNode;
@@ -23,6 +25,6 @@ export interface InfiniteScrollProps<T> {
23
25
  gridCols?: 1 | 2 | 3 | 4 | 5 | 6;
24
26
  gap?: 'none' | 'tight' | 'medium' | 'large';
25
27
  }
26
- declare const InfiniteScroll: <T>({ items, renderItem, loadMore, hasMore, loading, loadingComponent, endMessage, threshold, rootMargin, className, itemClassName, gridCols, gap, }: InfiniteScrollProps<T>) => import("react/jsx-runtime").JSX.Element;
28
+ declare const InfiniteScroll: <T>({ items, renderItem, keyExtractor, loadMore, hasMore, loading, loadingComponent, endMessage, threshold, rootMargin, className, itemClassName, gridCols, gap, }: InfiniteScrollProps<T>) => import("react/jsx-runtime").JSX.Element;
27
29
  export default InfiniteScroll;
28
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/InfiniteScroll/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,sBAAsB,CAAC;AAE9B,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAClD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC7C;AAED,QAAA,MAAM,cAAc,GAAI,CAAC,EAAG,kJAczB,mBAAmB,CAAC,CAAC,CAAC,4CAuGxB,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/atomic/InfiniteScroll/index.tsx"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAMf,OAAO,sBAAsB,CAAC;AAE9B,MAAM,WAAW,mBAAmB,CAAC,CAAC;IACpC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,SAAS,CAAC;IAClD,iFAAiF;IACjF,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;IAC3D,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC7C;AAED,QAAA,MAAM,cAAc,GAAI,CAAC,EAAG,gKAezB,mBAAmB,CAAC,CAAC,CAAC,4CAuGxB,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -14,7 +14,7 @@ import { cn, observeElement } from '../../utils';
14
14
  import Spinner from '../Spinner';
15
15
  import Stack from '../Stack';
16
16
  import './InfiniteScroll.css';
17
- const InfiniteScroll = ({ items, renderItem, loadMore, hasMore, loading = false, loadingComponent, endMessage, threshold = 0.1, rootMargin = '100px', className, itemClassName, gridCols = 3, gap = GAP_VARIANT.MEDIUM, }) => {
17
+ const InfiniteScroll = ({ items, renderItem, keyExtractor, loadMore, hasMore, loading = false, loadingComponent, endMessage, threshold = 0.1, rootMargin = '100px', className, itemClassName, gridCols = 3, gap = GAP_VARIANT.MEDIUM, }) => {
18
18
  const [isLoading, setIsLoading] = useState(false);
19
19
  const loadMoreRef = useRef(null);
20
20
  const handleLoadMore = useCallback(async () => {
@@ -48,6 +48,6 @@ const InfiniteScroll = ({ items, renderItem, loadMore, hasMore, loading = false,
48
48
  }[gap];
49
49
  const defaultLoadingComponent = (_jsx(Stack, { align: "center", justify: "center", className: "dndev-py-lg", children: _jsxs(Stack, { direction: "row", align: "center", gap: "tight", className: "dndev-infinite-scroll-loading-container", children: [_jsx(Spinner, {}), _jsx("span", { children: "Loading more..." })] }) }));
50
50
  const defaultEndMessage = (_jsx(Stack, { align: "center", justify: "center", className: "dndev-py-lg", children: _jsxs("div", { className: "dndev-text-center dndev-infinite-scroll-end-title", children: [_jsx("p", { className: "dndev-text-lg dndev-font-medium", children: "\uD83C\uDF89 You've seen it all!" }), _jsx("p", { className: "dndev-text-sm dndev-infinite-scroll-end-text", children: "That's everything we have to showcase." })] }) }));
51
- return (_jsxs("div", { className: cn('dndev-grid dndev-gap-md', className), children: [_jsx("div", { className: "dndev-infinite-scroll-grid", "data-cols": gridCols, style: gapStyle, children: items.map((item, index) => (_jsx("div", { className: itemClassName, children: renderItem(item, index) }, index))) }), hasMore && (_jsx(Stack, { ref: loadMoreRef, justify: "center", className: "dndev-py-md", children: loading || isLoading ? (loadingComponent || defaultLoadingComponent) : (_jsx("div", { className: "dndev-text-sm dndev-infinite-scroll-more-text", children: "Scroll down to load more..." })) })), !hasMore && items.length > 0 && (_jsx(Stack, { justify: "center", className: "dndev-infinite-scroll-end-container", children: endMessage || defaultEndMessage }))] }));
51
+ return (_jsxs("div", { className: cn('dndev-grid dndev-gap-md', className), children: [_jsx("div", { className: "dndev-infinite-scroll-grid", "data-cols": gridCols, style: gapStyle, children: items.map((item, index) => (_jsx("div", { className: itemClassName, children: renderItem(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }), hasMore && (_jsx(Stack, { ref: loadMoreRef, justify: "center", className: "dndev-py-md", children: loading || isLoading ? (loadingComponent || defaultLoadingComponent) : (_jsx("div", { className: "dndev-text-sm dndev-infinite-scroll-more-text", children: "Scroll down to load more..." })) })), !hasMore && items.length > 0 && (_jsx(Stack, { justify: "center", className: "dndev-infinite-scroll-end-container", children: endMessage || defaultEndMessage }))] }));
52
52
  };
53
53
  export default InfiniteScroll;
@@ -44,7 +44,7 @@ showNavigation = true, previousLabel = 'Previous', nextLabel = 'Next', itemsPerP
44
44
  pageSizeOptions = [
45
45
  { value: '12', label: '12' },
46
46
  { value: '36', label: '36' },
47
- { value: 'ALL', label: String(total) },
47
+ { value: 'all', label: String(total) },
48
48
  ];
49
49
  }
50
50
  else {