@rovula/ui 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/bundle.css +497 -4
- package/dist/cjs/bundle.js +1 -1
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/AlertDialog/Alert.stories.d.ts +20 -0
- package/dist/cjs/types/components/AlertDialog/AlertDialog.d.ts +20 -0
- package/dist/cjs/types/components/Button/Button.styles.d.ts +1 -1
- package/dist/cjs/types/components/Checkbox/Checkbox.d.ts +4 -0
- package/dist/cjs/types/components/Checkbox/Checkbox.stories.d.ts +308 -0
- package/dist/cjs/types/components/Dialog/Dialog.d.ts +19 -0
- package/dist/cjs/types/components/Dialog/Dialog.stories.d.ts +25 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +26 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +367 -0
- package/dist/cjs/types/components/Dropdown/Dropdown.styles.d.ts +11 -0
- package/dist/cjs/types/components/Input/Input.d.ts +5 -0
- package/dist/cjs/types/components/Input/Input.stories.d.ts +314 -0
- package/dist/cjs/types/components/Label/Label.d.ts +5 -0
- package/dist/cjs/types/components/Label/Label.stories.d.ts +286 -0
- package/dist/cjs/types/components/RadioGroup/RadioGroup.d.ts +5 -0
- package/dist/cjs/types/components/RadioGroup/RadioGroup.stories.d.ts +299 -0
- package/dist/cjs/types/components/Table/Datagrid.d.ts +11 -0
- package/dist/cjs/types/components/Table/Table.d.ts +10 -11
- package/dist/cjs/types/components/Table/Table.stories.d.ts +283 -0
- package/dist/cjs/types/components/Tabs/Tabs.d.ts +7 -5
- package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +49 -0
- package/dist/cjs/types/components/TextInput/TextInput.d.ts +3 -2
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +2 -16
- package/dist/cjs/types/index.d.ts +8 -2
- package/dist/cjs/types/utils/cn.d.ts +2 -0
- package/dist/components/AlertDialog/Alert.stories.js +39 -0
- package/dist/components/AlertDialog/AlertDialog.js +73 -0
- package/dist/components/Button/Button.js +3 -3
- package/dist/components/Button/Button.styles.js +1 -1
- package/dist/components/Checkbox/Checkbox.js +37 -0
- package/dist/components/Checkbox/Checkbox.stories.js +49 -0
- package/dist/components/Dialog/Dialog.js +63 -0
- package/dist/components/Dialog/Dialog.stories.js +52 -0
- package/dist/components/Dropdown/Dropdown.js +58 -0
- package/dist/components/{Select/Select.stories.js → Dropdown/Dropdown.stories.js} +8 -11
- package/dist/components/Dropdown/Dropdown.styles.js +47 -0
- package/dist/components/Input/Input.js +31 -0
- package/dist/components/Input/Input.stories.js +37 -0
- package/dist/components/Label/Label.js +35 -0
- package/dist/components/Label/Label.stories.js +38 -0
- package/dist/components/RadioGroup/RadioGroup.js +41 -0
- package/dist/components/RadioGroup/RadioGroup.stories.js +44 -0
- package/dist/components/Table/Datagrid.js +6 -0
- package/dist/components/Table/Table.js +65 -5
- package/dist/components/Table/Table.stories.js +32 -0
- package/dist/components/Tabs/Tabs.js +10 -4
- package/dist/components/Tabs/Tabs.stories.js +60 -0
- package/dist/components/TextInput/TextInput.js +3 -3
- package/dist/esm/bundle.css +497 -4
- package/dist/esm/bundle.js +1 -1
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/AlertDialog/Alert.stories.d.ts +20 -0
- package/dist/esm/types/components/AlertDialog/AlertDialog.d.ts +20 -0
- package/dist/esm/types/components/Button/Button.styles.d.ts +1 -1
- package/dist/esm/types/components/Checkbox/Checkbox.d.ts +4 -0
- package/dist/esm/types/components/Checkbox/Checkbox.stories.d.ts +308 -0
- package/dist/esm/types/components/Dialog/Dialog.d.ts +19 -0
- package/dist/esm/types/components/Dialog/Dialog.stories.d.ts +25 -0
- package/dist/esm/types/components/Dropdown/Dropdown.d.ts +26 -0
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +367 -0
- package/dist/esm/types/components/Dropdown/Dropdown.styles.d.ts +11 -0
- package/dist/esm/types/components/Input/Input.d.ts +5 -0
- package/dist/esm/types/components/Input/Input.stories.d.ts +314 -0
- package/dist/esm/types/components/Label/Label.d.ts +5 -0
- package/dist/esm/types/components/Label/Label.stories.d.ts +286 -0
- package/dist/esm/types/components/RadioGroup/RadioGroup.d.ts +5 -0
- package/dist/esm/types/components/RadioGroup/RadioGroup.stories.d.ts +299 -0
- package/dist/esm/types/components/Table/Datagrid.d.ts +11 -0
- package/dist/esm/types/components/Table/Table.d.ts +10 -11
- package/dist/esm/types/components/Table/Table.stories.d.ts +283 -0
- package/dist/esm/types/components/Tabs/Tabs.d.ts +7 -5
- package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +49 -0
- package/dist/esm/types/components/TextInput/TextInput.d.ts +3 -2
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +2 -16
- package/dist/esm/types/index.d.ts +8 -2
- package/dist/esm/types/utils/cn.d.ts +2 -0
- package/dist/index.d.ts +88 -30
- package/dist/index.js +8 -2
- package/dist/src/theme/global.css +598 -4
- package/dist/theme/global.css +57 -0
- package/dist/theme/main-preset.js +29 -1
- package/dist/theme/presets/colors.js +19 -0
- package/dist/utils/cn.js +9 -0
- package/package.json +9 -1
- package/src/components/AlertDialog/Alert.stories.tsx +67 -0
- package/src/components/AlertDialog/AlertDialog.tsx +142 -0
- package/src/components/Button/Button.styles.ts +1 -1
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Checkbox/Checkbox.stories.tsx +91 -0
- package/src/components/Checkbox/Checkbox.tsx +36 -0
- package/src/components/Dialog/Dialog.stories.tsx +118 -0
- package/src/components/Dialog/Dialog.tsx +119 -0
- package/src/components/{Select/Select.stories.tsx → Dropdown/Dropdown.stories.tsx} +11 -14
- package/src/components/Dropdown/Dropdown.styles.ts +54 -0
- package/src/components/Dropdown/Dropdown.tsx +151 -0
- package/src/components/Input/Input.stories.tsx +40 -0
- package/src/components/Input/Input.tsx +25 -0
- package/src/components/Label/Label.stories.tsx +45 -0
- package/src/components/Label/Label.tsx +26 -0
- package/src/components/RadioGroup/RadioGroup.stories.tsx +71 -0
- package/src/components/RadioGroup/RadioGroup.tsx +59 -0
- package/src/components/Table/Datagrid.tsx +36 -0
- package/src/components/Table/Table.stories.tsx +79 -0
- package/src/components/Table/Table.tsx +116 -35
- package/src/components/Tabs/Tabs.stories.tsx +75 -0
- package/src/components/Tabs/Tabs.tsx +39 -10
- package/src/components/TextInput/TextInput.tsx +11 -2
- package/src/index.ts +9 -2
- package/src/theme/global.css +57 -0
- package/src/theme/main-preset.js +29 -1
- package/src/theme/presets/colors.js +19 -0
- package/src/utils/cn.ts +6 -0
- package/dist/cjs/types/components/Select/Select copy.d.ts +0 -23
- package/dist/cjs/types/components/Select/Select.d.ts +0 -23
- package/dist/cjs/types/components/Select/Select.stories.d.ts +0 -348
- package/dist/cjs/types/components/Select/Select.styles.d.ts +0 -14
- package/dist/components/Select/Select copy.js +0 -42
- package/dist/components/Select/Select.js +0 -21
- package/dist/components/Select/Select.styles.js +0 -100
- package/dist/esm/types/components/Select/Select copy.d.ts +0 -23
- package/dist/esm/types/components/Select/Select.d.ts +0 -23
- package/dist/esm/types/components/Select/Select.stories.d.ts +0 -348
- package/dist/esm/types/components/Select/Select.styles.d.ts +0 -14
- package/src/components/Select/Select copy.tsx +0 -103
- package/src/components/Select/Select.styles.ts +0 -111
- package/src/components/Select/Select.tsx +0 -54
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
5
|
+
|
|
6
|
+
import { XMarkIcon } from "@heroicons/react/16/solid";
|
|
7
|
+
import { cn } from "@/utils/cn";
|
|
8
|
+
|
|
9
|
+
const Dialog = DialogPrimitive.Root;
|
|
10
|
+
|
|
11
|
+
const DialogTrigger = DialogPrimitive.Trigger;
|
|
12
|
+
|
|
13
|
+
const DialogPortal = DialogPrimitive.Portal;
|
|
14
|
+
|
|
15
|
+
const DialogClose = DialogPrimitive.Close;
|
|
16
|
+
|
|
17
|
+
const DialogOverlay = React.forwardRef<
|
|
18
|
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
19
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
20
|
+
>(({ className, ...props }, ref) => (
|
|
21
|
+
<DialogPrimitive.Overlay
|
|
22
|
+
ref={ref}
|
|
23
|
+
className={cn(
|
|
24
|
+
"fixed inset-0 z-50 bg-popup-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
/>
|
|
29
|
+
));
|
|
30
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
31
|
+
|
|
32
|
+
const DialogContent = React.forwardRef<
|
|
33
|
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
34
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
35
|
+
>(({ className, children, ...props }, ref) => (
|
|
36
|
+
<DialogPortal>
|
|
37
|
+
<DialogOverlay />
|
|
38
|
+
<DialogPrimitive.Content
|
|
39
|
+
ref={ref}
|
|
40
|
+
className={cn(
|
|
41
|
+
"fixed text-textcolor-grey-dark left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-[var(--popup-rounded)]",
|
|
42
|
+
className
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
|
|
48
|
+
<XMarkIcon className="h-4 w-4" />
|
|
49
|
+
<span className="sr-only">Close</span>
|
|
50
|
+
</DialogPrimitive.Close>
|
|
51
|
+
</DialogPrimitive.Content>
|
|
52
|
+
</DialogPortal>
|
|
53
|
+
));
|
|
54
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
55
|
+
|
|
56
|
+
const DialogHeader = ({
|
|
57
|
+
className,
|
|
58
|
+
...props
|
|
59
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
60
|
+
<div
|
|
61
|
+
className={cn(
|
|
62
|
+
"flex flex-col space-y-2 text-center sm:text-left",
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
DialogHeader.displayName = "DialogHeader";
|
|
69
|
+
|
|
70
|
+
const DialogFooter = ({
|
|
71
|
+
className,
|
|
72
|
+
...props
|
|
73
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
74
|
+
<div
|
|
75
|
+
className={cn(
|
|
76
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
DialogFooter.displayName = "DialogFooter";
|
|
83
|
+
|
|
84
|
+
const DialogTitle = React.forwardRef<
|
|
85
|
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
86
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
87
|
+
>(({ className, ...props }, ref) => (
|
|
88
|
+
<DialogPrimitive.Title
|
|
89
|
+
ref={ref}
|
|
90
|
+
className={cn("typography-h5 tracking-tight", className)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
));
|
|
94
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
95
|
+
|
|
96
|
+
const DialogDescription = React.forwardRef<
|
|
97
|
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
98
|
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
99
|
+
>(({ className, ...props }, ref) => (
|
|
100
|
+
<DialogPrimitive.Description
|
|
101
|
+
ref={ref}
|
|
102
|
+
className={cn("text-sm", className)}
|
|
103
|
+
{...props}
|
|
104
|
+
/>
|
|
105
|
+
));
|
|
106
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
Dialog,
|
|
110
|
+
DialogPortal,
|
|
111
|
+
DialogOverlay,
|
|
112
|
+
DialogClose,
|
|
113
|
+
DialogTrigger,
|
|
114
|
+
DialogContent,
|
|
115
|
+
DialogHeader,
|
|
116
|
+
DialogFooter,
|
|
117
|
+
DialogTitle,
|
|
118
|
+
DialogDescription,
|
|
119
|
+
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
-
import
|
|
3
|
+
import Dropdown from "./Dropdown";
|
|
4
4
|
|
|
5
5
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
|
6
6
|
const meta = {
|
|
7
|
-
title: "Components/
|
|
8
|
-
component:
|
|
7
|
+
title: "Components/Dropdown",
|
|
8
|
+
component: Dropdown,
|
|
9
9
|
tags: ["autodocs"],
|
|
10
10
|
parameters: {
|
|
11
11
|
// More on how to position stories at: https://storybook.js.org/docs/7.0/react/configure/story-layout
|
|
@@ -18,21 +18,18 @@ const meta = {
|
|
|
18
18
|
</div>
|
|
19
19
|
),
|
|
20
20
|
],
|
|
21
|
-
} satisfies Meta<typeof
|
|
21
|
+
} satisfies Meta<typeof Dropdown>;
|
|
22
22
|
|
|
23
23
|
export default meta;
|
|
24
24
|
|
|
25
|
-
const options =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{ value: "option4", label: "Option 4" },
|
|
30
|
-
];
|
|
25
|
+
const options = new Array(100).fill("").map((__, index) => ({
|
|
26
|
+
value: `option${index + 1}`,
|
|
27
|
+
label: `Option ${index + 1}`,
|
|
28
|
+
}));
|
|
31
29
|
|
|
32
30
|
export const Default = {
|
|
33
31
|
args: {
|
|
34
32
|
label: "Choose an option:",
|
|
35
|
-
// value: "",
|
|
36
33
|
fullwidth: true,
|
|
37
34
|
options,
|
|
38
35
|
},
|
|
@@ -43,9 +40,9 @@ export const Default = {
|
|
|
43
40
|
};
|
|
44
41
|
return (
|
|
45
42
|
<div className="flex flex-row gap-4 w-full">
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
<
|
|
43
|
+
<Dropdown id="1" size="lg" options={options} {...args} />
|
|
44
|
+
<Dropdown id="2" size="md" options={options} {...args} />
|
|
45
|
+
<Dropdown id="3" size="sm" options={options} {...args} />
|
|
49
46
|
</div>
|
|
50
47
|
);
|
|
51
48
|
},
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
export const iconWrapperVariant = cva(
|
|
5
|
+
["absolute inset-y-0 right-0 flex items-center justify-center"],
|
|
6
|
+
{
|
|
7
|
+
variants: {
|
|
8
|
+
size: {
|
|
9
|
+
sm: "mr-2",
|
|
10
|
+
md: "mr-3",
|
|
11
|
+
lg: "mr-4",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
size: "md",
|
|
16
|
+
},
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const dropdownIconVariant = cva(["transition-all"], {
|
|
21
|
+
variants: {
|
|
22
|
+
size: {
|
|
23
|
+
sm: "size-[14px]",
|
|
24
|
+
md: "size-5",
|
|
25
|
+
lg: "size-6",
|
|
26
|
+
},
|
|
27
|
+
disabled: {
|
|
28
|
+
true: "fill-input-text-disabled",
|
|
29
|
+
false: "fill-input-text",
|
|
30
|
+
},
|
|
31
|
+
isFocus: {
|
|
32
|
+
true: "fill-input-text-active rotate-180",
|
|
33
|
+
false: "",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
defaultVariants: {
|
|
37
|
+
size: "md",
|
|
38
|
+
disabled: false,
|
|
39
|
+
isFocus: false,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const customInputVariant = cva([], {
|
|
44
|
+
variants: {
|
|
45
|
+
size: {
|
|
46
|
+
sm: "pe-[30px]",
|
|
47
|
+
md: "pe-[40px]",
|
|
48
|
+
lg: "pe-[48px]",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
defaultVariants: {
|
|
52
|
+
size: "md",
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import TextInput, { InputProps } from "../TextInput/TextInput";
|
|
4
|
+
import {
|
|
5
|
+
customInputVariant,
|
|
6
|
+
dropdownIconVariant,
|
|
7
|
+
iconWrapperVariant,
|
|
8
|
+
} from "./Dropdown.styles";
|
|
9
|
+
|
|
10
|
+
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
|
11
|
+
|
|
12
|
+
type Options = {
|
|
13
|
+
value: string;
|
|
14
|
+
label: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type DropdownProps = {
|
|
18
|
+
id?: string;
|
|
19
|
+
label?: string;
|
|
20
|
+
size?: "sm" | "md" | "lg";
|
|
21
|
+
rounded?: "none" | "normal" | "full";
|
|
22
|
+
variant?: "flat" | "outline" | "underline";
|
|
23
|
+
helperText?: string;
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
filterMode?: boolean;
|
|
26
|
+
fullwidth?: boolean;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
error?: boolean;
|
|
29
|
+
required?: boolean;
|
|
30
|
+
className?: string;
|
|
31
|
+
options: Options[];
|
|
32
|
+
value?: Options;
|
|
33
|
+
onChangeText?: InputProps["onChange"];
|
|
34
|
+
onSelect?: (value: Options) => void;
|
|
35
|
+
} & Omit<InputProps, "value">;
|
|
36
|
+
|
|
37
|
+
const Dropdown = ({
|
|
38
|
+
id,
|
|
39
|
+
options,
|
|
40
|
+
value,
|
|
41
|
+
label,
|
|
42
|
+
size = "md",
|
|
43
|
+
rounded = "normal",
|
|
44
|
+
variant = "outline",
|
|
45
|
+
helperText,
|
|
46
|
+
errorMessage,
|
|
47
|
+
fullwidth = true,
|
|
48
|
+
disabled = false,
|
|
49
|
+
error = false,
|
|
50
|
+
filterMode = false,
|
|
51
|
+
required = true,
|
|
52
|
+
onChangeText,
|
|
53
|
+
onSelect,
|
|
54
|
+
...props
|
|
55
|
+
}: DropdownProps) => {
|
|
56
|
+
const _id = id || `${label}-select`;
|
|
57
|
+
|
|
58
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
59
|
+
const [selectedOption, setSelectedOption] = useState<
|
|
60
|
+
Options | null | undefined
|
|
61
|
+
>(null);
|
|
62
|
+
const [textValue, setTextValue] = useState("");
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (value && !selectedOption) {
|
|
66
|
+
setSelectedOption(value);
|
|
67
|
+
}
|
|
68
|
+
}, [value, selectedOption]);
|
|
69
|
+
|
|
70
|
+
const handleOnChangeText = useCallback(
|
|
71
|
+
(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
72
|
+
onChangeText?.(event);
|
|
73
|
+
setTextValue(event.target.value);
|
|
74
|
+
},
|
|
75
|
+
[onChangeText]
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const handleOptionClick = useCallback(
|
|
79
|
+
(option: Options) => {
|
|
80
|
+
setSelectedOption(option);
|
|
81
|
+
setTextValue(option.label);
|
|
82
|
+
onSelect?.(option);
|
|
83
|
+
},
|
|
84
|
+
[onSelect]
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const optionsFiltered = useMemo(() => {
|
|
88
|
+
return options.filter(
|
|
89
|
+
(option) =>
|
|
90
|
+
!filterMode ||
|
|
91
|
+
option.label?.toLowerCase().includes(textValue?.toLowerCase())
|
|
92
|
+
);
|
|
93
|
+
}, [options, filterMode, textValue]);
|
|
94
|
+
|
|
95
|
+
const renderOptions = () => (
|
|
96
|
+
<ul className="absolute mt-1 w-full bg-white border border-gray-300 rounded-md shadow-md z-10 max-h-60 overflow-y-auto">
|
|
97
|
+
{optionsFiltered.map((option) => (
|
|
98
|
+
<li
|
|
99
|
+
key={option.value}
|
|
100
|
+
onMouseDown={() => handleOptionClick(option)}
|
|
101
|
+
className={`px-4 py-2 hover:bg-gray-100 cursor-pointer ${
|
|
102
|
+
selectedOption?.value === option.value ? " bg-gray-200" : ""
|
|
103
|
+
}`}
|
|
104
|
+
>
|
|
105
|
+
{option.label}
|
|
106
|
+
</li>
|
|
107
|
+
))}
|
|
108
|
+
{optionsFiltered.length === 0 && (
|
|
109
|
+
<li className="px-4 py-14 text-center text-input-text">Not found</li>
|
|
110
|
+
)}
|
|
111
|
+
</ul>
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div className={`relative ${fullwidth ? "w-full" : ""}`}>
|
|
116
|
+
<TextInput
|
|
117
|
+
{...props}
|
|
118
|
+
readOnly={!filterMode}
|
|
119
|
+
value={textValue}
|
|
120
|
+
onChange={handleOnChangeText}
|
|
121
|
+
label={label}
|
|
122
|
+
placeholder=" "
|
|
123
|
+
type="text"
|
|
124
|
+
rounded={rounded}
|
|
125
|
+
variant={variant}
|
|
126
|
+
helperText={helperText}
|
|
127
|
+
errorMessage={errorMessage}
|
|
128
|
+
fullwidth={fullwidth}
|
|
129
|
+
error={error}
|
|
130
|
+
required={required}
|
|
131
|
+
id={_id}
|
|
132
|
+
disabled={disabled}
|
|
133
|
+
hasClearIcon={false}
|
|
134
|
+
size={size}
|
|
135
|
+
className={customInputVariant({ size })}
|
|
136
|
+
onFocus={() => setIsFocused(true)}
|
|
137
|
+
onBlur={() => setIsFocused(false)}
|
|
138
|
+
endIcon={
|
|
139
|
+
<div className={iconWrapperVariant({ size })}>
|
|
140
|
+
<ChevronDownIcon
|
|
141
|
+
className={dropdownIconVariant({ size, isFocus: isFocused })}
|
|
142
|
+
/>
|
|
143
|
+
</div>
|
|
144
|
+
}
|
|
145
|
+
/>
|
|
146
|
+
{isFocused && renderOptions()}
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export default Dropdown;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { Input } from "./Input";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/Input",
|
|
7
|
+
component: Input,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "fullscreen",
|
|
11
|
+
},
|
|
12
|
+
decorators: [
|
|
13
|
+
(Story) => (
|
|
14
|
+
<div className="p-5 flex w-full">
|
|
15
|
+
<Story />
|
|
16
|
+
</div>
|
|
17
|
+
),
|
|
18
|
+
],
|
|
19
|
+
} satisfies Meta<typeof Input>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
export const Default = {
|
|
24
|
+
args: {
|
|
25
|
+
// label: "Lorem Ipsum",
|
|
26
|
+
// value: "Lorem Ipsum",
|
|
27
|
+
// fullwidth: true,
|
|
28
|
+
},
|
|
29
|
+
render: (args) => {
|
|
30
|
+
console.log("args ", args);
|
|
31
|
+
const props: typeof args = {
|
|
32
|
+
...args,
|
|
33
|
+
};
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex flex-row gap-4 w-full">
|
|
36
|
+
<Input type="email" placeholder="Email" />
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/utils/cn";
|
|
4
|
+
|
|
5
|
+
export interface InputProps
|
|
6
|
+
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
7
|
+
|
|
8
|
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
9
|
+
({ className, type, ...props }, ref) => {
|
|
10
|
+
return (
|
|
11
|
+
<input
|
|
12
|
+
type={type}
|
|
13
|
+
className={cn(
|
|
14
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
ref={ref}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
Input.displayName = "Input";
|
|
24
|
+
|
|
25
|
+
export { Input };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
|
|
4
|
+
import { Checkbox } from "../Checkbox/Checkbox";
|
|
5
|
+
import { Label } from "./Label";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Components/Label",
|
|
9
|
+
component: Label,
|
|
10
|
+
tags: ["autodocs"],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: "fullscreen",
|
|
13
|
+
},
|
|
14
|
+
decorators: [
|
|
15
|
+
(Story) => (
|
|
16
|
+
<div className="p-5 flex w-full">
|
|
17
|
+
<Story />
|
|
18
|
+
</div>
|
|
19
|
+
),
|
|
20
|
+
],
|
|
21
|
+
} satisfies Meta<typeof Label>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
export const Default = {
|
|
26
|
+
args: {
|
|
27
|
+
// label: "Lorem Ipsum",
|
|
28
|
+
// value: "Lorem Ipsum",
|
|
29
|
+
// fullwidth: true,
|
|
30
|
+
},
|
|
31
|
+
render: (args) => {
|
|
32
|
+
console.log("args ", args);
|
|
33
|
+
const props: typeof args = {
|
|
34
|
+
...args,
|
|
35
|
+
};
|
|
36
|
+
return (
|
|
37
|
+
<div className="flex flex-row gap-4 w-full">
|
|
38
|
+
<div className="flex items-center space-x-2">
|
|
39
|
+
<Checkbox id="terms" />
|
|
40
|
+
<Label htmlFor="terms">Accept terms and conditions</Label>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/utils/cn";
|
|
8
|
+
|
|
9
|
+
const labelVariants = cva(
|
|
10
|
+
"typography-label1 peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const Label = React.forwardRef<
|
|
14
|
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
15
|
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
|
16
|
+
VariantProps<typeof labelVariants>
|
|
17
|
+
>(({ className, ...props }, ref) => (
|
|
18
|
+
<LabelPrimitive.Root
|
|
19
|
+
ref={ref}
|
|
20
|
+
className={cn(labelVariants(), className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
));
|
|
24
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
25
|
+
|
|
26
|
+
export { Label };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import { RadioGroup, RadioGroupItem } from "./RadioGroup";
|
|
4
|
+
import { Label } from "../Label/Label";
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/RadioGroup",
|
|
7
|
+
component: RadioGroup,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "fullscreen",
|
|
11
|
+
},
|
|
12
|
+
decorators: [
|
|
13
|
+
(Story) => (
|
|
14
|
+
<div className="p-5 flex w-full">
|
|
15
|
+
<Story />
|
|
16
|
+
</div>
|
|
17
|
+
),
|
|
18
|
+
],
|
|
19
|
+
} satisfies Meta<typeof RadioGroup>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
export const Default = {
|
|
24
|
+
args: {
|
|
25
|
+
disabled: false,
|
|
26
|
+
},
|
|
27
|
+
render: (args) => {
|
|
28
|
+
const props: typeof args = {
|
|
29
|
+
...args,
|
|
30
|
+
};
|
|
31
|
+
return (
|
|
32
|
+
<div className="flex flex-row gap-4 w-full">
|
|
33
|
+
<RadioGroup defaultValue="option-one" {...props}>
|
|
34
|
+
<div className="flex items-center space-x-2">
|
|
35
|
+
<RadioGroupItem value="option-one" id="option-one" />
|
|
36
|
+
<Label htmlFor="option-one">Option One</Label>
|
|
37
|
+
</div>
|
|
38
|
+
<div className="flex items-center space-x-2">
|
|
39
|
+
<RadioGroupItem value="option-two" id="option-two" />
|
|
40
|
+
<Label htmlFor="option-two">Option Two</Label>
|
|
41
|
+
</div>
|
|
42
|
+
</RadioGroup>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
} satisfies StoryObj;
|
|
47
|
+
|
|
48
|
+
export const Diabled = {
|
|
49
|
+
args: {
|
|
50
|
+
disabled: true,
|
|
51
|
+
},
|
|
52
|
+
render: (args) => {
|
|
53
|
+
const props: typeof args = {
|
|
54
|
+
...args,
|
|
55
|
+
};
|
|
56
|
+
return (
|
|
57
|
+
<div className="flex items-center space-x-2">
|
|
58
|
+
<RadioGroup defaultValue="option-one" disabled>
|
|
59
|
+
<div className="flex items-center space-x-2">
|
|
60
|
+
<RadioGroupItem value="option-one" id="option-one" />
|
|
61
|
+
<Label htmlFor="option-one">Option One</Label>
|
|
62
|
+
</div>
|
|
63
|
+
<div className="flex items-center space-x-2">
|
|
64
|
+
<RadioGroupItem value="option-two" id="option-two" />
|
|
65
|
+
<Label htmlFor="option-two">Option Two</Label>
|
|
66
|
+
</div>
|
|
67
|
+
</RadioGroup>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/utils/cn";
|
|
7
|
+
|
|
8
|
+
const RadioGroup = React.forwardRef<
|
|
9
|
+
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
|
11
|
+
>(({ className, ...props }, ref) => {
|
|
12
|
+
return (
|
|
13
|
+
<RadioGroupPrimitive.Root
|
|
14
|
+
className={cn("grid gap-2", className)}
|
|
15
|
+
{...props}
|
|
16
|
+
ref={ref}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
21
|
+
|
|
22
|
+
const RadioGroupItem = React.forwardRef<
|
|
23
|
+
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
|
24
|
+
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
|
|
25
|
+
>(({ className, ...props }, ref) => {
|
|
26
|
+
return (
|
|
27
|
+
<RadioGroupPrimitive.Item
|
|
28
|
+
ref={ref}
|
|
29
|
+
className={cn(
|
|
30
|
+
"aspect-square h-4 w-4 rounded-full border text-primary disabled:fill-secondary-110 ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:border-secondary-110",
|
|
31
|
+
{
|
|
32
|
+
"border-primary-30 data-[state=checked]:border-primary":
|
|
33
|
+
!props.disabled,
|
|
34
|
+
"border-secondary-110 data-disabled:border-secondary-110 text-secondary-110 fill-secondary-110":
|
|
35
|
+
props.disabled,
|
|
36
|
+
},
|
|
37
|
+
className
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
|
42
|
+
{/* <div className="bg-primary size-2.5 rounded-full" /> */}
|
|
43
|
+
<svg
|
|
44
|
+
width="10"
|
|
45
|
+
height="10"
|
|
46
|
+
viewBox="0 0 10 10"
|
|
47
|
+
fill="none"
|
|
48
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
49
|
+
className="fill-current text-current"
|
|
50
|
+
>
|
|
51
|
+
<circle cx="5" cy="5" r="5" fill="current" />
|
|
52
|
+
</svg>
|
|
53
|
+
</RadioGroupPrimitive.Indicator>
|
|
54
|
+
</RadioGroupPrimitive.Item>
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
58
|
+
|
|
59
|
+
export { RadioGroup, RadioGroupItem };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
interface Column {
|
|
4
|
+
header: string;
|
|
5
|
+
accessor: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface TableProps {
|
|
9
|
+
columns: Column[];
|
|
10
|
+
data: Record<string, any>[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const Table: React.FC<TableProps> = ({ columns, data }) => {
|
|
14
|
+
return (
|
|
15
|
+
<table className="table">
|
|
16
|
+
<thead>
|
|
17
|
+
<tr>
|
|
18
|
+
{columns.map((column, index) => (
|
|
19
|
+
<th key={index}>{column.header}</th>
|
|
20
|
+
))}
|
|
21
|
+
</tr>
|
|
22
|
+
</thead>
|
|
23
|
+
<tbody>
|
|
24
|
+
{data.map((row, rowIndex) => (
|
|
25
|
+
<tr key={rowIndex}>
|
|
26
|
+
{columns.map((column, colIndex) => (
|
|
27
|
+
<td key={colIndex}>{row[column.accessor]}</td>
|
|
28
|
+
))}
|
|
29
|
+
</tr>
|
|
30
|
+
))}
|
|
31
|
+
</tbody>
|
|
32
|
+
</table>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default Table;
|