@rovula/ui 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/bundle.css +197 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/AlertDialog/Alert.stories.d.ts +1 -1
- package/dist/cjs/types/components/Calendar/Calendar.d.ts +8 -0
- package/dist/cjs/types/components/Calendar/Calendar.stories.d.ts +272 -0
- package/dist/cjs/types/components/Calendar/index.d.ts +1 -0
- package/dist/cjs/types/components/Collapsible/Collapsible.d.ts +23 -0
- package/dist/cjs/types/components/Collapsible/Collapsible.stories.d.ts +8 -0
- package/dist/cjs/types/components/Collapsible/Collapsible.styles.d.ts +11 -0
- package/dist/cjs/types/components/Collapsible/CollapsibleContext.d.ts +16 -0
- package/dist/cjs/types/components/Collapsible/index.d.ts +1 -0
- package/dist/cjs/types/components/DatePicker/DatePicker.d.ts +8 -0
- package/dist/cjs/types/components/DatePicker/DatePicker.stories.d.ts +21 -0
- package/dist/cjs/types/components/Popover/Popover.d.ts +6 -0
- package/dist/cjs/types/components/Popover/Popover.stories.d.ts +21 -0
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +7 -0
- package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +5 -0
- package/dist/cjs/types/index.d.ts +4 -0
- package/dist/components/Calendar/Calendar.js +43 -0
- package/dist/components/Calendar/Calendar.stories.js +36 -0
- package/dist/components/Calendar/index.js +1 -0
- package/dist/components/Collapsible/Collapsible.js +37 -0
- package/dist/components/Collapsible/Collapsible.stories.js +44 -0
- package/dist/components/Collapsible/Collapsible.styles.js +47 -0
- package/dist/components/Collapsible/CollapsibleContext.js +25 -0
- package/dist/components/Collapsible/index.js +1 -0
- package/dist/components/DatePicker/DatePicker.js +22 -0
- package/dist/components/DatePicker/DatePicker.stories.js +36 -0
- package/dist/components/Popover/Popover.js +35 -0
- package/dist/components/Popover/Popover.stories.js +33 -0
- package/dist/components/TextInput/TextInput.js +9 -3
- package/dist/components/TextInput/TextInput.stories.js +12 -0
- package/dist/components/TextInput/TextInput.styles.js +41 -0
- package/dist/esm/bundle.css +197 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/AlertDialog/Alert.stories.d.ts +1 -1
- package/dist/esm/types/components/Calendar/Calendar.d.ts +8 -0
- package/dist/esm/types/components/Calendar/Calendar.stories.d.ts +272 -0
- package/dist/esm/types/components/Calendar/index.d.ts +1 -0
- package/dist/esm/types/components/Collapsible/Collapsible.d.ts +23 -0
- package/dist/esm/types/components/Collapsible/Collapsible.stories.d.ts +8 -0
- package/dist/esm/types/components/Collapsible/Collapsible.styles.d.ts +11 -0
- package/dist/esm/types/components/Collapsible/CollapsibleContext.d.ts +16 -0
- package/dist/esm/types/components/Collapsible/index.d.ts +1 -0
- package/dist/esm/types/components/DatePicker/DatePicker.d.ts +8 -0
- package/dist/esm/types/components/DatePicker/DatePicker.stories.d.ts +21 -0
- package/dist/esm/types/components/Popover/Popover.d.ts +6 -0
- package/dist/esm/types/components/Popover/Popover.stories.d.ts +21 -0
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +7 -0
- package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +5 -0
- package/dist/esm/types/index.d.ts +4 -0
- package/dist/index.d.ts +41 -1
- package/dist/index.js +4 -0
- package/dist/src/theme/global.css +248 -0
- package/package.json +5 -2
- package/src/components/Calendar/Calendar.stories.tsx +45 -0
- package/src/components/Calendar/Calendar.tsx +66 -0
- package/src/components/Calendar/index.ts +1 -0
- package/src/components/Collapsible/Collapsible.stories.tsx +65 -0
- package/src/components/Collapsible/Collapsible.styles.ts +62 -0
- package/src/components/Collapsible/Collapsible.tsx +113 -0
- package/src/components/Collapsible/CollapsibleContext.tsx +61 -0
- package/src/components/Collapsible/index.ts +1 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +40 -0
- package/src/components/DatePicker/DatePicker.tsx +57 -0
- package/src/components/Popover/Popover.stories.tsx +40 -0
- package/src/components/Popover/Popover.tsx +31 -0
- package/src/components/TextInput/TextInput.stories.tsx +36 -0
- package/src/components/TextInput/TextInput.styles.ts +45 -0
- package/src/components/TextInput/TextInput.tsx +13 -3
- package/src/index.ts +8 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import Collapsible from "./Collapsible";
|
|
4
|
+
|
|
5
|
+
const meta: any = {
|
|
6
|
+
title: "Components/Collapsible",
|
|
7
|
+
component: Collapsible,
|
|
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 Collapsible>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
const Test = () => {
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
console.log("Mont");
|
|
26
|
+
return () => {
|
|
27
|
+
console.log("UnMont");
|
|
28
|
+
};
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
return <p>This is the content of section 1.</p>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Default = {
|
|
35
|
+
args: {
|
|
36
|
+
size: "md",
|
|
37
|
+
},
|
|
38
|
+
render: (args) => {
|
|
39
|
+
const props: typeof args = {
|
|
40
|
+
...args,
|
|
41
|
+
};
|
|
42
|
+
return (
|
|
43
|
+
<div className="flex flex-col gap-1 w-full ">
|
|
44
|
+
<Collapsible isExpand {...props}>
|
|
45
|
+
<Collapsible.Button>Section 1</Collapsible.Button>
|
|
46
|
+
<Collapsible.Panel>
|
|
47
|
+
This is the content of section 1.
|
|
48
|
+
</Collapsible.Panel>
|
|
49
|
+
</Collapsible>
|
|
50
|
+
<Collapsible>
|
|
51
|
+
<Collapsible.Button>Section 2</Collapsible.Button>
|
|
52
|
+
<Collapsible.Panel>
|
|
53
|
+
<p>This is the content of section 2.</p>
|
|
54
|
+
</Collapsible.Panel>
|
|
55
|
+
</Collapsible>
|
|
56
|
+
<Collapsible>
|
|
57
|
+
<Collapsible.Button>Section 3</Collapsible.Button>
|
|
58
|
+
<Collapsible.Panel>
|
|
59
|
+
<p>This is the content of section 3.</p>
|
|
60
|
+
</Collapsible.Panel>
|
|
61
|
+
</Collapsible>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
},
|
|
65
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
export const collapseButtonVariants = cva(
|
|
4
|
+
[
|
|
5
|
+
"flex flex-1 bg-gray-100 hover:bg-gray-200",
|
|
6
|
+
"focus:outline-none focus-visible:ring focus-visible:ring-gray-500 focus-visible:ring-opacity-75",
|
|
7
|
+
],
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
size: {
|
|
11
|
+
sm: "py-2 px-3",
|
|
12
|
+
md: "py-3 px-4",
|
|
13
|
+
lg: "py-4 px-5",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
size: "md",
|
|
19
|
+
},
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const collapseIconVariants = cva(
|
|
24
|
+
["transition-all flex content-center justify-center "],
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
size: {
|
|
28
|
+
sm: "size-5",
|
|
29
|
+
md: "size-6",
|
|
30
|
+
lg: "size-7",
|
|
31
|
+
},
|
|
32
|
+
isExpand: {
|
|
33
|
+
true: "rotate-180",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
defaultVariants: {
|
|
37
|
+
size: "md",
|
|
38
|
+
isExpand: false,
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const collapsePanelVariants = cva(
|
|
44
|
+
["flex flex-1 border-t", "transition ease-in-out delay-150 duration-300"],
|
|
45
|
+
{
|
|
46
|
+
variants: {
|
|
47
|
+
size: {
|
|
48
|
+
sm: "py-2 px-3",
|
|
49
|
+
md: "py-3 px-4",
|
|
50
|
+
lg: "py-4 px-5",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
defaultVariants: {
|
|
55
|
+
size: "md",
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
export const collapseContainerVariants = cva([
|
|
61
|
+
"flex flex-col border rounded overflow-hidden",
|
|
62
|
+
]);
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import React, { forwardRef, Ref, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { ChevronDownIcon } from "@heroicons/react/16/solid";
|
|
3
|
+
import { CollapsibleProvider, useCollapsible } from "./CollapsibleContext";
|
|
4
|
+
import { cn } from "@/utils/cn";
|
|
5
|
+
import {
|
|
6
|
+
collapseButtonVariants,
|
|
7
|
+
collapseContainerVariants,
|
|
8
|
+
collapseIconVariants,
|
|
9
|
+
collapsePanelVariants,
|
|
10
|
+
} from "./Collapsible.styles";
|
|
11
|
+
|
|
12
|
+
const CollapsibleButton = forwardRef<
|
|
13
|
+
HTMLButtonElement,
|
|
14
|
+
{
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
hideExpandIcon?: boolean;
|
|
18
|
+
}
|
|
19
|
+
>(({ children, className, hideExpandIcon = false }, ref) => {
|
|
20
|
+
const { toggle, isExpand, size } = useCollapsible();
|
|
21
|
+
|
|
22
|
+
const collapseButtonClassName = collapseButtonVariants({ size });
|
|
23
|
+
const collapseIconClassName = collapseIconVariants({ isExpand, size });
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<button
|
|
27
|
+
onClick={toggle}
|
|
28
|
+
className={cn(collapseButtonClassName, className)}
|
|
29
|
+
ref={ref}
|
|
30
|
+
>
|
|
31
|
+
<span className="flex flex-1">{children}</span>
|
|
32
|
+
{!hideExpandIcon && (
|
|
33
|
+
<span className={cn(collapseIconClassName)}>
|
|
34
|
+
<ChevronDownIcon className={cn("size-full")} />
|
|
35
|
+
</span>
|
|
36
|
+
)}
|
|
37
|
+
</button>
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
CollapsibleButton.displayName = "CollapsibleButton";
|
|
42
|
+
|
|
43
|
+
const CollapsiblePanel = forwardRef<
|
|
44
|
+
HTMLDivElement,
|
|
45
|
+
{ children: React.ReactNode; className?: string }
|
|
46
|
+
>(({ children, className }, ref) => {
|
|
47
|
+
const { isExpand, size } = useCollapsible();
|
|
48
|
+
const collapsePanelClassName = collapsePanelVariants({ size });
|
|
49
|
+
|
|
50
|
+
const [height, setHeight] = useState<string | number>("0px");
|
|
51
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
52
|
+
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (contentRef.current) {
|
|
55
|
+
setHeight(isExpand ? `${contentRef.current.scrollHeight}px` : "0px");
|
|
56
|
+
}
|
|
57
|
+
}, [isExpand, children]); // Add `children` to the dependency array to recalculate height on content change
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
ref={ref}
|
|
62
|
+
className={cn("overflow-hidden transition-all ease-in-out")}
|
|
63
|
+
style={{ height }}
|
|
64
|
+
>
|
|
65
|
+
<div ref={contentRef} className={cn(collapsePanelClassName, className)}>
|
|
66
|
+
{children}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
CollapsiblePanel.displayName = "CollapsiblePanel";
|
|
73
|
+
|
|
74
|
+
interface CollapsibleComponent
|
|
75
|
+
extends React.ForwardRefExoticComponent<
|
|
76
|
+
CollapsibleProps & React.RefAttributes<HTMLDivElement>
|
|
77
|
+
> {
|
|
78
|
+
Button: typeof CollapsibleButton;
|
|
79
|
+
Panel: typeof CollapsiblePanel;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface CollapsibleProps {
|
|
83
|
+
size?: "sm" | "md" | "lg";
|
|
84
|
+
children: React.ReactNode;
|
|
85
|
+
isExpand?: boolean;
|
|
86
|
+
className?: string;
|
|
87
|
+
onToggle?: (isExpand: boolean) => void;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(
|
|
91
|
+
({ children, isExpand, size, className, onToggle }, ref) => {
|
|
92
|
+
const collapseContainerClassName = collapseContainerVariants();
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<CollapsibleProvider
|
|
96
|
+
size={size}
|
|
97
|
+
isExpandControlled={isExpand}
|
|
98
|
+
onToggle={onToggle}
|
|
99
|
+
>
|
|
100
|
+
<div ref={ref} className={cn(collapseContainerClassName, className)}>
|
|
101
|
+
{children}
|
|
102
|
+
</div>
|
|
103
|
+
</CollapsibleProvider>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
) as CollapsibleComponent;
|
|
107
|
+
|
|
108
|
+
Collapsible.displayName = "Collapsible";
|
|
109
|
+
|
|
110
|
+
Collapsible.Button = CollapsibleButton;
|
|
111
|
+
Collapsible.Panel = CollapsiblePanel;
|
|
112
|
+
|
|
113
|
+
export default Collapsible;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useEffect,
|
|
7
|
+
} from "react";
|
|
8
|
+
|
|
9
|
+
interface CollapsibleContextProps {
|
|
10
|
+
size?: "sm" | "md" | "lg";
|
|
11
|
+
isExpand: boolean;
|
|
12
|
+
toggle: () => void;
|
|
13
|
+
setIsExpand: React.Dispatch<React.SetStateAction<boolean>>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const CollapsibleContext = createContext<CollapsibleContextProps | undefined>(
|
|
17
|
+
undefined
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const useCollapsible = (): CollapsibleContextProps => {
|
|
21
|
+
const context = useContext(CollapsibleContext);
|
|
22
|
+
if (!context) {
|
|
23
|
+
throw new Error("useCollapsible must be used within a CollapsibleProvider");
|
|
24
|
+
}
|
|
25
|
+
return context;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
interface CollapsibleProviderProps {
|
|
29
|
+
size?: "sm" | "md" | "lg";
|
|
30
|
+
children: ReactNode;
|
|
31
|
+
isExpandControlled?: boolean;
|
|
32
|
+
onToggle?: (isExpand: boolean) => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const CollapsibleProvider: React.FC<CollapsibleProviderProps> = ({
|
|
36
|
+
size,
|
|
37
|
+
children,
|
|
38
|
+
isExpandControlled,
|
|
39
|
+
onToggle,
|
|
40
|
+
}) => {
|
|
41
|
+
const [isExpand, setIsExpand] = useState<boolean>(false);
|
|
42
|
+
|
|
43
|
+
const toggle = () => {
|
|
44
|
+
setIsExpand((prev) => !prev);
|
|
45
|
+
if (onToggle) onToggle(!isExpand);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (isExpandControlled !== undefined) {
|
|
50
|
+
setIsExpand(isExpandControlled);
|
|
51
|
+
}
|
|
52
|
+
}, [isExpandControlled]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<CollapsibleContext.Provider
|
|
56
|
+
value={{ size, isExpand, toggle, setIsExpand }}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
</CollapsibleContext.Provider>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Collapsible } from "./Collapsible";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
import DatePicker from "./DatePicker";
|
|
4
|
+
|
|
5
|
+
// import { Popover, PopoverTrigger, PopoverContent } from "./Popover";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Components/DatePicker",
|
|
9
|
+
component: DatePicker,
|
|
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 DatePicker>;
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
|
|
25
|
+
export const Default = {
|
|
26
|
+
args: {},
|
|
27
|
+
render: (args) => {
|
|
28
|
+
console.log("args ", args);
|
|
29
|
+
const props: typeof args = {
|
|
30
|
+
...args,
|
|
31
|
+
};
|
|
32
|
+
const [date, setDate] = React.useState<Date | undefined>(undefined);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex flex-row gap-4 w-full">
|
|
36
|
+
<DatePicker date={date} onSelect={setDate} />
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, { FC, useState } from "react";
|
|
4
|
+
import { CalendarIcon } from "@heroicons/react/16/solid";
|
|
5
|
+
|
|
6
|
+
import { Calendar } from "../Calendar";
|
|
7
|
+
import Button from "../Button/Button";
|
|
8
|
+
import { cn } from "@/utils/cn";
|
|
9
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../Popover/Popover";
|
|
10
|
+
import { SelectSingleEventHandler } from "react-day-picker";
|
|
11
|
+
import { TextInput } from "../TextInput/TextInput";
|
|
12
|
+
import { format } from "date-fns/format";
|
|
13
|
+
|
|
14
|
+
type DatePickerProps = {
|
|
15
|
+
date: Date | undefined;
|
|
16
|
+
onSelect: SelectSingleEventHandler;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
CalendarIcon;
|
|
20
|
+
|
|
21
|
+
const DatePicker: FC<DatePickerProps> = ({ date, onSelect }) => {
|
|
22
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div>
|
|
26
|
+
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
|
27
|
+
<PopoverTrigger asChild>
|
|
28
|
+
<div className="flex">
|
|
29
|
+
<TextInput
|
|
30
|
+
fullwidth
|
|
31
|
+
id="2"
|
|
32
|
+
readOnly
|
|
33
|
+
label="Date"
|
|
34
|
+
size="md"
|
|
35
|
+
value={date ? format(date, "dd MMM yyyy") : isOpen ? " " : ""}
|
|
36
|
+
hasClearIcon={false}
|
|
37
|
+
endIcon={<CalendarIcon fill="inherit" />}
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
</PopoverTrigger>
|
|
41
|
+
<PopoverContent className="w-auto p-0">
|
|
42
|
+
<Calendar
|
|
43
|
+
mode="single"
|
|
44
|
+
selected={date}
|
|
45
|
+
onSelect={(...value) => {
|
|
46
|
+
onSelect?.(...value);
|
|
47
|
+
setIsOpen(false);
|
|
48
|
+
}}
|
|
49
|
+
initialFocus
|
|
50
|
+
/>
|
|
51
|
+
</PopoverContent>
|
|
52
|
+
</Popover>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default DatePicker;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
|
+
|
|
4
|
+
import { Popover, PopoverTrigger, PopoverContent } from "./Popover";
|
|
5
|
+
|
|
6
|
+
const meta = {
|
|
7
|
+
title: "Components/Popver",
|
|
8
|
+
component: Popover,
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: "fullscreen",
|
|
12
|
+
},
|
|
13
|
+
decorators: [
|
|
14
|
+
(Story) => (
|
|
15
|
+
<div className="p-5 flex w-full">
|
|
16
|
+
<Story />
|
|
17
|
+
</div>
|
|
18
|
+
),
|
|
19
|
+
],
|
|
20
|
+
} satisfies Meta<typeof Popover>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
export const Default = {
|
|
25
|
+
args: {},
|
|
26
|
+
render: (args) => {
|
|
27
|
+
console.log("args ", args);
|
|
28
|
+
const props: typeof args = {
|
|
29
|
+
...args,
|
|
30
|
+
};
|
|
31
|
+
return (
|
|
32
|
+
<div className="flex flex-row gap-4 w-full">
|
|
33
|
+
<Popover>
|
|
34
|
+
<PopoverTrigger>Open</PopoverTrigger>
|
|
35
|
+
<PopoverContent>Place content for the popover here.</PopoverContent>
|
|
36
|
+
</Popover>
|
|
37
|
+
</div>
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
} satisfies StoryObj;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/utils/cn";
|
|
7
|
+
|
|
8
|
+
const Popover = PopoverPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
const PopoverTrigger = PopoverPrimitive.Trigger;
|
|
11
|
+
|
|
12
|
+
const PopoverContent = React.forwardRef<
|
|
13
|
+
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
14
|
+
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
15
|
+
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
16
|
+
<PopoverPrimitive.Portal>
|
|
17
|
+
<PopoverPrimitive.Content
|
|
18
|
+
ref={ref}
|
|
19
|
+
align={align}
|
|
20
|
+
sideOffset={sideOffset}
|
|
21
|
+
className={cn(
|
|
22
|
+
"z-50 w-72 rounded-md border bg-popup-background p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
23
|
+
className
|
|
24
|
+
)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
</PopoverPrimitive.Portal>
|
|
28
|
+
));
|
|
29
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
30
|
+
|
|
31
|
+
export { Popover, PopoverTrigger, PopoverContent };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useRef } from "react";
|
|
2
2
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
3
3
|
import TextInput from "./TextInput";
|
|
4
|
+
import { CalendarIcon } from "@heroicons/react/16/solid";
|
|
4
5
|
|
|
5
6
|
// More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
|
|
6
7
|
const meta = {
|
|
@@ -87,3 +88,38 @@ export const CustomLabel = {
|
|
|
87
88
|
);
|
|
88
89
|
},
|
|
89
90
|
} satisfies StoryObj;
|
|
91
|
+
|
|
92
|
+
export const FuctionInput = {
|
|
93
|
+
args: {
|
|
94
|
+
label: "Placeholder Text",
|
|
95
|
+
disabled: false,
|
|
96
|
+
},
|
|
97
|
+
render: (args) => {
|
|
98
|
+
console.log("args ", args);
|
|
99
|
+
const props: typeof args = {
|
|
100
|
+
...args,
|
|
101
|
+
};
|
|
102
|
+
return (
|
|
103
|
+
<div className="flex flex-row gap-4 w-full">
|
|
104
|
+
<TextInput
|
|
105
|
+
id="1"
|
|
106
|
+
size="lg"
|
|
107
|
+
{...args}
|
|
108
|
+
endIcon={<CalendarIcon className="size-full" fill="inherit" />}
|
|
109
|
+
/>
|
|
110
|
+
<TextInput
|
|
111
|
+
id="2"
|
|
112
|
+
size="md"
|
|
113
|
+
{...args}
|
|
114
|
+
endIcon={<CalendarIcon className="size-full" fill="inherit" />}
|
|
115
|
+
/>
|
|
116
|
+
<TextInput
|
|
117
|
+
id="3"
|
|
118
|
+
size="sm"
|
|
119
|
+
{...args}
|
|
120
|
+
endIcon={<CalendarIcon className="size-full" fill="inherit" />}
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
},
|
|
125
|
+
} satisfies StoryObj;
|
|
@@ -37,6 +37,9 @@ export const inputVariant = cva(
|
|
|
37
37
|
hasClearIcon: {
|
|
38
38
|
true: "",
|
|
39
39
|
},
|
|
40
|
+
rightSectionIcon: {
|
|
41
|
+
false: "",
|
|
42
|
+
},
|
|
40
43
|
},
|
|
41
44
|
compoundVariants: [
|
|
42
45
|
{
|
|
@@ -58,6 +61,21 @@ export const inputVariant = cva(
|
|
|
58
61
|
size: "lg",
|
|
59
62
|
class: "focus:pe-10",
|
|
60
63
|
},
|
|
64
|
+
{
|
|
65
|
+
rightSectionIcon: true,
|
|
66
|
+
size: "sm",
|
|
67
|
+
class: "pe-[38px]",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
rightSectionIcon: true,
|
|
71
|
+
size: "md",
|
|
72
|
+
class: "pe-[46px]",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
rightSectionIcon: true,
|
|
76
|
+
size: "lg",
|
|
77
|
+
class: "pe-[72px]",
|
|
78
|
+
},
|
|
61
79
|
],
|
|
62
80
|
defaultVariants: {
|
|
63
81
|
size: "md",
|
|
@@ -67,6 +85,7 @@ export const inputVariant = cva(
|
|
|
67
85
|
disabled: false,
|
|
68
86
|
error: false,
|
|
69
87
|
hasClearIcon: false,
|
|
88
|
+
rightSectionIcon: false,
|
|
70
89
|
},
|
|
71
90
|
}
|
|
72
91
|
);
|
|
@@ -167,3 +186,29 @@ export const iconVariant = cva(
|
|
|
167
186
|
},
|
|
168
187
|
}
|
|
169
188
|
);
|
|
189
|
+
|
|
190
|
+
export const sectionIconWrapperVariant = cva(
|
|
191
|
+
[
|
|
192
|
+
"absolute inset-y-0 right-0 items-center justify-center flex",
|
|
193
|
+
"border-l border-l-input-stroke peer-hover:border-l-input-active peer-focus:border-l-input-stroke-active peer-disabled:border-l-input-stroke-disabled",
|
|
194
|
+
"fill-input-text peer-hover:fill-input-text-active peer-focus:fill-input-text-active",
|
|
195
|
+
],
|
|
196
|
+
{
|
|
197
|
+
variants: {
|
|
198
|
+
size: {
|
|
199
|
+
sm: "p-1 size-[30px]",
|
|
200
|
+
md: "p-2 size-[38px]",
|
|
201
|
+
lg: "p-3 size-14",
|
|
202
|
+
},
|
|
203
|
+
rounded: {
|
|
204
|
+
none: "rounded-r-none",
|
|
205
|
+
normal: "rounded-r-xl",
|
|
206
|
+
full: "rounded-r-full",
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
defaultVariants: {
|
|
210
|
+
size: "md",
|
|
211
|
+
rounded: "normal",
|
|
212
|
+
},
|
|
213
|
+
}
|
|
214
|
+
);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
iconWrapperVariant,
|
|
12
12
|
inputVariant,
|
|
13
13
|
labelVariant,
|
|
14
|
+
sectionIconWrapperVariant,
|
|
14
15
|
} from "./TextInput.styles";
|
|
15
16
|
import { XCircleIcon, ExclamationCircleIcon } from "@heroicons/react/16/solid";
|
|
16
17
|
import { cn } from "@/utils/cn";
|
|
@@ -58,6 +59,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
58
59
|
) => {
|
|
59
60
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
60
61
|
const _id = id || `${type}-${label}-input`;
|
|
62
|
+
const hasRightSectionIcon = !!endIcon;
|
|
61
63
|
const inputClassname = inputVariant({
|
|
62
64
|
size,
|
|
63
65
|
rounded,
|
|
@@ -65,7 +67,8 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
65
67
|
fullwidth,
|
|
66
68
|
disabled,
|
|
67
69
|
error,
|
|
68
|
-
hasClearIcon,
|
|
70
|
+
hasClearIcon: hasRightSectionIcon ? false : hasClearIcon,
|
|
71
|
+
rightSectionIcon: hasRightSectionIcon,
|
|
69
72
|
});
|
|
70
73
|
const labelClassname = labelVariant({
|
|
71
74
|
size,
|
|
@@ -75,6 +78,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
75
78
|
const helperTextClassname = helperTextVariant({ size, error, disabled });
|
|
76
79
|
const iconWrapperClassname = iconWrapperVariant({ size });
|
|
77
80
|
const iconClassname = iconVariant({ size });
|
|
81
|
+
const sectionIconWrapperClassname = sectionIconWrapperVariant({
|
|
82
|
+
size,
|
|
83
|
+
rounded,
|
|
84
|
+
});
|
|
78
85
|
|
|
79
86
|
useImperativeHandle(ref, () => inputRef?.current as HTMLInputElement);
|
|
80
87
|
|
|
@@ -96,7 +103,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
96
103
|
disabled={disabled}
|
|
97
104
|
className={cn(inputClassname, props.className)}
|
|
98
105
|
/>
|
|
99
|
-
{hasClearIcon && (
|
|
106
|
+
{hasClearIcon && !hasRightSectionIcon && (
|
|
100
107
|
<div className={iconWrapperClassname}>
|
|
101
108
|
<XCircleIcon
|
|
102
109
|
type="button"
|
|
@@ -105,7 +112,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
|
|
|
105
112
|
/>
|
|
106
113
|
</div>
|
|
107
114
|
)}
|
|
108
|
-
{
|
|
115
|
+
{hasRightSectionIcon && (
|
|
116
|
+
<div className={sectionIconWrapperClassname}>{endIcon}</div>
|
|
117
|
+
)}
|
|
118
|
+
|
|
109
119
|
<label htmlFor={_id} className={cn(labelClassname, labelClassName)}>
|
|
110
120
|
{label} {required && <span className="text-error">*</span>}
|
|
111
121
|
</label>
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,14 @@ export { Input } from "./components/Input/Input";
|
|
|
12
12
|
export { Navbar } from "./components/Navbar";
|
|
13
13
|
export { default as ActionButton } from "./components/ActionButton/ActionButton";
|
|
14
14
|
export { Avatar, AvatarGroup } from "./components/Avatar";
|
|
15
|
+
export { Collapsible } from "./components/Collapsible";
|
|
16
|
+
export { Calendar } from "./components/Calendar";
|
|
17
|
+
export { default as DatePicker } from "./components/DatePicker/DatePicker";
|
|
18
|
+
export {
|
|
19
|
+
Popover,
|
|
20
|
+
PopoverTrigger,
|
|
21
|
+
PopoverContent,
|
|
22
|
+
} from "./components/Popover/Popover";
|
|
15
23
|
export * from "./components/Table/Table";
|
|
16
24
|
export * from "./components/DataTable/DataTable";
|
|
17
25
|
export * from "./components/Dialog/Dialog";
|