periplo-ui 3.10.0 → 3.11.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.
- package/README.md +47 -1
- package/dist/components/Badge/Badge.d.ts +1 -1
- package/dist/components/Button/Button.d.ts +1 -1
- package/dist/components/Button/Button.js +10 -1
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Chip/Chip.d.ts +1 -1
- package/dist/components/Combobox/Combobox.d.ts +38 -31
- package/dist/components/Combobox/Combobox.js +44 -19
- package/dist/components/Combobox/Combobox.js.map +1 -1
- package/dist/components/Combobox/index.d.ts +1 -0
- package/dist/components/Combobox/index.js +2 -0
- package/dist/components/Combobox/index.js.map +1 -0
- package/dist/components/Command/Command.d.ts +7 -7
- package/dist/components/DataTable/DataTable.d.ts +108 -0
- package/dist/components/DataTable/DataTable.js +228 -0
- package/dist/components/DataTable/DataTable.js.map +1 -0
- package/dist/components/DataTable/DataTablePagination.d.ts +36 -0
- package/dist/components/DataTable/DataTablePagination.js +71 -0
- package/dist/components/DataTable/DataTablePagination.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +1 -0
- package/dist/components/DataTable/index.js +2 -0
- package/dist/components/DataTable/index.js.map +1 -0
- package/dist/components/DropdownMenu/DropdownMenu.js +1 -1
- package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +102 -20
- package/dist/components/Pagination/Pagination.js +193 -39
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/index.js +1 -1
- package/dist/components/Table/Table.d.ts +34 -2
- package/dist/components/Table/Table.js +4 -9
- package/dist/components/Table/Table.js.map +1 -1
- package/dist/components/Typography/Typography.d.ts +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/plugin.js +1 -0
- package/dist/lib/plugin.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -14,7 +14,53 @@
|
|
|
14
14
|
npm install periplo-ui
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
3. **
|
|
17
|
+
3. **Configuration:**
|
|
18
|
+
|
|
19
|
+
1. **Root Layout Setup** (Next.js):
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { Providers } from '@src/providers/Providers';
|
|
23
|
+
import { Onest } from 'next/font/google';
|
|
24
|
+
|
|
25
|
+
const fontOnest = Onest({
|
|
26
|
+
subsets: ['latin'],
|
|
27
|
+
display: 'swap',
|
|
28
|
+
variable: '--font-onest',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export default function RootLayout({
|
|
32
|
+
children,
|
|
33
|
+
}: Readonly<{
|
|
34
|
+
children: React.ReactNode;
|
|
35
|
+
}>) {
|
|
36
|
+
return (
|
|
37
|
+
<html lang="es" className={fontOnest.variable}>
|
|
38
|
+
<body className={`antialiased`}>
|
|
39
|
+
<Providers>{children}</Providers>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. **Tailwind Configuration**:
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
import type { Config } from 'tailwindcss';
|
|
50
|
+
import { periploTheme } from 'periplo-ui';
|
|
51
|
+
|
|
52
|
+
export default {
|
|
53
|
+
content: [
|
|
54
|
+
'./node_modules/periplo-ui/dist/**/*.{js,ts,jsx,tsx}',
|
|
55
|
+
'../../node_modules/periplo-ui/dist/**/*.{js,ts,jsx,tsx}',
|
|
56
|
+
'./src/**/*.{js,ts,jsx,tsx}',
|
|
57
|
+
],
|
|
58
|
+
darkMode: 'selector',
|
|
59
|
+
plugins: [periploTheme(), require('tailwindcss-animated')],
|
|
60
|
+
} satisfies Config;
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
4. **Usage:**
|
|
18
64
|
|
|
19
65
|
- Import component:
|
|
20
66
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
intent?: "
|
|
4
|
+
intent?: "neutral" | "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
7
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
@@ -2,7 +2,7 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
2
2
|
import { Icon } from '@phosphor-icons/react';
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
declare const buttonVariants: (props?: ({
|
|
5
|
-
variant?: "primary" | "secondary" | "
|
|
5
|
+
variant?: "primary" | "secondary" | "success" | "error" | "text" | "input" | "ghost" | "inverse-ghost" | null | undefined;
|
|
6
6
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
7
7
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
8
8
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -3,6 +3,7 @@ import { cva } from 'class-variance-authority';
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { cn } from '../../lib/utils.js';
|
|
5
5
|
import { SpinnerGap } from '@phosphor-icons/react/dist/ssr';
|
|
6
|
+
import { typographyVariants } from '../Typography/Typography.js';
|
|
6
7
|
|
|
7
8
|
const buttonVariants = cva(
|
|
8
9
|
"inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
@@ -18,7 +19,8 @@ const buttonVariants = cva(
|
|
|
18
19
|
"inverse-ghost": "border border-neutral-50 text-neutral-50 hover:bg-neutral/50 hover:border-neutral-50 active:bg-neutral-600/50 dark:border-neutral-500 dark:text-primary-foreground dark:hover:bg-neutral-100/50 dark:active:bg-neutral-200/50 disabled:border-neutral-300 disabled:text-neutral-300 dark:disabled:border-neutral-500 dark:disabled:text-neutral-500",
|
|
19
20
|
text: "hover:bg-neutral-50 active:bg-neutral-100 text-primary-foreground disabled:text-neutral-500 dark:disable:text-neutral-300 dark:text-neutral-50 dark:hover:bg-neutral dark:active:bg-neutral-600",
|
|
20
21
|
error: "bg-error text-white hover:bg-error-800 active:bg-error-900 disabled:bg-error-200 disabled:text-neutral-600",
|
|
21
|
-
success: "bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600"
|
|
22
|
+
success: "bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600",
|
|
23
|
+
input: "border border-neutral-200 bg-white text-neutral-950 hover:bg-neutral-50 active:bg-neutral-100 focus-visible:border-neutral-950 disabled:bg-neutral-50 dark:border-neutral-500 dark:bg-neutral-950 dark:text-neutral-50 dark:hover:bg-neutral-800 dark:active:bg-neutral-700 dark:focus-visible:border-neutral-500 focus-visible:ring-0"
|
|
22
24
|
},
|
|
23
25
|
/**
|
|
24
26
|
* Controls the size and padding of the button
|
|
@@ -29,6 +31,13 @@ const buttonVariants = cva(
|
|
|
29
31
|
lg: "h-12 px-6 text-base"
|
|
30
32
|
}
|
|
31
33
|
},
|
|
34
|
+
compoundVariants: [
|
|
35
|
+
{
|
|
36
|
+
variant: "input",
|
|
37
|
+
size: ["sm", "md", "lg"],
|
|
38
|
+
className: typographyVariants({ variant: "body-lg" })
|
|
39
|
+
}
|
|
40
|
+
],
|
|
32
41
|
defaultVariants: {
|
|
33
42
|
variant: "primary",
|
|
34
43
|
size: "md"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\nimport { cn } from '../../lib/utils'\nimport { Icon, IconWeight } from '@phosphor-icons/react'\nimport { SpinnerGap } from '@phosphor-icons/react/dist/ssr'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n /**\n * Defines the visual style of the button\n */\n variant: {\n primary:\n 'bg-primary-500 text-primary-foreground hover:bg-primary-700 active:bg-primary-900 disabled:bg-background-200 dark:disabled:bg-background-200 dark:disabled:text-neutral',\n secondary:\n 'bg-neutral-950 text-neutral-foreground hover:bg-neutral-800 active:bg-neutral-700 disabled:bg-neutral-200 dark:bg-neutral-600 dark:hover:bg-neutral-500 dark:disable:bg-neutral-900 disabled:text-neutral-600 dark:disabled:text-neutral-300',\n ghost:\n 'border border-neutral-500 text-primary-foreground hover:bg-neutral-100/50 active:bg-neutral-200/50 dark:border-neutral dark:text-neutral-50 dark:active:bg-neutral-600/50 disabled:border-neutral-500 dark:hover:bg-neutral/50 disabled:text-neutral-500 dark:disabled:border-neutral-300 dark:disabled:text-neutral-300',\n 'inverse-ghost':\n 'border border-neutral-50 text-neutral-50 hover:bg-neutral/50 hover:border-neutral-50 active:bg-neutral-600/50 dark:border-neutral-500 dark:text-primary-foreground dark:hover:bg-neutral-100/50 dark:active:bg-neutral-200/50 disabled:border-neutral-300 disabled:text-neutral-300 dark:disabled:border-neutral-500 dark:disabled:text-neutral-500',\n text: 'hover:bg-neutral-50 active:bg-neutral-100 text-primary-foreground disabled:text-neutral-500 dark:disable:text-neutral-300 dark:text-neutral-50 dark:hover:bg-neutral dark:active:bg-neutral-600',\n error:\n 'bg-error text-white hover:bg-error-800 active:bg-error-900 disabled:bg-error-200 disabled:text-neutral-600',\n success:\n 'bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600',\n },\n /**\n * Controls the size and padding of the button\n */\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-4 text-sm',\n lg: 'h-12 px-6 text-base',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n },\n },\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n /**\n * The visual style of the button.\n * @default primary\n */\n variant?: 'primary' | 'secondary' | 'ghost' | 'inverse-ghost' | 'text' | 'error' | 'success'\n\n /**\n * The size of the button, affecting height, padding, and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * Icon component to display at the start of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button StartIcon={House}>Home</Button>\n */\n StartIcon?: Icon\n\n /**\n * Icon component to display at the end of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button EndIcon={ArrowRight}>Next</Button>\n */\n EndIcon?: Icon\n\n /**\n * When true, displays a loading spinner and disables the button.\n * The spinner replaces the StartIcon if present.\n * @default false\n */\n loading?: boolean\n\n /**\n * When true, creates a circular button with only the StartIcon visible.\n * @default false\n */\n iconOnly?: boolean\n\n /**\n * The content to display inside the button.\n * Not displayed when iconOnly is true.\n */\n children?: React.ReactNode\n}\n\n/**\n * A versatile button component that supports multiple variants, sizes, and icon placements.\n *\n * @example\n * // Basic usage\n * <Button>Click me</Button>\n *\n * // With icon\n * <Button StartIcon={House}>Home</Button>\n *\n * // Icon only button\n * <Button StartIcon={Plus} iconOnly aria-label=\"Add item\" />\n *\n * // Loading state\n * <Button loading>Processing...</Button>\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'primary', size = 'md', StartIcon, EndIcon, loading, iconOnly, ...props }, ref) => {\n const iconProps = (): { size: number; weight: IconWeight } => {\n switch (size) {\n case 'sm':\n return { size: 16, weight: 'regular' }\n case 'lg':\n return { size: 20, weight: 'regular' }\n default:\n return { size: 18, weight: 'regular' }\n }\n }\n\n const getIconOnlyClasses = () => {\n switch (size) {\n case 'sm':\n return 'h-8 w-8'\n case 'lg':\n return 'h-12 w-12'\n default:\n return 'h-10 w-10'\n }\n }\n\n return (\n <button\n className={cn(\n buttonVariants({ variant, size, className }),\n iconOnly && 'rounded-full p-0',\n iconOnly && getIconOnlyClasses(),\n className,\n )}\n ref={ref}\n disabled={loading}\n {...props}\n >\n {loading && <SpinnerGap {...iconProps()} className=\"animate-spin\" aria-label=\"Loading\" />}\n {StartIcon && !loading && <StartIcon {...iconProps()} />}\n {iconOnly ? <span className=\"sr-only\">{props.children}</span> : props.children}\n {EndIcon && !iconOnly && <EndIcon {...iconProps()} />}\n </button>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.js","sources":["../../../src/components/Button/Button.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority'\nimport * as React from 'react'\nimport { cn } from '../../lib/utils'\nimport { Icon, IconWeight } from '@phosphor-icons/react'\nimport { SpinnerGap } from '@phosphor-icons/react/dist/ssr'\nimport { typographyVariants } from '../Typography'\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',\n {\n variants: {\n /**\n * Defines the visual style of the button\n */\n variant: {\n primary:\n 'bg-primary-500 text-primary-foreground hover:bg-primary-700 active:bg-primary-900 disabled:bg-background-200 dark:disabled:bg-background-200 dark:disabled:text-neutral',\n secondary:\n 'bg-neutral-950 text-neutral-foreground hover:bg-neutral-800 active:bg-neutral-700 disabled:bg-neutral-200 dark:bg-neutral-600 dark:hover:bg-neutral-500 dark:disable:bg-neutral-900 disabled:text-neutral-600 dark:disabled:text-neutral-300',\n ghost:\n 'border border-neutral-500 text-primary-foreground hover:bg-neutral-100/50 active:bg-neutral-200/50 dark:border-neutral dark:text-neutral-50 dark:active:bg-neutral-600/50 disabled:border-neutral-500 dark:hover:bg-neutral/50 disabled:text-neutral-500 dark:disabled:border-neutral-300 dark:disabled:text-neutral-300',\n 'inverse-ghost':\n 'border border-neutral-50 text-neutral-50 hover:bg-neutral/50 hover:border-neutral-50 active:bg-neutral-600/50 dark:border-neutral-500 dark:text-primary-foreground dark:hover:bg-neutral-100/50 dark:active:bg-neutral-200/50 disabled:border-neutral-300 disabled:text-neutral-300 dark:disabled:border-neutral-500 dark:disabled:text-neutral-500',\n text: 'hover:bg-neutral-50 active:bg-neutral-100 text-primary-foreground disabled:text-neutral-500 dark:disable:text-neutral-300 dark:text-neutral-50 dark:hover:bg-neutral dark:active:bg-neutral-600',\n error:\n 'bg-error text-white hover:bg-error-800 active:bg-error-900 disabled:bg-error-200 disabled:text-neutral-600',\n success:\n 'bg-success text-white hover:bg-success-800 active:bg-success-900 disabled:bg-success-200 disabled:text-neutral-600',\n input:\n 'border border-neutral-200 bg-white text-neutral-950 hover:bg-neutral-50 active:bg-neutral-100 focus-visible:border-neutral-950 disabled:bg-neutral-50 dark:border-neutral-500 dark:bg-neutral-950 dark:text-neutral-50 dark:hover:bg-neutral-800 dark:active:bg-neutral-700 dark:focus-visible:border-neutral-500 focus-visible:ring-0',\n },\n /**\n * Controls the size and padding of the button\n */\n size: {\n sm: 'h-8 px-3 text-sm',\n md: 'h-10 px-4 text-sm',\n lg: 'h-12 px-6 text-base',\n },\n },\n compoundVariants: [\n {\n variant: 'input',\n size: ['sm', 'md', 'lg'],\n className: typographyVariants({ variant: 'body-lg' }),\n },\n ],\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n },\n },\n)\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n /**\n * The visual style of the button.\n * @default primary\n */\n variant?: 'primary' | 'secondary' | 'ghost' | 'inverse-ghost' | 'text' | 'error' | 'success'\n\n /**\n * The size of the button, affecting height, padding, and font size.\n * @default md\n */\n size?: 'sm' | 'md' | 'lg'\n\n /**\n * Icon component to display at the start of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button StartIcon={House}>Home</Button>\n */\n StartIcon?: Icon\n\n /**\n * Icon component to display at the end of the button content.\n * Use Phosphor icons for consistent styling.\n * @example <Button EndIcon={ArrowRight}>Next</Button>\n */\n EndIcon?: Icon\n\n /**\n * When true, displays a loading spinner and disables the button.\n * The spinner replaces the StartIcon if present.\n * @default false\n */\n loading?: boolean\n\n /**\n * When true, creates a circular button with only the StartIcon visible.\n * @default false\n */\n iconOnly?: boolean\n\n /**\n * The content to display inside the button.\n * Not displayed when iconOnly is true.\n */\n children?: React.ReactNode\n}\n\n/**\n * A versatile button component that supports multiple variants, sizes, and icon placements.\n *\n * @example\n * // Basic usage\n * <Button>Click me</Button>\n *\n * // With icon\n * <Button StartIcon={House}>Home</Button>\n *\n * // Icon only button\n * <Button StartIcon={Plus} iconOnly aria-label=\"Add item\" />\n *\n * // Loading state\n * <Button loading>Processing...</Button>\n */\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'primary', size = 'md', StartIcon, EndIcon, loading, iconOnly, ...props }, ref) => {\n const iconProps = (): { size: number; weight: IconWeight } => {\n switch (size) {\n case 'sm':\n return { size: 16, weight: 'regular' }\n case 'lg':\n return { size: 20, weight: 'regular' }\n default:\n return { size: 18, weight: 'regular' }\n }\n }\n\n const getIconOnlyClasses = () => {\n switch (size) {\n case 'sm':\n return 'h-8 w-8'\n case 'lg':\n return 'h-12 w-12'\n default:\n return 'h-10 w-10'\n }\n }\n\n return (\n <button\n className={cn(\n buttonVariants({ variant, size, className }),\n iconOnly && 'rounded-full p-0',\n iconOnly && getIconOnlyClasses(),\n className,\n )}\n ref={ref}\n disabled={loading}\n {...props}\n >\n {loading && <SpinnerGap {...iconProps()} className=\"animate-spin\" aria-label=\"Loading\" />}\n {StartIcon && !loading && <StartIcon {...iconProps()} />}\n {iconOnly ? <span className=\"sr-only\">{props.children}</span> : props.children}\n {EndIcon && !iconOnly && <EndIcon {...iconProps()} />}\n </button>\n )\n },\n)\nButton.displayName = 'Button'\n\nexport { Button, buttonVariants }\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
declare const chipVariants: (props?: ({
|
|
4
|
-
variant?: "primary" | "secondary" | "
|
|
4
|
+
variant?: "primary" | "secondary" | "success" | "error" | "ghost" | "default" | null | undefined;
|
|
5
5
|
size?: "sm" | "md" | "lg" | null | undefined;
|
|
6
6
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
7
7
|
export interface ChipProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof chipVariants> {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
export type
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
/** The text to display for the option */
|
|
5
|
-
label: string;
|
|
6
|
-
/** Additional properties that can be used in custom rendering */
|
|
7
|
-
[key: string]: any;
|
|
8
|
-
};
|
|
9
|
-
export type ComboboxProps = {
|
|
1
|
+
export type ComboboxProps<T> = {
|
|
2
|
+
/** Unique identifier for the combobox */
|
|
3
|
+
id?: string;
|
|
10
4
|
/** Array of options to display in the combobox */
|
|
11
|
-
options:
|
|
5
|
+
options: T[];
|
|
12
6
|
/** Currently selected value */
|
|
13
7
|
value?: string;
|
|
14
8
|
/** Callback fired when selection changes */
|
|
15
9
|
onChange: (value: string) => void;
|
|
10
|
+
/** Function to get the unique identifier from an option. */
|
|
11
|
+
getOptionValue: (option: T) => string;
|
|
12
|
+
/** Function to get the display text from an option. */
|
|
13
|
+
getOptionLabel: (option: T) => string;
|
|
14
|
+
/** Custom render function for options. If not provided, defaults to showing a checkmark and label */
|
|
15
|
+
renderOption?: (option: T, isSelected: boolean) => React.ReactNode;
|
|
16
16
|
/** Placeholder text shown when no option is selected */
|
|
17
17
|
placeholder?: string;
|
|
18
18
|
/** Placeholder text for the search input field */
|
|
@@ -25,8 +25,6 @@ export type ComboboxProps = {
|
|
|
25
25
|
disabled?: boolean;
|
|
26
26
|
/** Maximum height of the options list. Can be any valid CSS height value */
|
|
27
27
|
maxHeight?: string | number;
|
|
28
|
-
/** Custom render function for options. If not provided, defaults to showing a checkbox and label */
|
|
29
|
-
renderOption?: (option: ComboboxOption, isSelected: boolean) => React.ReactNode;
|
|
30
28
|
/** Whether the selection can be cleared by selecting the same option again */
|
|
31
29
|
clearable?: boolean;
|
|
32
30
|
/** Whether to close the dropdown when an option is selected */
|
|
@@ -37,35 +35,44 @@ export type ComboboxProps = {
|
|
|
37
35
|
loadingPlaceholder?: string;
|
|
38
36
|
/** Whether the combobox has an error */
|
|
39
37
|
error?: boolean | string;
|
|
40
|
-
/**
|
|
41
|
-
|
|
38
|
+
/** Custom function to filter options based on search term */
|
|
39
|
+
filterOptions?: (options: T[], searchTerm: string) => T[];
|
|
42
40
|
};
|
|
43
41
|
/**
|
|
44
42
|
* A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.
|
|
45
43
|
*
|
|
46
44
|
* @example
|
|
47
45
|
* ```tsx
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
46
|
+
* interface User {
|
|
47
|
+
* id: string
|
|
48
|
+
* name: string
|
|
49
|
+
* email: string
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* <Combobox<User>
|
|
53
|
+
* options={users}
|
|
54
|
+
* value={selectedUserId}
|
|
55
|
+
* onChange={setSelectedUserId}
|
|
56
|
+
* getOptionValue={(user) => user.id}
|
|
57
|
+
* getOptionLabel={(user) => user.name}
|
|
55
58
|
* />
|
|
56
59
|
* ```
|
|
57
60
|
*
|
|
58
|
-
* @example Custom
|
|
61
|
+
* @example Custom filtering
|
|
59
62
|
* ```tsx
|
|
60
|
-
* <Combobox
|
|
61
|
-
* options={
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
63
|
+
* <Combobox<User>
|
|
64
|
+
* options={users}
|
|
65
|
+
* value={selectedUserId}
|
|
66
|
+
* onChange={setSelectedUserId}
|
|
67
|
+
* getOptionValue={(user) => user.id}
|
|
68
|
+
* getOptionLabel={(user) => user.name}
|
|
69
|
+
* filterOptions={(options, searchTerm) =>
|
|
70
|
+
* options.filter(user =>
|
|
71
|
+
* user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
72
|
+
* user.email.toLowerCase().includes(searchTerm.toLowerCase())
|
|
73
|
+
* )
|
|
74
|
+
* }
|
|
68
75
|
* />
|
|
69
76
|
* ```
|
|
70
77
|
*/
|
|
71
|
-
export declare const Combobox: ({ options, value, onChange, placeholder, searchPlaceholder, emptyMessage, className, disabled, maxHeight, renderOption, clearable, closeOnSelect, loading, loadingPlaceholder, error,
|
|
78
|
+
export declare const Combobox: <T extends object>({ id, options, value, onChange, getOptionValue, getOptionLabel, placeholder, searchPlaceholder, emptyMessage, className, disabled, maxHeight, renderOption, clearable, closeOnSelect, loading, loadingPlaceholder, error, filterOptions, }: ComboboxProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -2,17 +2,20 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { CaretUpDown, Check } from '@phosphor-icons/react';
|
|
3
3
|
import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from '../Command/Command.js';
|
|
4
4
|
import { PopoverRoot, PopoverTrigger, PopoverContent } from '../Popover/Popover.js';
|
|
5
|
-
import { useState } from 'react';
|
|
5
|
+
import { useState, useMemo } from 'react';
|
|
6
6
|
import { cn } from '../../lib/utils.js';
|
|
7
|
-
import { Button } from '../Button/Button.js';
|
|
7
|
+
import { Button, buttonVariants } from '../Button/Button.js';
|
|
8
8
|
|
|
9
9
|
const Combobox = ({
|
|
10
|
+
id,
|
|
10
11
|
options,
|
|
11
12
|
value,
|
|
12
13
|
onChange,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
getOptionValue,
|
|
15
|
+
getOptionLabel,
|
|
16
|
+
placeholder = "Select...",
|
|
17
|
+
searchPlaceholder = "Search...",
|
|
18
|
+
emptyMessage = "No results found.",
|
|
16
19
|
className = "w-60",
|
|
17
20
|
disabled = false,
|
|
18
21
|
maxHeight = "300px",
|
|
@@ -22,10 +25,17 @@ const Combobox = ({
|
|
|
22
25
|
loading = false,
|
|
23
26
|
loadingPlaceholder = "Cargando...",
|
|
24
27
|
error = false,
|
|
25
|
-
|
|
28
|
+
filterOptions
|
|
26
29
|
}) => {
|
|
27
30
|
const [open, setOpen] = useState(false);
|
|
28
|
-
const
|
|
31
|
+
const [searchTerm, setSearchTerm] = useState("");
|
|
32
|
+
const selectedOption = options.find((option) => getOptionValue(option) === value);
|
|
33
|
+
const filteredOptions = useMemo(() => {
|
|
34
|
+
if (!filterOptions) {
|
|
35
|
+
return options.filter((option) => getOptionLabel(option).toLowerCase().includes(searchTerm.toLowerCase()));
|
|
36
|
+
}
|
|
37
|
+
return searchTerm ? filterOptions(options, searchTerm) : options;
|
|
38
|
+
}, [filterOptions, options, searchTerm, getOptionLabel]);
|
|
29
39
|
const handleSelect = (currentValue) => {
|
|
30
40
|
const newValue = clearable && currentValue === value ? "" : currentValue;
|
|
31
41
|
onChange(newValue);
|
|
@@ -43,30 +53,45 @@ const Combobox = ({
|
|
|
43
53
|
disabled,
|
|
44
54
|
variant: "text",
|
|
45
55
|
className: cn(
|
|
46
|
-
|
|
56
|
+
buttonVariants({ variant: "input" }),
|
|
57
|
+
"flex h-10 w-full justify-between rounded-lg",
|
|
47
58
|
open && "border-neutral-950",
|
|
48
|
-
"
|
|
49
|
-
"focus-visible:border-neutral-950 focus-visible:ring-0",
|
|
50
|
-
disabled && "cursor-not-allowed bg-neutral-50 opacity-50",
|
|
59
|
+
disabled && "cursor-not-allowed",
|
|
51
60
|
error && "border-error-400 focus-visible:border-error-700",
|
|
52
61
|
className
|
|
53
62
|
),
|
|
54
63
|
"aria-expanded": open,
|
|
55
64
|
"aria-haspopup": "listbox",
|
|
56
65
|
children: [
|
|
57
|
-
/* @__PURE__ */ jsx("span", { className: cn("block truncate", !selectedOption
|
|
66
|
+
/* @__PURE__ */ jsx("span", { className: cn("block truncate", !selectedOption && "text-neutral-300"), children: selectedOption ? getOptionLabel(selectedOption) : placeholder }),
|
|
58
67
|
/* @__PURE__ */ jsx(CaretUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
|
|
59
68
|
]
|
|
60
69
|
}
|
|
61
70
|
) }),
|
|
62
|
-
/* @__PURE__ */ jsx(PopoverContent, { className: "p-0", children: /* @__PURE__ */ jsxs(Command, { children: [
|
|
63
|
-
/* @__PURE__ */ jsx(
|
|
71
|
+
/* @__PURE__ */ jsx(PopoverContent, { className: "p-0", children: /* @__PURE__ */ jsxs(Command, { shouldFilter: false, children: [
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
CommandInput,
|
|
74
|
+
{
|
|
75
|
+
placeholder: searchPlaceholder,
|
|
76
|
+
disabled: loading,
|
|
77
|
+
value: searchTerm,
|
|
78
|
+
onValueChange: setSearchTerm
|
|
79
|
+
}
|
|
80
|
+
),
|
|
64
81
|
/* @__PURE__ */ jsx(CommandList, { style: { maxHeight }, children: loading ? /* @__PURE__ */ jsx("div", { className: "text-muted-foreground flex items-center justify-center py-6 text-sm", children: loadingPlaceholder }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
65
|
-
/* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
|
|
66
|
-
/* @__PURE__ */ jsx(CommandGroup, { children:
|
|
67
|
-
|
|
68
|
-
option
|
|
69
|
-
|
|
82
|
+
filteredOptions.length === 0 && /* @__PURE__ */ jsx(CommandEmpty, { children: emptyMessage }),
|
|
83
|
+
/* @__PURE__ */ jsx(CommandGroup, { children: filteredOptions.map((option) => {
|
|
84
|
+
const optionValue = getOptionValue(option);
|
|
85
|
+
return /* @__PURE__ */ jsx(CommandItem, { value: optionValue, onSelect: handleSelect, children: renderOption ? renderOption(option, value === optionValue) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
86
|
+
/* @__PURE__ */ jsx(
|
|
87
|
+
Check,
|
|
88
|
+
{
|
|
89
|
+
className: `mr-2 h-4 w-4 ${value === optionValue ? "opacity-100" : "opacity-0"}`
|
|
90
|
+
}
|
|
91
|
+
),
|
|
92
|
+
getOptionLabel(option)
|
|
93
|
+
] }) }, optionValue);
|
|
94
|
+
}) })
|
|
70
95
|
] }) })
|
|
71
96
|
] }) })
|
|
72
97
|
] }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { CaretUpDown, Check } from '@phosphor-icons/react'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { useState } from 'react'\nimport { cn } from '../../lib/utils'\nimport { Button } from '../Button'\n\nexport type ComboboxOption = {\n /** The unique identifier or value of the option */\n value: string\n /** The text to display for the option */\n label: string\n /** Additional properties that can be used in custom rendering */\n [key: string]: any\n}\n\nexport type ComboboxProps = {\n /** Array of options to display in the combobox */\n options: ComboboxOption[]\n /** Currently selected value */\n value?: string\n /** Callback fired when selection changes */\n onChange: (value: string) => void\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Custom render function for options. If not provided, defaults to showing a checkbox and label */\n renderOption?: (option: ComboboxOption, isSelected: boolean) => React.ReactNode\n /** Whether the selection can be cleared by selecting the same option again */\n clearable?: boolean\n /** Whether to close the dropdown when an option is selected */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Unique identifier for the combobox */\n id?: string\n}\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example\n * ```tsx\n * <Combobox\n * options={[\n * { value: '1', label: 'Option 1' },\n * { value: '2', label: 'Option 2' }\n * ]}\n * value={selectedValue}\n * onChange={setValue}\n * />\n * ```\n *\n * @example Custom Rendering\n * ```tsx\n * <Combobox\n * options={options}\n * renderOption={(option, isSelected) => (\n * <div className=\"flex items-center\">\n * <CustomIcon className=\"mr-2\" />\n * {option.label}\n * </div>\n * )}\n * />\n * ```\n */\nexport const Combobox = ({\n options,\n value,\n onChange,\n placeholder = 'Seleccionar...',\n searchPlaceholder = 'Buscar...',\n emptyMessage = 'No se encontraron resultados.',\n className = 'w-60',\n disabled = false,\n maxHeight = '300px',\n renderOption,\n clearable = false,\n closeOnSelect = true,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n id,\n}: ComboboxProps) => {\n const [open, setOpen] = useState(false)\n\n const selectedOption = options.find((option) => option.value === value)\n\n const handleSelect = (currentValue: string) => {\n const newValue = clearable && currentValue === value ? '' : currentValue\n onChange(newValue)\n if (closeOnSelect) {\n setOpen(false)\n }\n }\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n 'flex h-10 w-full items-center justify-between rounded-lg border border-neutral-200 bg-white px-3 text-left outline-none transition-colors',\n open && 'border-neutral-950',\n 'hover:bg-neutral-50',\n 'focus-visible:border-neutral-950 focus-visible:ring-0',\n disabled && 'cursor-not-allowed bg-neutral-50 opacity-50',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n >\n <span className={cn('block truncate', !selectedOption?.label && 'text-neutral-300')}>\n {selectedOption?.label ?? placeholder}\n </span>\n <CaretUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"p-0\">\n <Command>\n <CommandInput placeholder={searchPlaceholder} disabled={loading} />\n <CommandList style={{ maxHeight }}>\n {loading ? (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">\n {loadingPlaceholder}\n </div>\n ) : (\n <>\n <CommandEmpty>{emptyMessage}</CommandEmpty>\n <CommandGroup>\n {options.map((option) => (\n <CommandItem key={option.value} value={option.value} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, value === option.value)\n ) : (\n <>\n <Check className={`mr-2 h-4 w-4 ${value === option.value ? 'opacity-100' : 'opacity-0'}`} />\n {option.label}\n </>\n )}\n </CommandItem>\n ))}\n </CommandGroup>\n </>\n )}\n </CommandList>\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-sm text-error-500\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { CaretUpDown, Check } from '@phosphor-icons/react'\nimport { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\nimport { useMemo, useState } from 'react'\nimport { cn } from '../../lib/utils'\nimport { Button, buttonVariants } from '../Button'\n\nexport type ComboboxProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox */\n options: T[]\n /** Currently selected value */\n value?: string\n /** Callback fired when selection changes */\n onChange: (value: string) => void\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether the selection can be cleared by selecting the same option again */\n clearable?: boolean\n /** Whether to close the dropdown when an option is selected */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term */\n filterOptions?: (options: T[], searchTerm: string) => T[]\n}\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example\n * ```tsx\n * interface User {\n * id: string\n * name: string\n * email: string\n * }\n *\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n *\n * @example Custom filtering\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * filterOptions={(options, searchTerm) =>\n * options.filter(user =>\n * user.name.toLowerCase().includes(searchTerm.toLowerCase()) ||\n * user.email.toLowerCase().includes(searchTerm.toLowerCase())\n * )\n * }\n * />\n * ```\n */\nexport const Combobox = <T extends object>({\n id,\n options,\n value,\n onChange,\n getOptionValue,\n getOptionLabel,\n placeholder = 'Select...',\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n disabled = false,\n maxHeight = '300px',\n renderOption,\n clearable = false,\n closeOnSelect = true,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n filterOptions,\n}: ComboboxProps<T>) => {\n const [open, setOpen] = useState(false)\n const [searchTerm, setSearchTerm] = useState('')\n\n const selectedOption = options.find((option) => getOptionValue(option) === value)\n\n const filteredOptions = useMemo(() => {\n if (!filterOptions) {\n return options.filter((option) => getOptionLabel(option).toLowerCase().includes(searchTerm.toLowerCase()))\n }\n\n return searchTerm ? filterOptions(options, searchTerm) : options\n }, [filterOptions, options, searchTerm, getOptionLabel])\n\n const handleSelect = (currentValue: string) => {\n const newValue = clearable && currentValue === value ? '' : currentValue\n onChange(newValue)\n if (closeOnSelect) {\n setOpen(false)\n }\n }\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n id={id}\n type=\"button\"\n disabled={disabled}\n variant=\"text\"\n className={cn(\n buttonVariants({ variant: 'input' }),\n 'flex h-10 w-full justify-between rounded-lg',\n open && 'border-neutral-950',\n disabled && 'cursor-not-allowed',\n error && 'border-error-400 focus-visible:border-error-700',\n className,\n )}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n >\n <span className={cn('block truncate', !selectedOption && 'text-neutral-300')}>\n {selectedOption ? getOptionLabel(selectedOption) : placeholder}\n </span>\n <CaretUpDown className=\"h-4 w-4 shrink-0 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"p-0\">\n <Command shouldFilter={false}>\n <CommandInput\n placeholder={searchPlaceholder}\n disabled={loading}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n <CommandList style={{ maxHeight }}>\n {loading ? (\n <div className=\"text-muted-foreground flex items-center justify-center py-6 text-sm\">\n {loadingPlaceholder}\n </div>\n ) : (\n <>\n {filteredOptions.length === 0 && <CommandEmpty>{emptyMessage}</CommandEmpty>}\n <CommandGroup>\n {filteredOptions.map((option) => {\n const optionValue = getOptionValue(option)\n return (\n <CommandItem key={optionValue} value={optionValue} onSelect={handleSelect}>\n {renderOption ? (\n renderOption(option, value === optionValue)\n ) : (\n <>\n <Check\n className={`mr-2 h-4 w-4 ${value === optionValue ? 'opacity-100' : 'opacity-0'}`}\n />\n {getOptionLabel(option)}\n </>\n )}\n </CommandItem>\n )\n })}\n </CommandGroup>\n </>\n )}\n </CommandList>\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-sm text-error-500\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Combobox';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -6,7 +6,7 @@ declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
|
6
6
|
ref?: React.Ref<HTMLDivElement>;
|
|
7
7
|
} & {
|
|
8
8
|
asChild?: boolean;
|
|
9
|
-
}, "
|
|
9
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
10
10
|
label?: string;
|
|
11
11
|
shouldFilter?: boolean;
|
|
12
12
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -22,7 +22,7 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
22
22
|
ref?: React.Ref<HTMLInputElement>;
|
|
23
23
|
} & {
|
|
24
24
|
asChild?: boolean;
|
|
25
|
-
}, "
|
|
25
|
+
}, "asChild" | "key" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
|
|
26
26
|
value?: string;
|
|
27
27
|
onValueChange?: (search: string) => void;
|
|
28
28
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -32,7 +32,7 @@ declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
|
32
32
|
ref?: React.Ref<HTMLDivElement>;
|
|
33
33
|
} & {
|
|
34
34
|
asChild?: boolean;
|
|
35
|
-
}, "
|
|
35
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
36
36
|
label?: string;
|
|
37
37
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
38
38
|
declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
@@ -41,14 +41,14 @@ declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
|
41
41
|
ref?: React.Ref<HTMLDivElement>;
|
|
42
42
|
} & {
|
|
43
43
|
asChild?: boolean;
|
|
44
|
-
}, "
|
|
44
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
45
45
|
declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
46
46
|
children?: React.ReactNode;
|
|
47
47
|
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
48
48
|
ref?: React.Ref<HTMLDivElement>;
|
|
49
49
|
} & {
|
|
50
50
|
asChild?: boolean;
|
|
51
|
-
}, "
|
|
51
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "heading" | "value"> & {
|
|
52
52
|
heading?: React.ReactNode;
|
|
53
53
|
value?: string;
|
|
54
54
|
forceMount?: boolean;
|
|
@@ -57,7 +57,7 @@ declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<R
|
|
|
57
57
|
ref?: React.Ref<HTMLDivElement>;
|
|
58
58
|
} & {
|
|
59
59
|
asChild?: boolean;
|
|
60
|
-
}, "
|
|
60
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
61
61
|
alwaysRender?: boolean;
|
|
62
62
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
63
63
|
declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
@@ -66,7 +66,7 @@ declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
|
66
66
|
ref?: React.Ref<HTMLDivElement>;
|
|
67
67
|
} & {
|
|
68
68
|
asChild?: boolean;
|
|
69
|
-
}, "
|
|
69
|
+
}, "asChild" | "key" | keyof React.HTMLAttributes<HTMLDivElement>>, "onSelect" | "disabled" | "value"> & {
|
|
70
70
|
disabled?: boolean;
|
|
71
71
|
onSelect?: (value: string) => void;
|
|
72
72
|
value?: string;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { ColumnDef } from '@tanstack/react-table';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
type BasePaginationProps = {
|
|
4
|
+
/** Number of rows per page */
|
|
5
|
+
readonly pageSize: number;
|
|
6
|
+
/** Whether the pagination is in a loading state */
|
|
7
|
+
readonly isLoading?: boolean;
|
|
8
|
+
/** Text customization for pagination */
|
|
9
|
+
readonly labels?: {
|
|
10
|
+
/** Text shown before the page size number (default: "Showing") */
|
|
11
|
+
showing?: string;
|
|
12
|
+
/** Text shown before the total number (default: "of") */
|
|
13
|
+
of?: string;
|
|
14
|
+
/** Text shown after the total number (default: "results") */
|
|
15
|
+
results?: string;
|
|
16
|
+
/** Aria label for previous page button (default: "Previous page") */
|
|
17
|
+
previousPage?: string;
|
|
18
|
+
/** Aria label for next page button (default: "Next page") */
|
|
19
|
+
nextPage?: string;
|
|
20
|
+
/** Aria label for page number (default: "Page {number}") */
|
|
21
|
+
pageLabel?: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
type BackendPaginationProps = BasePaginationProps & {
|
|
25
|
+
/** Current page */
|
|
26
|
+
readonly currentPage: number;
|
|
27
|
+
/** Total number of items */
|
|
28
|
+
readonly total: number;
|
|
29
|
+
/** Callback when page changes */
|
|
30
|
+
readonly onPageChange: (page: number) => void;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Type helper to check if a type has an 'id' property
|
|
34
|
+
*/
|
|
35
|
+
type HasId<T> = T extends {
|
|
36
|
+
id: string | number;
|
|
37
|
+
} ? true : false;
|
|
38
|
+
/**
|
|
39
|
+
* Props for the DataTable component
|
|
40
|
+
* @template TData The type of data being displayed in the table
|
|
41
|
+
*/
|
|
42
|
+
export type DataTableProps<TData> = {
|
|
43
|
+
/** Array of column definitions that describe the table structure */
|
|
44
|
+
readonly columns: Array<ColumnDef<TData>>;
|
|
45
|
+
/** Array of data items to be displayed in the table */
|
|
46
|
+
readonly data: Array<TData>;
|
|
47
|
+
/** Whether to show the column visibility toggle menu */
|
|
48
|
+
readonly showColumnVisibilityControls?: boolean;
|
|
49
|
+
/** Custom text for the column visibility button */
|
|
50
|
+
readonly columnVisibilityButtonLabel?: string;
|
|
51
|
+
/** Whether the table is in a loading state */
|
|
52
|
+
readonly isLoading?: boolean;
|
|
53
|
+
/** Pagination configuration. If not provided, pagination is disabled */
|
|
54
|
+
readonly pagination?: BasePaginationProps | BackendPaginationProps;
|
|
55
|
+
/** Optional component to render filters */
|
|
56
|
+
readonly Filters?: React.ReactNode;
|
|
57
|
+
/** Callback when all rows are selected */
|
|
58
|
+
readonly onSelectAll?: (selected: boolean) => void;
|
|
59
|
+
/** Callback when a row is selected */
|
|
60
|
+
readonly onSelect?: (selected: boolean, row: TData) => void;
|
|
61
|
+
/** Optional className for the table container */
|
|
62
|
+
readonly className?: string;
|
|
63
|
+
} & (HasId<TData> extends true ? {
|
|
64
|
+
/** Function to get unique identifier from a row. Not needed when data has 'id' property */
|
|
65
|
+
readonly getRowId?: never;
|
|
66
|
+
} : {
|
|
67
|
+
/** Function to get unique identifier from a row. Required when data doesn't have 'id' property */
|
|
68
|
+
readonly getRowId: RowIdentifierFn<TData>;
|
|
69
|
+
});
|
|
70
|
+
/**
|
|
71
|
+
* Function to get a unique identifier from a row
|
|
72
|
+
*/
|
|
73
|
+
type RowIdentifierFn<T> = (row: T) => string;
|
|
74
|
+
/**
|
|
75
|
+
* A feature-rich data table component built on top of TanStack Table.
|
|
76
|
+
* Provides sorting, filtering, pagination, and column visibility controls.
|
|
77
|
+
*
|
|
78
|
+
* @template TData The type of data being displayed in the table
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```tsx
|
|
82
|
+
* type User = {
|
|
83
|
+
* id: string;
|
|
84
|
+
* name: string;
|
|
85
|
+
* email: string;
|
|
86
|
+
* };
|
|
87
|
+
*
|
|
88
|
+
* const columns: ColumnDef<User>[] = [
|
|
89
|
+
* {
|
|
90
|
+
* accessorKey: 'name',
|
|
91
|
+
* header: 'Name',
|
|
92
|
+
* },
|
|
93
|
+
* {
|
|
94
|
+
* accessorKey: 'email',
|
|
95
|
+
* header: 'Email',
|
|
96
|
+
* },
|
|
97
|
+
* ];
|
|
98
|
+
*
|
|
99
|
+
* const data: User[] = [
|
|
100
|
+
* { id: '1', name: 'John', email: 'john@example.com' },
|
|
101
|
+
* { id: '2', name: 'Jane', email: 'jane@example.com' },
|
|
102
|
+
* ];
|
|
103
|
+
*
|
|
104
|
+
* <DataTable columns={columns} data={data} />
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export declare function DataTable<TData extends object = any>({ columns: userColumns, data, getRowId, showColumnVisibilityControls, columnVisibilityButtonLabel, isLoading, pagination, onSelectAll, onSelect, Filters, className, }: DataTableProps<TData>): import("react/jsx-runtime").JSX.Element;
|
|
108
|
+
export {};
|