periplo-ui 3.16.0 → 3.17.0

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.
@@ -1,9 +1,10 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from 'react';
3
3
  declare const badgeVariants: (props?: ({
4
- intent?: "neutral" | "accent" | "success" | "warning" | "error" | null | undefined;
4
+ color?: "neutral" | "primary" | "accent" | "success" | "warning" | "error" | null | undefined;
5
5
  size?: "sm" | "md" | "lg" | null | undefined;
6
6
  position?: "top-right" | "top-left" | "bottom-right" | "bottom-left" | null | undefined;
7
+ numeric?: boolean | null | undefined;
7
8
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
8
9
  export interface BadgeProps extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof badgeVariants> {
9
10
  /**
@@ -15,7 +16,7 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLElement>, VariantPr
15
16
  * The color variant of the badge
16
17
  * @default 'accent'
17
18
  */
18
- intent?: 'neutral' | 'accent' | 'success' | 'warning' | 'error';
19
+ color?: 'neutral' | 'accent' | 'primary' | 'success' | 'warning' | 'error';
19
20
  /**
20
21
  * The size of the badge
21
22
  * @default 'md'
@@ -26,6 +27,10 @@ export interface BadgeProps extends React.HTMLAttributes<HTMLElement>, VariantPr
26
27
  * @default 'top-right'
27
28
  */
28
29
  position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';
30
+ /**
31
+ * The number to display in the badge)
32
+ */
33
+ count?: number;
29
34
  }
30
35
  /**
31
36
  * A status indicator component that can be used to show notifications,
@@ -9,17 +9,19 @@ const badgeVariants = cva("rounded-full", {
9
9
  * Controls the color scheme of the badge
10
10
  * @default 'accent'
11
11
  */
12
- intent: {
12
+ color: {
13
13
  /** Default gray appearance */
14
- neutral: "bg-neutral",
14
+ neutral: "bg-neutral text-neutral-foreground",
15
+ /** Accent brand color */
16
+ accent: "bg-accent text-accent-foreground",
15
17
  /** Primary brand color */
16
- accent: "bg-accent",
18
+ primary: "bg-primary text-primary-foreground",
17
19
  /** Indicates successful or positive state */
18
- success: "bg-success",
20
+ success: "bg-success text-success-foreground ",
19
21
  /** Indicates warning or cautionary state */
20
- warning: "bg-warning",
22
+ warning: "bg-warning text-warning-foreground",
21
23
  /** Indicates error or critical state */
22
- error: "bg-error"
24
+ error: "bg-error text-error-foreground"
23
25
  },
24
26
  /**
25
27
  * Controls the size of the badge
@@ -46,30 +48,58 @@ const badgeVariants = cva("rounded-full", {
46
48
  "bottom-right": "right-0 bottom-0",
47
49
  /** Places the badge in the bottom-left corner */
48
50
  "bottom-left": "left-0 bottom-0"
51
+ },
52
+ /**
53
+ * Controls whether the badge displays a number
54
+ * @default false
55
+ */
56
+ numeric: {
57
+ true: "min-w-[16px] h-4 px-1 flex items-center justify-center text-[10px] font-medium",
58
+ false: ""
49
59
  }
50
60
  },
51
61
  defaultVariants: {
52
- intent: "accent",
62
+ color: "primary",
53
63
  size: "md",
54
- position: "top-right"
64
+ position: "top-right",
65
+ numeric: false
55
66
  }
56
67
  });
57
68
  const Badge = React.forwardRef(
58
- ({ className, intent = "accent", size = "md", position = "top-right", ping = true, ...props }, ref) => {
69
+ ({ className, color = "accent", size = "md", position = "top-right", ping = true, count, ...props }, ref) => {
59
70
  const sizeClasses = {
60
71
  sm: "h-2 w-2",
61
72
  md: "h-3 w-3",
62
73
  lg: "h-4 w-4"
63
74
  }[size || "md"];
64
- return /* @__PURE__ */ jsxs("span", { className: cn("absolute flex", badgeVariants({ position }), sizeClasses, className), ref, ...props, children: [
65
- ping && /* @__PURE__ */ jsx(
66
- "span",
67
- {
68
- className: cn(badgeVariants({ intent }), "absolute inline-flex h-full w-full animate-ping opacity-75")
69
- }
70
- ),
71
- /* @__PURE__ */ jsx("span", { className: cn(badgeVariants({ intent }), "relative inline-flex h-full w-full") })
72
- ] });
75
+ return /* @__PURE__ */ jsxs(
76
+ "span",
77
+ {
78
+ className: cn(
79
+ "absolute flex",
80
+ badgeVariants({ color, position, numeric: !!count }),
81
+ !count && sizeClasses,
82
+ className
83
+ ),
84
+ ref,
85
+ ...props,
86
+ children: [
87
+ ping && /* @__PURE__ */ jsx(
88
+ "span",
89
+ {
90
+ className: cn(badgeVariants({ color }), "absolute inline-flex h-full w-full animate-ping opacity-75")
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsx(
94
+ "span",
95
+ {
96
+ className: cn(badgeVariants({ color }), "relative inline-flex h-full w-full items-center justify-center"),
97
+ children: count
98
+ }
99
+ )
100
+ ]
101
+ }
102
+ );
73
103
  }
74
104
  );
75
105
  Badge.displayName = "Badge";
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nconst badgeVariants = cva('rounded-full', {\n variants: {\n /**\n * Controls the color scheme of the badge\n * @default 'accent'\n */\n intent: {\n /** Default gray appearance */\n neutral: 'bg-neutral',\n /** Primary brand color */\n accent: 'bg-accent',\n /** Indicates successful or positive state */\n success: 'bg-success',\n /** Indicates warning or cautionary state */\n warning: 'bg-warning',\n /** Indicates error or critical state */\n error: 'bg-error',\n },\n /**\n * Controls the size of the badge\n * @default 'md'\n */\n size: {\n /** Small size - 8px */\n sm: 'h-2 w-2',\n /** Medium size - 12px */\n md: 'h-3 w-3',\n /** Large size - 16px */\n lg: 'h-4 w-4',\n },\n /**\n * Controls the position of the badge relative to its container\n * @default 'top-right'\n */\n position: {\n /** Places the badge in the top-right corner */\n 'top-right': 'right-0 top-0',\n /** Places the badge in the top-left corner */\n 'top-left': 'left-0 top-0',\n /** Places the badge in the bottom-right corner */\n 'bottom-right': 'right-0 bottom-0',\n /** Places the badge in the bottom-left corner */\n 'bottom-left': 'left-0 bottom-0',\n },\n },\n defaultVariants: {\n intent: 'accent',\n size: 'md',\n position: 'top-right',\n },\n})\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof badgeVariants> {\n /**\n * Controls the visibility of the pulsing animation effect\n * @default true\n */\n ping?: boolean\n\n /**\n * The color variant of the badge\n * @default 'accent'\n */\n intent?: 'neutral' | 'accent' | 'success' | 'warning' | 'error'\n\n /**\n * The size of the badge\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * The position of the badge relative to its container\n * @default 'top-right'\n */\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n}\n\n/**\n * A status indicator component that can be used to show notifications,\n * status, or draw attention to an element.\n *\n * @example\n * ```tsx\n * // Simple notification badge\n * <div className=\"relative\">\n * <Bell className=\"h-6 w-6\" />\n * <Badge intent=\"error\" />\n * </div>\n *\n * // Custom size and position\n * <div className=\"relative\">\n * <Avatar />\n * <Badge\n * intent=\"success\"\n * size=\"sm\"\n * position=\"bottom-right\"\n * ping={false}\n * />\n * </div>\n * ```\n */\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, intent = 'accent', size = 'md', position = 'top-right', ping = true, ...props }, ref) => {\n const sizeClasses = {\n sm: 'h-2 w-2',\n md: 'h-3 w-3',\n lg: 'h-4 w-4',\n }[size || 'md']\n\n return (\n <span className={cn('absolute flex', badgeVariants({ position }), sizeClasses, className)} ref={ref} {...props}>\n {ping && (\n <span\n className={cn(badgeVariants({ intent }), 'absolute inline-flex h-full w-full animate-ping opacity-75')}\n />\n )}\n <span className={cn(badgeVariants({ intent }), 'relative inline-flex h-full w-full')} />\n </span>\n )\n },\n)\n\nBadge.displayName = 'Badge'\n\nexport { Badge, badgeVariants }\n"],"names":[],"mappings":";;;;;AAIM,MAAA,aAAA,GAAgB,IAAI,cAAgB,EAAA;AAAA,EACxC,QAAU,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKR,MAAQ,EAAA;AAAA;AAAA,MAEN,OAAS,EAAA,YAAA;AAAA;AAAA,MAET,MAAQ,EAAA,WAAA;AAAA;AAAA,MAER,OAAS,EAAA,YAAA;AAAA;AAAA,MAET,OAAS,EAAA,YAAA;AAAA;AAAA,MAET,KAAO,EAAA;AAAA,KACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,IAAM,EAAA;AAAA;AAAA,MAEJ,EAAI,EAAA,SAAA;AAAA;AAAA,MAEJ,EAAI,EAAA,SAAA;AAAA;AAAA,MAEJ,EAAI,EAAA;AAAA,KACN;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,QAAU,EAAA;AAAA;AAAA,MAER,WAAa,EAAA,eAAA;AAAA;AAAA,MAEb,UAAY,EAAA,cAAA;AAAA;AAAA,MAEZ,cAAgB,EAAA,kBAAA;AAAA;AAAA,MAEhB,aAAe,EAAA;AAAA;AACjB,GACF;AAAA,EACA,eAAiB,EAAA;AAAA,IACf,MAAQ,EAAA,QAAA;AAAA,IACR,IAAM,EAAA,IAAA;AAAA,IACN,QAAU,EAAA;AAAA;AAEd,CAAC;AAoDD,MAAM,QAAQ,KAAM,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAW,EAAA,MAAA,GAAS,UAAU,IAAO,GAAA,IAAA,EAAM,QAAW,GAAA,WAAA,EAAa,IAAO,GAAA,IAAA,EAAM,GAAG,KAAA,IAAS,GAAQ,KAAA;AACrG,IAAA,MAAM,WAAc,GAAA;AAAA,MAClB,EAAI,EAAA,SAAA;AAAA,MACJ,EAAI,EAAA,SAAA;AAAA,MACJ,EAAI,EAAA;AAAA,KACN,CAAE,QAAQ,IAAI,CAAA;AAEd,IAAA,uBACG,IAAA,CAAA,MAAA,EAAA,EAAK,SAAW,EAAA,EAAA,CAAG,iBAAiB,aAAc,CAAA,EAAE,QAAS,EAAC,GAAG,WAAa,EAAA,SAAS,CAAG,EAAA,GAAA,EAAW,GAAG,KACtG,EAAA,QAAA,EAAA;AAAA,MACC,IAAA,oBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,WAAW,EAAG,CAAA,aAAA,CAAc,EAAE,MAAO,EAAC,GAAG,4DAA4D;AAAA;AAAA,OACvG;AAAA,sBAEF,GAAA,CAAC,MAAK,EAAA,EAAA,SAAA,EAAW,EAAG,CAAA,aAAA,CAAc,EAAE,MAAO,EAAC,CAAG,EAAA,oCAAoC,CAAG,EAAA;AAAA,KACxF,EAAA,CAAA;AAAA;AAGN;AAEA,KAAA,CAAM,WAAc,GAAA,OAAA;;;;"}
1
+ {"version":3,"file":"Badge.js","sources":["../../../src/components/Badge/Badge.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\nimport { cn } from '../../lib/utils'\n\nconst badgeVariants = cva('rounded-full', {\n variants: {\n /**\n * Controls the color scheme of the badge\n * @default 'accent'\n */\n color: {\n /** Default gray appearance */\n neutral: 'bg-neutral text-neutral-foreground',\n /** Accent brand color */\n accent: 'bg-accent text-accent-foreground',\n /** Primary brand color */\n primary: 'bg-primary text-primary-foreground',\n /** Indicates successful or positive state */\n success: 'bg-success text-success-foreground ',\n /** Indicates warning or cautionary state */\n warning: 'bg-warning text-warning-foreground',\n /** Indicates error or critical state */\n error: 'bg-error text-error-foreground',\n },\n /**\n * Controls the size of the badge\n * @default 'md'\n */\n size: {\n /** Small size - 8px */\n sm: 'h-2 w-2',\n /** Medium size - 12px */\n md: 'h-3 w-3',\n /** Large size - 16px */\n lg: 'h-4 w-4',\n },\n /**\n * Controls the position of the badge relative to its container\n * @default 'top-right'\n */\n position: {\n /** Places the badge in the top-right corner */\n 'top-right': 'right-0 top-0',\n /** Places the badge in the top-left corner */\n 'top-left': 'left-0 top-0',\n /** Places the badge in the bottom-right corner */\n 'bottom-right': 'right-0 bottom-0',\n /** Places the badge in the bottom-left corner */\n 'bottom-left': 'left-0 bottom-0',\n },\n /**\n * Controls whether the badge displays a number\n * @default false\n */\n numeric: {\n true: 'min-w-[16px] h-4 px-1 flex items-center justify-center text-[10px] font-medium',\n false: '',\n },\n },\n defaultVariants: {\n color: 'primary',\n size: 'md',\n position: 'top-right',\n numeric: false,\n },\n})\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof badgeVariants> {\n /**\n * Controls the visibility of the pulsing animation effect\n * @default true\n */\n ping?: boolean\n\n /**\n * The color variant of the badge\n * @default 'accent'\n */\n color?: 'neutral' | 'accent' | 'primary' | 'success' | 'warning' | 'error'\n\n /**\n * The size of the badge\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * The position of the badge relative to its container\n * @default 'top-right'\n */\n position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'\n\n /**\n * The number to display in the badge)\n */\n count?: number\n}\n\n/**\n * A status indicator component that can be used to show notifications,\n * status, or draw attention to an element.\n *\n * @example\n * ```tsx\n * // Simple notification badge\n * <div className=\"relative\">\n * <Bell className=\"h-6 w-6\" />\n * <Badge intent=\"error\" />\n * </div>\n *\n * // Custom size and position\n * <div className=\"relative\">\n * <Avatar />\n * <Badge\n * intent=\"success\"\n * size=\"sm\"\n * position=\"bottom-right\"\n * ping={false}\n * />\n * </div>\n * ```\n */\nconst Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n ({ className, color = 'accent', size = 'md', position = 'top-right', ping = true, count, ...props }, ref) => {\n const sizeClasses = {\n sm: 'h-2 w-2',\n md: 'h-3 w-3',\n lg: 'h-4 w-4',\n }[size || 'md']\n\n return (\n <span\n className={cn(\n 'absolute flex',\n badgeVariants({ color, position, numeric: !!count }),\n !count && sizeClasses,\n className,\n )}\n ref={ref}\n {...props}\n >\n {ping && (\n <span\n className={cn(badgeVariants({ color }), 'absolute inline-flex h-full w-full animate-ping opacity-75')}\n />\n )}\n <span\n className={cn(badgeVariants({ color }), 'relative inline-flex h-full w-full items-center justify-center')}\n >\n {count}\n </span>\n </span>\n )\n },\n)\n\nBadge.displayName = 'Badge'\n\nexport { Badge, badgeVariants }\n"],"names":[],"mappings":";;;;;AAIM,MAAA,aAAA,GAAgB,IAAI,cAAgB,EAAA;AAAA,EACxC,QAAU,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKR,KAAO,EAAA;AAAA;AAAA,MAEL,OAAS,EAAA,oCAAA;AAAA;AAAA,MAET,MAAQ,EAAA,kCAAA;AAAA;AAAA,MAER,OAAS,EAAA,oCAAA;AAAA;AAAA,MAET,OAAS,EAAA,sCAAA;AAAA;AAAA,MAET,OAAS,EAAA,oCAAA;AAAA;AAAA,MAET,KAAO,EAAA;AAAA,KACT;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,IAAM,EAAA;AAAA;AAAA,MAEJ,EAAI,EAAA,SAAA;AAAA;AAAA,MAEJ,EAAI,EAAA,SAAA;AAAA;AAAA,MAEJ,EAAI,EAAA;AAAA,KACN;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,QAAU,EAAA;AAAA;AAAA,MAER,WAAa,EAAA,eAAA;AAAA;AAAA,MAEb,UAAY,EAAA,cAAA;AAAA;AAAA,MAEZ,cAAgB,EAAA,kBAAA;AAAA;AAAA,MAEhB,aAAe,EAAA;AAAA,KACjB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,OAAS,EAAA;AAAA,MACP,IAAM,EAAA,gFAAA;AAAA,MACN,KAAO,EAAA;AAAA;AACT,GACF;AAAA,EACA,eAAiB,EAAA;AAAA,IACf,KAAO,EAAA,SAAA;AAAA,IACP,IAAM,EAAA,IAAA;AAAA,IACN,QAAU,EAAA,WAAA;AAAA,IACV,OAAS,EAAA;AAAA;AAEb,CAAC;AAyDD,MAAM,QAAQ,KAAM,CAAA,UAAA;AAAA,EAClB,CAAC,EAAE,SAAW,EAAA,KAAA,GAAQ,UAAU,IAAO,GAAA,IAAA,EAAM,QAAW,GAAA,WAAA,EAAa,OAAO,IAAM,EAAA,KAAA,EAAO,GAAG,KAAA,IAAS,GAAQ,KAAA;AAC3G,IAAA,MAAM,WAAc,GAAA;AAAA,MAClB,EAAI,EAAA,SAAA;AAAA,MACJ,EAAI,EAAA,SAAA;AAAA,MACJ,EAAI,EAAA;AAAA,KACN,CAAE,QAAQ,IAAI,CAAA;AAEd,IACE,uBAAA,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,SAAW,EAAA,EAAA;AAAA,UACT,eAAA;AAAA,UACA,aAAA,CAAc,EAAE,KAAO,EAAA,QAAA,EAAU,SAAS,CAAC,CAAC,OAAO,CAAA;AAAA,UACnD,CAAC,KAAS,IAAA,WAAA;AAAA,UACV;AAAA,SACF;AAAA,QACA,GAAA;AAAA,QACC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UACC,IAAA,oBAAA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,WAAW,EAAG,CAAA,aAAA,CAAc,EAAE,KAAM,EAAC,GAAG,4DAA4D;AAAA;AAAA,WACtG;AAAA,0BAEF,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,WAAW,EAAG,CAAA,aAAA,CAAc,EAAE,KAAM,EAAC,GAAG,gEAAgE,CAAA;AAAA,cAEvG,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AAAA,KACF;AAAA;AAGN;AAEA,KAAA,CAAM,WAAc,GAAA,OAAA;;;;"}
@@ -54,8 +54,12 @@ export type DataTableProps<TData> = {
54
54
  readonly primaryFilters?: React.ReactNode;
55
55
  /** Secondary filters that appear in the filters dropdown */
56
56
  readonly secondaryFilters?: React.ReactNode;
57
+ /** Number of active primary filters */
58
+ readonly activePrimaryFiltersCount?: number;
59
+ /** Number of active secondary filters */
60
+ readonly activeSecondaryFiltersCount?: number;
57
61
  /** Text customization for filters */
58
- readonly customLabels?: {
62
+ readonly labels?: {
59
63
  /** Text for the column visibility button (default: "Hide columns") */
60
64
  columnVisibilityButton?: string;
61
65
  /** Text for the filters button when only secondary filters are present (default: "Filters") */
@@ -115,5 +119,5 @@ type RowIdentifierFn<T> = (row: T) => string;
115
119
  * <DataTable columns={columns} data={data} />
116
120
  * ```
117
121
  */
118
- export declare function DataTable<TData extends object = any>({ columns: userColumns, data, getRowId, showColumnVisibilityControls, isLoading, pagination, primaryFilters, secondaryFilters, customLabels, onSelectAll, onSelect, className, tableClassName, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
122
+ export declare function DataTable<TData extends object = any>({ columns: userColumns, data, getRowId, showColumnVisibilityControls, isLoading, pagination, primaryFilters, secondaryFilters, activePrimaryFiltersCount, activeSecondaryFiltersCount, labels, onSelectAll, onSelect, className, tableClassName, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
119
123
  export {};
@@ -13,6 +13,7 @@ import { cn } from '../../lib/utils.js';
13
13
  import { Typography } from '../Typography/Typography.js';
14
14
  import { PopoverRoot, PopoverTrigger, PopoverContent } from '../Popover/Popover.js';
15
15
  import { useIsMobile } from '../../lib/useMobile.js';
16
+ import { Badge } from '../Badge/Badge.js';
16
17
 
17
18
  function DataTable({
18
19
  columns: userColumns,
@@ -23,7 +24,9 @@ function DataTable({
23
24
  pagination,
24
25
  primaryFilters,
25
26
  secondaryFilters,
26
- customLabels = {
27
+ activePrimaryFiltersCount = 0,
28
+ activeSecondaryFiltersCount = 0,
29
+ labels = {
27
30
  columnVisibilityButton: "Hide columns",
28
31
  filters: "Filters",
29
32
  moreFilters: "More filters"
@@ -158,14 +161,25 @@ function DataTable({
158
161
  !isMobile && (primaryFilters ? /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: primaryFilters }) : /* @__PURE__ */ jsx("div", {})),
159
162
  /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", isMobile ? "w-full justify-end" : ""), children: [
160
163
  (isMobile ? primaryFilters || secondaryFilters : secondaryFilters) && /* @__PURE__ */ jsxs(PopoverRoot, { children: [
161
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", StartIcon: FunnelSimple, children: !primaryFilters || isMobile ? customLabels.filters : customLabels.moreFilters }) }),
164
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { variant: "text", size: "sm", StartIcon: FunnelSimple, className: "relative whitespace-nowrap", children: [
165
+ (isMobile && activePrimaryFiltersCount + activeSecondaryFiltersCount > 0 || !isMobile && activeSecondaryFiltersCount > 0) && /* @__PURE__ */ jsx(
166
+ Badge,
167
+ {
168
+ count: isMobile ? activePrimaryFiltersCount + activeSecondaryFiltersCount : activeSecondaryFiltersCount,
169
+ color: "primary",
170
+ ping: false,
171
+ className: "absolute -right-1 -top-1"
172
+ }
173
+ ),
174
+ !primaryFilters || isMobile ? labels.filters : labels.moreFilters
175
+ ] }) }),
162
176
  /* @__PURE__ */ jsx(PopoverContent, { align: "center", className: "w-fit p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
163
177
  isMobile && primaryFilters && primaryFilters,
164
178
  secondaryFilters
165
179
  ] }) })
166
180
  ] }),
167
181
  showColumnVisibilityControls && /* @__PURE__ */ jsxs(DropdownMenu, { children: [
168
- /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", className: cn("whitespace-nowrap"), StartIcon: TextColumns, children: customLabels.columnVisibilityButton ?? "Hide columns" }) }),
182
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", className: cn("whitespace-nowrap"), StartIcon: TextColumns, children: labels.columnVisibilityButton ?? "Hide columns" }) }),
169
183
  /* @__PURE__ */ jsxs(DropdownMenuContent, { children: [
170
184
  /* @__PURE__ */ jsx(
171
185
  DropdownMenuCheckboxItem,
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["'use client'\n\nimport {\n ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n useReactTable,\n VisibilityState,\n} from '@tanstack/react-table'\nimport * as React from 'react'\n\nimport { Button } from '../Button'\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../DropdownMenu'\nimport { Skeleton } from '../Skeleton'\nimport { Table as TableComponent, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../Table'\nimport { DataTablePagination } from './DataTablePagination'\nimport { Checkbox } from '../Checkbox'\nimport { TextColumns, FunnelSimple } from '@phosphor-icons/react'\nimport { cn } from '@/lib/utils'\nimport { Typography } from '../Typography'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { useIsMobile } from '@/lib/useMobile'\n\ntype BasePaginationProps = {\n /** Number of rows per page */\n readonly pageSize: number\n /** Whether the pagination is in a loading state */\n readonly isLoading?: boolean\n /** Text customization for pagination */\n readonly labels?: {\n /** Text shown before the page size number (default: \"Showing\") */\n showing?: string\n /** Text shown before the total number (default: \"of\") */\n of?: string\n /** Text shown after the total number (default: \"results\") */\n results?: string\n /** Aria label for previous page button (default: \"Previous page\") */\n previousPage?: string\n /** Aria label for next page button (default: \"Next page\") */\n nextPage?: string\n /** Aria label for page number (default: \"Page {number}\") */\n pageLabel?: string\n }\n}\n\ntype BackendPaginationProps = BasePaginationProps & {\n /** Current page */\n readonly currentPage: number\n /** Total number of items */\n readonly total: number\n /** Callback when page changes */\n readonly onPageChange: (page: number) => void\n}\n\n/**\n * Type helper to check if a type has an 'id' property\n */\ntype HasId<T> = T extends { id: string | number } ? true : false\n\n/**\n * Props for the DataTable component\n * @template TData The type of data being displayed in the table\n */\nexport type DataTableProps<TData> = {\n /** Array of column definitions that describe the table structure */\n readonly columns: Array<ColumnDef<TData>>\n /** Array of data items to be displayed in the table */\n readonly data: Array<TData>\n /** Whether to show the column visibility toggle menu */\n readonly showColumnVisibilityControls?: boolean\n /** Whether the table is in a loading state */\n readonly isLoading?: boolean\n /** Pagination configuration. If not provided, pagination is disabled */\n readonly pagination?: BasePaginationProps | BackendPaginationProps\n /** Primary filters that appear directly above the table */\n readonly primaryFilters?: React.ReactNode\n /** Secondary filters that appear in the filters dropdown */\n readonly secondaryFilters?: React.ReactNode\n /** Text customization for filters */\n readonly customLabels?: {\n /** Text for the column visibility button (default: \"Hide columns\") */\n columnVisibilityButton?: string\n /** Text for the filters button when only secondary filters are present (default: \"Filters\") */\n filters?: string\n /** Text for the more filters button when both primary and secondary filters are present (default: \"More filters\") */\n moreFilters?: string\n }\n /** Callback when all rows are selected */\n readonly onSelectAll?: (selected: boolean) => void\n /** Callback when a row is selected */\n readonly onSelect?: (selected: boolean, row: TData) => void\n /** Optional className for the table container */\n readonly className?: string\n /** Optional className for the table */\n readonly tableClassName?: string\n} & (HasId<TData> extends true\n ? {\n /** Function to get unique identifier from a row. Not needed when data has 'id' property */\n readonly getRowId?: never\n }\n : {\n /** Function to get unique identifier from a row. Required when data doesn't have 'id' property */\n readonly getRowId: RowIdentifierFn<TData>\n })\n\n/**\n * Function to get a unique identifier from a row\n */\ntype RowIdentifierFn<T> = (row: T) => string\n\n/**\n * A feature-rich data table component built on top of TanStack Table.\n * Provides sorting, filtering, pagination, and column visibility controls.\n *\n * @template TData The type of data being displayed in the table\n *\n * @example\n * ```tsx\n * type User = {\n * id: string;\n * name: string;\n * email: string;\n * };\n *\n * const columns: ColumnDef<User>[] = [\n * {\n * accessorKey: 'name',\n * header: 'Name',\n * },\n * {\n * accessorKey: 'email',\n * header: 'Email',\n * },\n * ];\n *\n * const data: User[] = [\n * { id: '1', name: 'John', email: 'john@example.com' },\n * { id: '2', name: 'Jane', email: 'jane@example.com' },\n * ];\n *\n * <DataTable columns={columns} data={data} />\n * ```\n */\nexport function DataTable<TData extends object = any>({\n columns: userColumns,\n data,\n getRowId = (row: TData) => (row as { id: string })?.id,\n showColumnVisibilityControls = true,\n isLoading = false,\n pagination,\n primaryFilters,\n secondaryFilters,\n customLabels = {\n columnVisibilityButton: 'Hide columns',\n filters: 'Filters',\n moreFilters: 'More filters',\n },\n onSelectAll,\n onSelect,\n className,\n tableClassName,\n}: DataTableProps<TData>) {\n const isMobile = useIsMobile()\n const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})\n const [isAllRowsSelected, setIsAllRowsSelected] = React.useState(false)\n const [deselectedRows, setDeselectedRows] = React.useState<Record<string, boolean>>({})\n const [selectedRows, setSelectedRows] = React.useState<Record<string, boolean>>({})\n const [pageIndex, setPageIndex] = React.useState(0)\n\n const isBackendPagination = pagination && 'onPageChange' in pagination\n const total = isBackendPagination ? pagination.total : data.length\n const pageSize = pagination?.pageSize ?? data.length\n const totalPages = Math.ceil(total / pageSize)\n\n const isSelectable = typeof onSelectAll === 'function' || typeof onSelect === 'function'\n\n const handleSelectAll = (checked: boolean) => {\n setIsAllRowsSelected(checked)\n setDeselectedRows({})\n setSelectedRows({})\n onSelectAll?.(checked)\n }\n\n const handleRowSelect = (checked: boolean, rowData: TData) => {\n const rowId = (getRowId as (row: TData) => string)(rowData)\n\n if (isAllRowsSelected) {\n setDeselectedRows((prev) => {\n const newDeselections = { ...prev }\n if (!checked) {\n newDeselections[rowId] = true\n } else {\n delete newDeselections[rowId]\n }\n return newDeselections\n })\n } else {\n setSelectedRows((prev) => {\n const newSelection = { ...prev }\n if (checked) {\n newSelection[rowId] = true\n } else {\n delete newSelection[rowId]\n }\n return newSelection\n })\n }\n\n onSelect?.(checked, rowData)\n }\n\n const rowSelection = React.useMemo(() => {\n if (isAllRowsSelected) {\n return Object.fromEntries(\n data.map((row) => [\n (getRowId as (row: TData) => string)(row),\n !deselectedRows[(getRowId as (row: TData) => string)(row)],\n ]),\n )\n }\n return selectedRows\n }, [data, isAllRowsSelected, deselectedRows, selectedRows, getRowId])\n\n const table = useReactTable({\n data,\n columns: userColumns,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: pagination && !isBackendPagination ? getPaginationRowModel() : undefined,\n onColumnVisibilityChange: setColumnVisibility,\n enableRowSelection: isSelectable,\n getRowId: getRowId,\n state: {\n columnVisibility,\n rowSelection,\n pagination: pagination\n ? {\n pageIndex: isBackendPagination ? pagination.currentPage - 1 : pageIndex,\n pageSize,\n }\n : undefined,\n },\n manualPagination: isBackendPagination,\n onPaginationChange: isBackendPagination\n ? undefined\n : (updater) => {\n if (typeof updater === 'function') {\n const newState = updater({ pageIndex, pageSize })\n setPageIndex(newState.pageIndex)\n }\n },\n })\n\n const renderTableBody = () => {\n if (isLoading) {\n return Array.from({ length: pageSize ?? 10 }).map((_, rowIndex) => (\n <TableRow key={`skeleton-row-${rowIndex.toString()}`}>\n {isSelectable && (\n <TableCell className=\"w-[50px]\">\n <Checkbox checked={false} disabled />\n </TableCell>\n )}\n {table\n .getAllColumns()\n .filter((column) => column.getIsVisible())\n .map((column) => (\n <TableCell\n key={`skeleton-cell-${rowIndex.toString()}-${column.id}`}\n style={{ width: column.columnDef.size }}\n >\n <div className={cn('flex items-center justify-center', column.id === 'actions' && 'justify-end')}>\n <Skeleton className={cn(column.id === 'actions' ? 'h-8 w-8' : 'h-[20px] w-full')} />\n </div>\n </TableCell>\n ))}\n </TableRow>\n ))\n }\n\n if (data.length === 0) {\n return (\n <TableRow>\n <TableCell\n colSpan={isSelectable ? table.getAllColumns().length + 1 : table.getAllColumns().length}\n className=\"h-[200px] text-center\"\n >\n <Typography color=\"neutral\">No data available</Typography>\n </TableCell>\n </TableRow>\n )\n }\n\n return table.getRowModel().rows.map((row) => {\n const rowId = (getRowId as (row: TData) => string)(row.original)\n const isSelected = rowSelection[rowId] ?? false\n\n return (\n <TableRow key={rowId} data-selected={isSelected}>\n {isSelectable && (\n <TableCell className=\"w-[50px]\">\n <Checkbox\n checked={isSelected}\n onCheckedChange={(checked) => {\n const isChecked = checked === true\n handleRowSelect(isChecked, row.original)\n }}\n aria-label={`Select row ${rowId}`}\n />\n </TableCell>\n )}\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} style={{ width: cell.column.columnDef.size }}>\n <Typography>{flexRender(cell.column.columnDef.cell, cell.getContext())}</Typography>\n </TableCell>\n ))}\n </TableRow>\n )\n })\n }\n\n return (\n <div className={cn('flex h-full min-h-0 w-full flex-1 flex-col gap-2 overflow-hidden', className)}>\n {(showColumnVisibilityControls || primaryFilters || secondaryFilters) && (\n <div className=\"flex flex-shrink-0 items-end justify-between p-1\">\n {!isMobile && (primaryFilters ? <div className=\"flex items-center gap-2\">{primaryFilters}</div> : <div />)}\n <div className={cn('flex items-center gap-2', isMobile ? 'w-full justify-end' : '')}>\n {(isMobile ? primaryFilters || secondaryFilters : secondaryFilters) && (\n <PopoverRoot>\n <PopoverTrigger asChild>\n <Button variant=\"text\" size=\"sm\" StartIcon={FunnelSimple}>\n {!primaryFilters || isMobile ? customLabels.filters : customLabels.moreFilters}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"center\" className=\"w-fit p-4\">\n <div className=\"flex flex-col gap-4\">\n {isMobile && primaryFilters && primaryFilters}\n {secondaryFilters}\n </div>\n </PopoverContent>\n </PopoverRoot>\n )}\n {showColumnVisibilityControls && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"text\" size=\"sm\" className={cn('whitespace-nowrap')} StartIcon={TextColumns}>\n {customLabels.columnVisibilityButton ?? 'Hide columns'}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuCheckboxItem\n key={'all-columns'}\n className=\"capitalize\"\n checked={table.getAllColumns().every((column) => column.getIsVisible())}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(value) =>\n table.getAllColumns().forEach((column) => column.toggleVisibility(!!value))\n }\n >\n Select all\n </DropdownMenuCheckboxItem>\n <DropdownMenuSeparator className=\"bg-neutral-100\" />\n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n <DropdownMenuCheckboxItem\n key={column.id}\n className=\"capitalize\"\n checked={column.getIsVisible()}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(value) => column.toggleVisibility(!!value)}\n >\n {column.columnDef.header?.toString()}\n </DropdownMenuCheckboxItem>\n )\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </div>\n )}\n\n <div className=\"flex min-h-0 flex-1 flex-col rounded-md border bg-white\">\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <div className=\"h-full overflow-auto\">\n <TableComponent className=\"w-full\" tableClassName={cn('table-fixed', tableClassName)}>\n <TableHeader className=\"sticky top-0 z-10 bg-neutral-50\">\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {isSelectable && (\n <TableHead className=\"w-[50px]\">\n <Checkbox\n checked={isAllRowsSelected}\n onCheckedChange={handleSelectAll}\n disabled={isLoading || !data.length}\n aria-label=\"Select all rows\"\n />\n </TableHead>\n )}\n {headerGroup.headers.map((header) => (\n <TableHead\n key={header.id}\n className=\"whitespace-normal\"\n style={{ width: header.column.columnDef.size }}\n >\n <Typography weight=\"medium\">\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n </Typography>\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>{renderTableBody()}</TableBody>\n </TableComponent>\n </div>\n </div>\n {!!pagination && (\n <div className=\"border-t px-4 py-2\">\n <DataTablePagination\n table={table}\n total={total}\n pageSize={pageSize}\n currentPage={\n isBackendPagination ? pagination?.currentPage : table.getState().pagination?.pageIndex + 1 || 1\n }\n totalPages={totalPages}\n onPageChange={isBackendPagination ? pagination?.onPageChange : undefined}\n isLoading={pagination?.isLoading}\n labels={pagination?.labels}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAsJO;AAA+C;AAC3C;AACT;AACoD;AACrB;AACnB;AACZ;AACA;AACA;AACe;AACW;AACf;AACI;AACf;AACA;AACA;AACA;AAEF;AACE;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACE;AACA;AACA;AACA;AAAqB;AAGvB;AACE;AAEA;AACE;AACE;AACA;AACE;AAAyB;AAEzB;AAA4B;AAE9B;AAAO;AACR;AAED;AACE;AACA;AACE;AAAsB;AAEtB;AAAyB;AAE3B;AAAO;AACR;AAGH;AAA2B;AAG7B;AACE;AACE;AAAc;AACM;AACwB;AACiB;AAC1D;AACH;AAEF;AAAO;AAGT;AAA4B;AAC1B;AACS;AACwB;AACqD;AAC5D;AACN;AACpB;AACO;AACL;AACA;AAEI;AACgE;AAC9D;AAEF;AACN;AACkB;AAIZ;AACE;AACA;AAA+B;AACjC;AACF;AAGN;AACE;AACE;AAEK;AAGC;AAME;AAAC;AAAA;AAEuC;AAItC;AAAA;AALsD;AAOzD;AAEN;AAGH;AACE;AAEI;AAAC;AAAA;AACkF;AACvE;AAEmC;AAAA;AAEjD;AAIJ;AACE;AACA;AAEA;AAEK;AAEG;AAAC;AAAA;AACU;AAEP;AACA;AAAuC;AACzC;AAC+B;AAAA;AAEnC;AAMD;AACH;AAEH;AAGH;AAEM;AAEG;AAAsG;AAEnG;AAEE;AAIA;AAGK;AAA8B;AAC9B;AAEL;AACF;AAIE;AAIA;AAEE;AAAA;AAAC;AAAA;AAEW;AAC4D;AAC5B;AAEkC;AAE7E;AAAA;AAPM;AASP;AACkD;AAK9C;AACE;AAAC;AAAA;AAEW;AACmB;AACa;AACiB;AAExB;AAAA;AANvB;AAOd;AAEH;AACL;AACF;AAEJ;AACF;AAIA;AAGM;AAGO;AAEG;AAAC;AAAA;AACU;AACQ;AACY;AAClB;AAAA;AAEf;AAGA;AAAC;AAAA;AAEW;AACmC;AAM7C;AAAA;AARY;AAUf;AAGP;AAC8B;AAGpC;AAGI;AAAC;AAAA;AACC;AACA;AACA;AAEgG;AAEhG;AAC+D;AACxC;AACH;AAAA;AAExB;AAEJ;AAGN;;"}
1
+ {"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["'use client'\n\nimport {\n ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n useReactTable,\n VisibilityState,\n} from '@tanstack/react-table'\nimport * as React from 'react'\n\nimport { Button } from '../Button'\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '../DropdownMenu'\nimport { Skeleton } from '../Skeleton'\nimport { Table as TableComponent, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../Table'\nimport { DataTablePagination } from './DataTablePagination'\nimport { Checkbox } from '../Checkbox'\nimport { TextColumns, FunnelSimple } from '@phosphor-icons/react'\nimport { cn } from '@/lib/utils'\nimport { Typography } from '../Typography'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { useIsMobile } from '@/lib/useMobile'\nimport { Badge } from '../Badge'\n\ntype BasePaginationProps = {\n /** Number of rows per page */\n readonly pageSize: number\n /** Whether the pagination is in a loading state */\n readonly isLoading?: boolean\n /** Text customization for pagination */\n readonly labels?: {\n /** Text shown before the page size number (default: \"Showing\") */\n showing?: string\n /** Text shown before the total number (default: \"of\") */\n of?: string\n /** Text shown after the total number (default: \"results\") */\n results?: string\n /** Aria label for previous page button (default: \"Previous page\") */\n previousPage?: string\n /** Aria label for next page button (default: \"Next page\") */\n nextPage?: string\n /** Aria label for page number (default: \"Page {number}\") */\n pageLabel?: string\n }\n}\n\ntype BackendPaginationProps = BasePaginationProps & {\n /** Current page */\n readonly currentPage: number\n /** Total number of items */\n readonly total: number\n /** Callback when page changes */\n readonly onPageChange: (page: number) => void\n}\n\n/**\n * Type helper to check if a type has an 'id' property\n */\ntype HasId<T> = T extends { id: string | number } ? true : false\n\n/**\n * Props for the DataTable component\n * @template TData The type of data being displayed in the table\n */\nexport type DataTableProps<TData> = {\n /** Array of column definitions that describe the table structure */\n readonly columns: Array<ColumnDef<TData>>\n /** Array of data items to be displayed in the table */\n readonly data: Array<TData>\n /** Whether to show the column visibility toggle menu */\n readonly showColumnVisibilityControls?: boolean\n /** Whether the table is in a loading state */\n readonly isLoading?: boolean\n /** Pagination configuration. If not provided, pagination is disabled */\n readonly pagination?: BasePaginationProps | BackendPaginationProps\n /** Primary filters that appear directly above the table */\n readonly primaryFilters?: React.ReactNode\n /** Secondary filters that appear in the filters dropdown */\n readonly secondaryFilters?: React.ReactNode\n /** Number of active primary filters */\n readonly activePrimaryFiltersCount?: number\n /** Number of active secondary filters */\n readonly activeSecondaryFiltersCount?: number\n /** Text customization for filters */\n readonly labels?: {\n /** Text for the column visibility button (default: \"Hide columns\") */\n columnVisibilityButton?: string\n /** Text for the filters button when only secondary filters are present (default: \"Filters\") */\n filters?: string\n /** Text for the more filters button when both primary and secondary filters are present (default: \"More filters\") */\n moreFilters?: string\n }\n /** Callback when all rows are selected */\n readonly onSelectAll?: (selected: boolean) => void\n /** Callback when a row is selected */\n readonly onSelect?: (selected: boolean, row: TData) => void\n /** Optional className for the table container */\n readonly className?: string\n /** Optional className for the table */\n readonly tableClassName?: string\n} & (HasId<TData> extends true\n ? {\n /** Function to get unique identifier from a row. Not needed when data has 'id' property */\n readonly getRowId?: never\n }\n : {\n /** Function to get unique identifier from a row. Required when data doesn't have 'id' property */\n readonly getRowId: RowIdentifierFn<TData>\n })\n\n/**\n * Function to get a unique identifier from a row\n */\ntype RowIdentifierFn<T> = (row: T) => string\n\n/**\n * A feature-rich data table component built on top of TanStack Table.\n * Provides sorting, filtering, pagination, and column visibility controls.\n *\n * @template TData The type of data being displayed in the table\n *\n * @example\n * ```tsx\n * type User = {\n * id: string;\n * name: string;\n * email: string;\n * };\n *\n * const columns: ColumnDef<User>[] = [\n * {\n * accessorKey: 'name',\n * header: 'Name',\n * },\n * {\n * accessorKey: 'email',\n * header: 'Email',\n * },\n * ];\n *\n * const data: User[] = [\n * { id: '1', name: 'John', email: 'john@example.com' },\n * { id: '2', name: 'Jane', email: 'jane@example.com' },\n * ];\n *\n * <DataTable columns={columns} data={data} />\n * ```\n */\nexport function DataTable<TData extends object = any>({\n columns: userColumns,\n data,\n getRowId = (row: TData) => (row as { id: string })?.id,\n showColumnVisibilityControls = true,\n isLoading = false,\n pagination,\n primaryFilters,\n secondaryFilters,\n activePrimaryFiltersCount = 0,\n activeSecondaryFiltersCount = 0,\n labels = {\n columnVisibilityButton: 'Hide columns',\n filters: 'Filters',\n moreFilters: 'More filters',\n },\n onSelectAll,\n onSelect,\n className,\n tableClassName,\n}: DataTableProps<TData>) {\n const isMobile = useIsMobile()\n const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})\n const [isAllRowsSelected, setIsAllRowsSelected] = React.useState(false)\n const [deselectedRows, setDeselectedRows] = React.useState<Record<string, boolean>>({})\n const [selectedRows, setSelectedRows] = React.useState<Record<string, boolean>>({})\n const [pageIndex, setPageIndex] = React.useState(0)\n\n const isBackendPagination = pagination && 'onPageChange' in pagination\n const total = isBackendPagination ? pagination.total : data.length\n const pageSize = pagination?.pageSize ?? data.length\n const totalPages = Math.ceil(total / pageSize)\n\n const isSelectable = typeof onSelectAll === 'function' || typeof onSelect === 'function'\n\n const handleSelectAll = (checked: boolean) => {\n setIsAllRowsSelected(checked)\n setDeselectedRows({})\n setSelectedRows({})\n onSelectAll?.(checked)\n }\n\n const handleRowSelect = (checked: boolean, rowData: TData) => {\n const rowId = (getRowId as (row: TData) => string)(rowData)\n\n if (isAllRowsSelected) {\n setDeselectedRows((prev) => {\n const newDeselections = { ...prev }\n if (!checked) {\n newDeselections[rowId] = true\n } else {\n delete newDeselections[rowId]\n }\n return newDeselections\n })\n } else {\n setSelectedRows((prev) => {\n const newSelection = { ...prev }\n if (checked) {\n newSelection[rowId] = true\n } else {\n delete newSelection[rowId]\n }\n return newSelection\n })\n }\n\n onSelect?.(checked, rowData)\n }\n\n const rowSelection = React.useMemo(() => {\n if (isAllRowsSelected) {\n return Object.fromEntries(\n data.map((row) => [\n (getRowId as (row: TData) => string)(row),\n !deselectedRows[(getRowId as (row: TData) => string)(row)],\n ]),\n )\n }\n return selectedRows\n }, [data, isAllRowsSelected, deselectedRows, selectedRows, getRowId])\n\n const table = useReactTable({\n data,\n columns: userColumns,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: pagination && !isBackendPagination ? getPaginationRowModel() : undefined,\n onColumnVisibilityChange: setColumnVisibility,\n enableRowSelection: isSelectable,\n getRowId: getRowId,\n state: {\n columnVisibility,\n rowSelection,\n pagination: pagination\n ? {\n pageIndex: isBackendPagination ? pagination.currentPage - 1 : pageIndex,\n pageSize,\n }\n : undefined,\n },\n manualPagination: isBackendPagination,\n onPaginationChange: isBackendPagination\n ? undefined\n : (updater) => {\n if (typeof updater === 'function') {\n const newState = updater({ pageIndex, pageSize })\n setPageIndex(newState.pageIndex)\n }\n },\n })\n\n const renderTableBody = () => {\n if (isLoading) {\n return Array.from({ length: pageSize ?? 10 }).map((_, rowIndex) => (\n <TableRow key={`skeleton-row-${rowIndex.toString()}`}>\n {isSelectable && (\n <TableCell className=\"w-[50px]\">\n <Checkbox checked={false} disabled />\n </TableCell>\n )}\n {table\n .getAllColumns()\n .filter((column) => column.getIsVisible())\n .map((column) => (\n <TableCell\n key={`skeleton-cell-${rowIndex.toString()}-${column.id}`}\n style={{ width: column.columnDef.size }}\n >\n <div className={cn('flex items-center justify-center', column.id === 'actions' && 'justify-end')}>\n <Skeleton className={cn(column.id === 'actions' ? 'h-8 w-8' : 'h-[20px] w-full')} />\n </div>\n </TableCell>\n ))}\n </TableRow>\n ))\n }\n\n if (data.length === 0) {\n return (\n <TableRow>\n <TableCell\n colSpan={isSelectable ? table.getAllColumns().length + 1 : table.getAllColumns().length}\n className=\"h-[200px] text-center\"\n >\n <Typography color=\"neutral\">No data available</Typography>\n </TableCell>\n </TableRow>\n )\n }\n\n return table.getRowModel().rows.map((row) => {\n const rowId = (getRowId as (row: TData) => string)(row.original)\n const isSelected = rowSelection[rowId] ?? false\n\n return (\n <TableRow key={rowId} data-selected={isSelected}>\n {isSelectable && (\n <TableCell className=\"w-[50px]\">\n <Checkbox\n checked={isSelected}\n onCheckedChange={(checked) => {\n const isChecked = checked === true\n handleRowSelect(isChecked, row.original)\n }}\n aria-label={`Select row ${rowId}`}\n />\n </TableCell>\n )}\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} style={{ width: cell.column.columnDef.size }}>\n <Typography>{flexRender(cell.column.columnDef.cell, cell.getContext())}</Typography>\n </TableCell>\n ))}\n </TableRow>\n )\n })\n }\n\n return (\n <div className={cn('flex h-full min-h-0 w-full flex-1 flex-col gap-2 overflow-hidden', className)}>\n {(showColumnVisibilityControls || primaryFilters || secondaryFilters) && (\n <div className=\"flex flex-shrink-0 items-end justify-between p-1\">\n {!isMobile && (primaryFilters ? <div className=\"flex items-center gap-2\">{primaryFilters}</div> : <div />)}\n <div className={cn('flex items-center gap-2', isMobile ? 'w-full justify-end' : '')}>\n {(isMobile ? primaryFilters || secondaryFilters : secondaryFilters) && (\n <PopoverRoot>\n <PopoverTrigger asChild>\n <Button variant=\"text\" size=\"sm\" StartIcon={FunnelSimple} className=\"relative whitespace-nowrap\">\n {((isMobile && activePrimaryFiltersCount + activeSecondaryFiltersCount > 0) ||\n (!isMobile && activeSecondaryFiltersCount > 0)) && (\n <Badge\n count={\n isMobile\n ? activePrimaryFiltersCount + activeSecondaryFiltersCount\n : activeSecondaryFiltersCount\n }\n color=\"primary\"\n ping={false}\n className=\"absolute -right-1 -top-1\"\n />\n )}\n {!primaryFilters || isMobile ? labels.filters : labels.moreFilters}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"center\" className=\"w-fit p-4\">\n <div className=\"flex flex-col gap-4\">\n {isMobile && primaryFilters && primaryFilters}\n {secondaryFilters}\n </div>\n </PopoverContent>\n </PopoverRoot>\n )}\n {showColumnVisibilityControls && (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"text\" size=\"sm\" className={cn('whitespace-nowrap')} StartIcon={TextColumns}>\n {labels.columnVisibilityButton ?? 'Hide columns'}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuCheckboxItem\n key={'all-columns'}\n className=\"capitalize\"\n checked={table.getAllColumns().every((column) => column.getIsVisible())}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(value) =>\n table.getAllColumns().forEach((column) => column.toggleVisibility(!!value))\n }\n >\n Select all\n </DropdownMenuCheckboxItem>\n <DropdownMenuSeparator className=\"bg-neutral-100\" />\n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n <DropdownMenuCheckboxItem\n key={column.id}\n className=\"capitalize\"\n checked={column.getIsVisible()}\n onSelect={(event) => event.preventDefault()}\n onCheckedChange={(value) => column.toggleVisibility(!!value)}\n >\n {column.columnDef.header?.toString()}\n </DropdownMenuCheckboxItem>\n )\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n )}\n </div>\n </div>\n )}\n\n <div className=\"flex min-h-0 flex-1 flex-col rounded-md border bg-white\">\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <div className=\"h-full overflow-auto\">\n <TableComponent className=\"w-full\" tableClassName={cn('table-fixed', tableClassName)}>\n <TableHeader className=\"sticky top-0 z-10 bg-neutral-50\">\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {isSelectable && (\n <TableHead className=\"w-[50px]\">\n <Checkbox\n checked={isAllRowsSelected}\n onCheckedChange={handleSelectAll}\n disabled={isLoading || !data.length}\n aria-label=\"Select all rows\"\n />\n </TableHead>\n )}\n {headerGroup.headers.map((header) => (\n <TableHead\n key={header.id}\n className=\"whitespace-normal\"\n style={{ width: header.column.columnDef.size }}\n >\n <Typography weight=\"medium\">\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n </Typography>\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <TableBody>{renderTableBody()}</TableBody>\n </TableComponent>\n </div>\n </div>\n {!!pagination && (\n <div className=\"border-t px-4 py-2\">\n <DataTablePagination\n table={table}\n total={total}\n pageSize={pageSize}\n currentPage={\n isBackendPagination ? pagination?.currentPage : table.getState().pagination?.pageIndex + 1 || 1\n }\n totalPages={totalPages}\n onPageChange={isBackendPagination ? pagination?.onPageChange : undefined}\n isLoading={pagination?.isLoading}\n labels={pagination?.labels}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA2JO;AAA+C;AAC3C;AACT;AACoD;AACrB;AACnB;AACZ;AACA;AACA;AAC4B;AACE;AACrB;AACiB;AACf;AACI;AACf;AACA;AACA;AACA;AAEF;AACE;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AAEA;AAEA;AACE;AACA;AACA;AACA;AAAqB;AAGvB;AACE;AAEA;AACE;AACE;AACA;AACE;AAAyB;AAEzB;AAA4B;AAE9B;AAAO;AACR;AAED;AACE;AACA;AACE;AAAsB;AAEtB;AAAyB;AAE3B;AAAO;AACR;AAGH;AAA2B;AAG7B;AACE;AACE;AAAc;AACM;AACwB;AACiB;AAC1D;AACH;AAEF;AAAO;AAGT;AAA4B;AAC1B;AACS;AACwB;AACqD;AAC5D;AACN;AACpB;AACO;AACL;AACA;AAEI;AACgE;AAC9D;AAEF;AACN;AACkB;AAIZ;AACE;AACA;AAA+B;AACjC;AACF;AAGN;AACE;AACE;AAEK;AAGC;AAME;AAAC;AAAA;AAEuC;AAItC;AAAA;AALsD;AAOzD;AAEN;AAGH;AACE;AAEI;AAAC;AAAA;AACkF;AACvE;AAEmC;AAAA;AAEjD;AAIJ;AACE;AACA;AAEA;AAEK;AAEG;AAAC;AAAA;AACU;AAEP;AACA;AAAuC;AACzC;AAC+B;AAAA;AAEnC;AAMD;AACH;AAEH;AAGH;AAEM;AAEG;AAAsG;AAEnG;AAEE;AAEO;AAED;AAAC;AAAA;AAIO;AAEA;AACA;AACI;AAAA;AACZ;AAEqD;AAE3D;AAGK;AAA8B;AAC9B;AAEL;AACF;AAIE;AAIA;AAEE;AAAA;AAAC;AAAA;AAEW;AAC4D;AAC5B;AAEkC;AAE7E;AAAA;AAPM;AASP;AACkD;AAK9C;AACE;AAAC;AAAA;AAEW;AACmB;AACa;AACiB;AAExB;AAAA;AANvB;AAOd;AAEH;AACL;AACF;AAEJ;AACF;AAIA;AAGM;AAGO;AAEG;AAAC;AAAA;AACU;AACQ;AACY;AAClB;AAAA;AAEf;AAGA;AAAC;AAAA;AAEW;AACmC;AAM7C;AAAA;AARY;AAUf;AAGP;AAC8B;AAGpC;AAGI;AAAC;AAAA;AACC;AACA;AACA;AAEgG;AAEhG;AAC+D;AACxC;AACH;AAAA;AAExB;AAEJ;AAGN;;"}
@@ -37,3 +37,4 @@ declare namespace DatePicker {
37
37
  var displayName: string;
38
38
  }
39
39
  export { DatePicker };
40
+ export type { DateRange };
@@ -86,15 +86,15 @@ function DatePicker(props) {
86
86
  id: rest.id,
87
87
  variant: "ghost",
88
88
  className: cn(
89
- "w-fit justify-start text-left font-normal",
89
+ "relative flex w-fit items-center justify-start text-left font-normal",
90
90
  !(variant === "single" ? singleDate : dateRange) && "text-muted-foreground",
91
91
  buttonVariants({ variant: "input" }),
92
92
  buttonClassName
93
93
  ),
94
94
  disabled: typeof rest.disabled === "boolean" ? rest.disabled : false,
95
95
  children: [
96
- /* @__PURE__ */ jsx(CalendarBlank, { className: "mr-2 h-4 w-4 shrink-0" }),
97
- /* @__PURE__ */ jsx("span", { children: formatDate() })
96
+ /* @__PURE__ */ jsx(CalendarBlank, { className: "absolute left-4 h-4 w-4 shrink-0" }),
97
+ /* @__PURE__ */ jsx("span", { className: "w-full pl-7 text-center", children: formatDate() })
98
98
  ]
99
99
  }
100
100
  ) }),
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.js","sources":["../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { format } from 'date-fns'\nimport { DateRange, PropsBase } from 'react-day-picker'\n\nimport { cn } from '@/lib/utils'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { CalendarBlank } from '@phosphor-icons/react'\n\ntype BaseDatePickerProps = {\n /**\n * Placeholder text displayed when no date is selected\n * @default 'Pick a date'\n */\n placeholder?: string\n /**\n * Format string to use when displaying the selected date\n * @default 'MMM d, yyyy'\n */\n format?: string\n /**\n * ClassName for the button\n */\n buttonClassName?: string\n} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect'>\n\ntype SingleDatePickerProps = {\n variant?: 'single'\n value?: Date\n initialValue?: Date\n onChange?: (date: Date | undefined) => void\n closeOnSelect?: boolean\n showYearSwitcher?: boolean\n} & BaseDatePickerProps\n\ntype RangeDatePickerProps = {\n variant: 'range'\n value?: DateRange\n initialValue?: DateRange\n onChange?: (date: DateRange | undefined) => void\n closeOnSelect?: never\n showYearSwitcher?: never\n} & BaseDatePickerProps\n\nexport type DatePickerProps = SingleDatePickerProps | RangeDatePickerProps\n\nfunction isDateRange(value: any): value is DateRange {\n return typeof value === 'object' && value !== null && 'from' in value\n}\n\nfunction DatePicker(props: DatePickerProps) {\n const {\n variant = 'single',\n placeholder = variant === 'single' ? 'Pick a date' : 'Pick a date range',\n initialValue,\n value,\n onChange,\n buttonClassName,\n closeOnSelect = variant === 'single',\n showYearSwitcher = variant === 'single',\n ...rest\n } = props\n\n const [isOpen, setIsOpen] = React.useState(false)\n\n const [internalSingleDate, setInternalSingleDate] = React.useState<Date | undefined>(\n variant === 'single' && initialValue instanceof Date ? initialValue : undefined,\n )\n const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>(\n variant === 'range' && isDateRange(initialValue) ? initialValue : undefined,\n )\n\n const singleDate = variant === 'single' && value instanceof Date ? value : internalSingleDate\n const dateRange = variant === 'range' && isDateRange(value) ? value : internalDateRange\n\n const handleSelect = React.useCallback(\n (selectedDate: Date | DateRange | undefined) => {\n if (variant === 'single') {\n const date = selectedDate as Date | undefined\n setInternalSingleDate(date)\n if (onChange && typeof onChange === 'function') (onChange as (date: Date | undefined) => void)(date)\n if (closeOnSelect) {\n setIsOpen(false)\n }\n } else {\n const range = selectedDate as DateRange | undefined\n setInternalDateRange(range)\n if (onChange && typeof onChange === 'function') (onChange as (range: DateRange | undefined) => void)(range)\n }\n },\n [variant, onChange, closeOnSelect],\n )\n\n const formatDate = () => {\n if (variant === 'single') {\n return singleDate ? format(singleDate, rest.format ?? 'MMM d, yyyy') : placeholder\n }\n\n if (!dateRange) return placeholder\n return `${dateRange.from ? format(dateRange.from, rest.format ?? 'MMM d, yyyy') : ''} - ${\n dateRange.to ? format(dateRange.to, rest.format ?? 'MMM d, yyyy') : ''\n }`\n }\n\n const calendarProps = React.useMemo(() => {\n const baseProps = {\n ...rest,\n initialFocus: true,\n }\n\n if (variant === 'single') {\n return {\n ...baseProps,\n mode: 'single' as const,\n selected: singleDate,\n onSelect: (date: Date | undefined) => handleSelect(date),\n defaultMonth: singleDate ?? new Date(),\n }\n }\n\n return {\n ...baseProps,\n mode: 'range' as const,\n selected: dateRange,\n onSelect: (range: DateRange | undefined) => handleSelect(range),\n defaultMonth: dateRange?.from ?? new Date(),\n numberOfMonths: rest.numberOfMonths ?? 2,\n }\n }, [variant, rest, singleDate, dateRange, handleSelect])\n\n return (\n <PopoverRoot open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <Button\n id={rest.id}\n variant=\"ghost\"\n className={cn(\n 'w-fit justify-start text-left font-normal',\n !(variant === 'single' ? singleDate : dateRange) && 'text-muted-foreground',\n buttonVariants({ variant: 'input' }),\n buttonClassName,\n )}\n disabled={typeof rest.disabled === 'boolean' ? rest.disabled : false}\n >\n <CalendarBlank className=\"mr-2 h-4 w-4 shrink-0\" />\n <span>{formatDate()}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"center\">\n <Calendar\n {...calendarProps}\n className=\"border-0\"\n showYearSwitcher={variant === 'single' ? showYearSwitcher : false}\n />\n </PopoverContent>\n </PopoverRoot>\n )\n}\n\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\n"],"names":[],"mappings":";;;;;;;;;;AAiDA;AACE;AACF;AAEA;AACE;AAAM;AACM;AAC2C;AACrD;AACA;AACA;AACA;AAC4B;AACG;AAC5B;AAGL;AAEA;AAA0D;AACc;AAExE;AAAwD;AACY;AAGpE;AACA;AAEA;AAA2B;AAEvB;AACE;AACA;AACA;AACA;AACE;AAAe;AACjB;AAEA;AACA;AACA;AAA0G;AAC5G;AACF;AACiC;AAGnC;AACE;AACE;AAAuE;AAGzE;AACA;AAEA;AAGF;AACE;AAAkB;AACb;AACW;AAGhB;AACE;AAAO;AACF;AACG;AACI;AAC6C;AAClB;AACvC;AAGF;AAAO;AACF;AACG;AACI;AACoD;AACpB;AACH;AACzC;AAGF;AAEI;AACE;AAAC;AAAA;AACU;AACD;AACG;AACT;AACoD;AACjB;AACnC;AACF;AAC+D;AAE/D;AAAiD;AAC7B;AAAA;AAAA;AAExB;AAEE;AAAC;AAAA;AACK;AACM;AACkD;AAAA;AAEhE;AAGN;AAEA;;"}
1
+ {"version":3,"file":"DatePicker.js","sources":["../../../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { format } from 'date-fns'\nimport { DateRange, PropsBase } from 'react-day-picker'\n\nimport { cn } from '@/lib/utils'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { Button, buttonVariants } from '../Button'\nimport { Calendar } from '../Calendar'\nimport { CalendarBlank } from '@phosphor-icons/react'\n\ntype BaseDatePickerProps = {\n /**\n * Placeholder text displayed when no date is selected\n * @default 'Pick a date'\n */\n placeholder?: string\n /**\n * Format string to use when displaying the selected date\n * @default 'MMM d, yyyy'\n */\n format?: string\n /**\n * ClassName for the button\n */\n buttonClassName?: string\n} & Omit<PropsBase, 'mode' | 'selected' | 'onSelect'>\n\ntype SingleDatePickerProps = {\n variant?: 'single'\n value?: Date\n initialValue?: Date\n onChange?: (date: Date | undefined) => void\n closeOnSelect?: boolean\n showYearSwitcher?: boolean\n} & BaseDatePickerProps\n\ntype RangeDatePickerProps = {\n variant: 'range'\n value?: DateRange\n initialValue?: DateRange\n onChange?: (date: DateRange | undefined) => void\n closeOnSelect?: never\n showYearSwitcher?: never\n} & BaseDatePickerProps\n\nexport type DatePickerProps = SingleDatePickerProps | RangeDatePickerProps\n\nfunction isDateRange(value: any): value is DateRange {\n return typeof value === 'object' && value !== null && 'from' in value\n}\n\nfunction DatePicker(props: DatePickerProps) {\n const {\n variant = 'single',\n placeholder = variant === 'single' ? 'Pick a date' : 'Pick a date range',\n initialValue,\n value,\n onChange,\n buttonClassName,\n closeOnSelect = variant === 'single',\n showYearSwitcher = variant === 'single',\n ...rest\n } = props\n\n const [isOpen, setIsOpen] = React.useState(false)\n\n const [internalSingleDate, setInternalSingleDate] = React.useState<Date | undefined>(\n variant === 'single' && initialValue instanceof Date ? initialValue : undefined,\n )\n const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>(\n variant === 'range' && isDateRange(initialValue) ? initialValue : undefined,\n )\n\n const singleDate = variant === 'single' && value instanceof Date ? value : internalSingleDate\n const dateRange = variant === 'range' && isDateRange(value) ? value : internalDateRange\n\n const handleSelect = React.useCallback(\n (selectedDate: Date | DateRange | undefined) => {\n if (variant === 'single') {\n const date = selectedDate as Date | undefined\n setInternalSingleDate(date)\n if (onChange && typeof onChange === 'function') (onChange as (date: Date | undefined) => void)(date)\n if (closeOnSelect) {\n setIsOpen(false)\n }\n } else {\n const range = selectedDate as DateRange | undefined\n setInternalDateRange(range)\n if (onChange && typeof onChange === 'function') (onChange as (range: DateRange | undefined) => void)(range)\n }\n },\n [variant, onChange, closeOnSelect],\n )\n\n const formatDate = () => {\n if (variant === 'single') {\n return singleDate ? format(singleDate, rest.format ?? 'MMM d, yyyy') : placeholder\n }\n\n if (!dateRange) return placeholder\n return `${dateRange.from ? format(dateRange.from, rest.format ?? 'MMM d, yyyy') : ''} - ${\n dateRange.to ? format(dateRange.to, rest.format ?? 'MMM d, yyyy') : ''\n }`\n }\n\n const calendarProps = React.useMemo(() => {\n const baseProps = {\n ...rest,\n initialFocus: true,\n }\n\n if (variant === 'single') {\n return {\n ...baseProps,\n mode: 'single' as const,\n selected: singleDate,\n onSelect: (date: Date | undefined) => handleSelect(date),\n defaultMonth: singleDate ?? new Date(),\n }\n }\n\n return {\n ...baseProps,\n mode: 'range' as const,\n selected: dateRange,\n onSelect: (range: DateRange | undefined) => handleSelect(range),\n defaultMonth: dateRange?.from ?? new Date(),\n numberOfMonths: rest.numberOfMonths ?? 2,\n }\n }, [variant, rest, singleDate, dateRange, handleSelect])\n\n return (\n <PopoverRoot open={isOpen} onOpenChange={setIsOpen}>\n <PopoverTrigger asChild>\n <Button\n id={rest.id}\n variant=\"ghost\"\n className={cn(\n 'relative flex w-fit items-center justify-start text-left font-normal',\n !(variant === 'single' ? singleDate : dateRange) && 'text-muted-foreground',\n buttonVariants({ variant: 'input' }),\n buttonClassName,\n )}\n disabled={typeof rest.disabled === 'boolean' ? rest.disabled : false}\n >\n <CalendarBlank className=\"absolute left-4 h-4 w-4 shrink-0\" />\n <span className=\"w-full pl-7 text-center\">{formatDate()}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-0\" align=\"center\">\n <Calendar\n {...calendarProps}\n className=\"border-0\"\n showYearSwitcher={variant === 'single' ? showYearSwitcher : false}\n />\n </PopoverContent>\n </PopoverRoot>\n )\n}\n\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\nexport type { DateRange }\n"],"names":[],"mappings":";;;;;;;;;;AAiDA;AACE;AACF;AAEA;AACE;AAAM;AACM;AAC2C;AACrD;AACA;AACA;AACA;AAC4B;AACG;AAC5B;AAGL;AAEA;AAA0D;AACc;AAExE;AAAwD;AACY;AAGpE;AACA;AAEA;AAA2B;AAEvB;AACE;AACA;AACA;AACA;AACE;AAAe;AACjB;AAEA;AACA;AACA;AAA0G;AAC5G;AACF;AACiC;AAGnC;AACE;AACE;AAAuE;AAGzE;AACA;AAEA;AAGF;AACE;AAAkB;AACb;AACW;AAGhB;AACE;AAAO;AACF;AACG;AACI;AAC6C;AAClB;AACvC;AAGF;AAAO;AACF;AACG;AACI;AACoD;AACpB;AACH;AACzC;AAGF;AAEI;AACE;AAAC;AAAA;AACU;AACD;AACG;AACT;AACoD;AACjB;AACnC;AACF;AAC+D;AAE/D;AAA4D;AACJ;AAAA;AAAA;AAE5D;AAEE;AAAC;AAAA;AACK;AACM;AACkD;AAAA;AAEhE;AAGN;AAEA;;"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "periplo-ui",
3
3
  "description": "IATI UI library",
4
4
  "private": false,
5
- "version": "3.16.0",
5
+ "version": "3.17.0",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",