@rovula/ui 0.0.16 → 0.0.17
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 +45 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- 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/index.d.ts +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/esm/bundle.css +45 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- 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/index.d.ts +1 -0
- package/dist/index.d.ts +23 -1
- package/dist/index.js +1 -0
- package/dist/src/theme/global.css +56 -0
- package/package.json +1 -1
- 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/index.ts +1 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
declare const CollapsibleButton: React.ForwardRefExoticComponent<{
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
className?: string | undefined;
|
|
5
|
+
hideExpandIcon?: boolean | undefined;
|
|
6
|
+
} & React.RefAttributes<HTMLButtonElement>>;
|
|
7
|
+
declare const CollapsiblePanel: React.ForwardRefExoticComponent<{
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
className?: string | undefined;
|
|
10
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
11
|
+
interface CollapsibleComponent extends React.ForwardRefExoticComponent<CollapsibleProps & React.RefAttributes<HTMLDivElement>> {
|
|
12
|
+
Button: typeof CollapsibleButton;
|
|
13
|
+
Panel: typeof CollapsiblePanel;
|
|
14
|
+
}
|
|
15
|
+
interface CollapsibleProps {
|
|
16
|
+
size?: "sm" | "md" | "lg";
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
isExpand?: boolean;
|
|
19
|
+
className?: string;
|
|
20
|
+
onToggle?: (isExpand: boolean) => void;
|
|
21
|
+
}
|
|
22
|
+
declare const Collapsible: CollapsibleComponent;
|
|
23
|
+
export default Collapsible;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const collapseButtonVariants: (props?: ({
|
|
2
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
3
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
4
|
+
export declare const collapseIconVariants: (props?: ({
|
|
5
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
6
|
+
isExpand?: boolean | null | undefined;
|
|
7
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
8
|
+
export declare const collapsePanelVariants: (props?: ({
|
|
9
|
+
size?: "sm" | "md" | "lg" | null | undefined;
|
|
10
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
11
|
+
export declare const collapseContainerVariants: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
interface CollapsibleContextProps {
|
|
3
|
+
size?: "sm" | "md" | "lg";
|
|
4
|
+
isExpand: boolean;
|
|
5
|
+
toggle: () => void;
|
|
6
|
+
setIsExpand: React.Dispatch<React.SetStateAction<boolean>>;
|
|
7
|
+
}
|
|
8
|
+
export declare const useCollapsible: () => CollapsibleContextProps;
|
|
9
|
+
interface CollapsibleProviderProps {
|
|
10
|
+
size?: "sm" | "md" | "lg";
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
isExpandControlled?: boolean;
|
|
13
|
+
onToggle?: (isExpand: boolean) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare const CollapsibleProvider: React.FC<CollapsibleProviderProps>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Collapsible } from "./Collapsible";
|
|
@@ -10,6 +10,7 @@ export { Input } from "./components/Input/Input";
|
|
|
10
10
|
export { Navbar } from "./components/Navbar";
|
|
11
11
|
export { default as ActionButton } from "./components/ActionButton/ActionButton";
|
|
12
12
|
export { Avatar, AvatarGroup } from "./components/Avatar";
|
|
13
|
+
export { Collapsible } from "./components/Collapsible";
|
|
13
14
|
export * from "./components/Table/Table";
|
|
14
15
|
export * from "./components/DataTable/DataTable";
|
|
15
16
|
export * from "./components/Dialog/Dialog";
|
package/dist/index.d.ts
CHANGED
|
@@ -225,6 +225,28 @@ type AvatarGroupProps = {
|
|
|
225
225
|
};
|
|
226
226
|
declare const AvatarGroup: FC<AvatarGroupProps>;
|
|
227
227
|
|
|
228
|
+
declare const CollapsibleButton: React__default.ForwardRefExoticComponent<{
|
|
229
|
+
children: React__default.ReactNode;
|
|
230
|
+
className?: string | undefined;
|
|
231
|
+
hideExpandIcon?: boolean | undefined;
|
|
232
|
+
} & React__default.RefAttributes<HTMLButtonElement>>;
|
|
233
|
+
declare const CollapsiblePanel: React__default.ForwardRefExoticComponent<{
|
|
234
|
+
children: React__default.ReactNode;
|
|
235
|
+
className?: string | undefined;
|
|
236
|
+
} & React__default.RefAttributes<HTMLDivElement>>;
|
|
237
|
+
interface CollapsibleComponent extends React__default.ForwardRefExoticComponent<CollapsibleProps & React__default.RefAttributes<HTMLDivElement>> {
|
|
238
|
+
Button: typeof CollapsibleButton;
|
|
239
|
+
Panel: typeof CollapsiblePanel;
|
|
240
|
+
}
|
|
241
|
+
interface CollapsibleProps {
|
|
242
|
+
size?: "sm" | "md" | "lg";
|
|
243
|
+
children: React__default.ReactNode;
|
|
244
|
+
isExpand?: boolean;
|
|
245
|
+
className?: string;
|
|
246
|
+
onToggle?: (isExpand: boolean) => void;
|
|
247
|
+
}
|
|
248
|
+
declare const Collapsible: CollapsibleComponent;
|
|
249
|
+
|
|
228
250
|
declare const Table: React.ForwardRefExoticComponent<{
|
|
229
251
|
rootRef?: React.LegacyRef<HTMLDivElement> | undefined;
|
|
230
252
|
} & React.HTMLAttributes<HTMLTableElement> & React.RefAttributes<HTMLTableElement>>;
|
|
@@ -291,4 +313,4 @@ declare const getTimestampUTC: (date: Date) => number;
|
|
|
291
313
|
|
|
292
314
|
declare function cn(...inputs: ClassValue[]): string;
|
|
293
315
|
|
|
294
|
-
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, Checkbox, DataTable, type DataTableProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, type DropdownProps, Input, type InputProps, Label, Navbar, type NavbarProps, type Options, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextInput, cn, getEndDateOfDay, getStartDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, resloveTimestamp };
|
|
316
|
+
export { ActionButton, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, Button, type ButtonProps, Checkbox, Collapsible, DataTable, type DataTableProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Dropdown, type DropdownProps, Input, type InputProps, Label, Navbar, type NavbarProps, type Options, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, Text, TextInput, cn, getEndDateOfDay, getStartDateOfDay, getStartEndTimestampOfDay, getTimestampUTC, resloveTimestamp };
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ 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";
|
|
15
16
|
export * from "./components/Table/Table";
|
|
16
17
|
export * from "./components/DataTable/DataTable";
|
|
17
18
|
export * from "./components/Dialog/Dialog";
|
|
@@ -1062,11 +1062,21 @@ body {
|
|
|
1062
1062
|
height: 1.5rem;
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
|
+
.size-7 {
|
|
1066
|
+
width: 1.75rem;
|
|
1067
|
+
height: 1.75rem;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1065
1070
|
.size-\[14px\] {
|
|
1066
1071
|
width: 14px;
|
|
1067
1072
|
height: 14px;
|
|
1068
1073
|
}
|
|
1069
1074
|
|
|
1075
|
+
.size-full {
|
|
1076
|
+
width: 100%;
|
|
1077
|
+
height: 100%;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1070
1080
|
.h-10 {
|
|
1071
1081
|
height: 2.5rem;
|
|
1072
1082
|
}
|
|
@@ -1303,6 +1313,10 @@ body {
|
|
|
1303
1313
|
flex-wrap: wrap;
|
|
1304
1314
|
}
|
|
1305
1315
|
|
|
1316
|
+
.content-center {
|
|
1317
|
+
align-content: center;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1306
1320
|
.items-center {
|
|
1307
1321
|
align-items: center;
|
|
1308
1322
|
}
|
|
@@ -1590,6 +1604,11 @@ body {
|
|
|
1590
1604
|
background-color: rgb(var(--error-100) / var(--tw-bg-opacity));
|
|
1591
1605
|
}
|
|
1592
1606
|
|
|
1607
|
+
.bg-gray-100 {
|
|
1608
|
+
--tw-bg-opacity: 1;
|
|
1609
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1593
1612
|
.bg-gray-200 {
|
|
1594
1613
|
--tw-bg-opacity: 1;
|
|
1595
1614
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
@@ -1779,6 +1798,11 @@ body {
|
|
|
1779
1798
|
padding-right: 1rem;
|
|
1780
1799
|
}
|
|
1781
1800
|
|
|
1801
|
+
.px-5 {
|
|
1802
|
+
padding-left: 1.25rem;
|
|
1803
|
+
padding-right: 1.25rem;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1782
1806
|
.px-6 {
|
|
1783
1807
|
padding-left: 1.5rem;
|
|
1784
1808
|
padding-right: 1.5rem;
|
|
@@ -2249,6 +2273,14 @@ body {
|
|
|
2249
2273
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
2250
2274
|
}
|
|
2251
2275
|
|
|
2276
|
+
.transition {
|
|
2277
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
|
|
2278
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
|
|
2279
|
+
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
|
|
2280
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
2281
|
+
transition-duration: 150ms;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2252
2284
|
.transition-all {
|
|
2253
2285
|
transition-property: all;
|
|
2254
2286
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -2267,6 +2299,10 @@ body {
|
|
|
2267
2299
|
transition-duration: 150ms;
|
|
2268
2300
|
}
|
|
2269
2301
|
|
|
2302
|
+
.delay-150 {
|
|
2303
|
+
transition-delay: 150ms;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2270
2306
|
.duration-200 {
|
|
2271
2307
|
transition-duration: 200ms;
|
|
2272
2308
|
}
|
|
@@ -2452,6 +2488,11 @@ body {
|
|
|
2452
2488
|
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
2453
2489
|
}
|
|
2454
2490
|
|
|
2491
|
+
.hover\:bg-gray-200:hover {
|
|
2492
|
+
--tw-bg-opacity: 1;
|
|
2493
|
+
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2455
2496
|
.hover\:bg-info-100:hover {
|
|
2456
2497
|
--tw-bg-opacity: 1;
|
|
2457
2498
|
background-color: rgb(var(--info-100)) / var(--tw-bg-opacity));
|
|
@@ -2604,16 +2645,31 @@ body {
|
|
|
2604
2645
|
outline-offset: 2px;
|
|
2605
2646
|
}
|
|
2606
2647
|
|
|
2648
|
+
.focus-visible\:ring:focus-visible {
|
|
2649
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2650
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2651
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2607
2654
|
.focus-visible\:ring-2:focus-visible {
|
|
2608
2655
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
2609
2656
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
2610
2657
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
2611
2658
|
}
|
|
2612
2659
|
|
|
2660
|
+
.focus-visible\:ring-gray-500:focus-visible {
|
|
2661
|
+
--tw-ring-opacity: 1;
|
|
2662
|
+
--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity));
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2613
2665
|
.focus-visible\:ring-ring:focus-visible {
|
|
2614
2666
|
--tw-ring-color: hsl(var(--ring));
|
|
2615
2667
|
}
|
|
2616
2668
|
|
|
2669
|
+
.focus-visible\:ring-opacity-75:focus-visible {
|
|
2670
|
+
--tw-ring-opacity: 0.75;
|
|
2671
|
+
}
|
|
2672
|
+
|
|
2617
2673
|
.focus-visible\:ring-offset-2:focus-visible {
|
|
2618
2674
|
--tw-ring-offset-width: 2px;
|
|
2619
2675
|
}
|
package/package.json
CHANGED
|
@@ -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";
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ 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";
|
|
15
16
|
export * from "./components/Table/Table";
|
|
16
17
|
export * from "./components/DataTable/DataTable";
|
|
17
18
|
export * from "./components/Dialog/Dialog";
|