@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.
Files changed (33) hide show
  1. package/dist/cjs/bundle.css +45 -0
  2. package/dist/cjs/bundle.js +3 -3
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Collapsible/Collapsible.d.ts +23 -0
  5. package/dist/cjs/types/components/Collapsible/Collapsible.stories.d.ts +8 -0
  6. package/dist/cjs/types/components/Collapsible/Collapsible.styles.d.ts +11 -0
  7. package/dist/cjs/types/components/Collapsible/CollapsibleContext.d.ts +16 -0
  8. package/dist/cjs/types/components/Collapsible/index.d.ts +1 -0
  9. package/dist/cjs/types/index.d.ts +1 -0
  10. package/dist/components/Collapsible/Collapsible.js +37 -0
  11. package/dist/components/Collapsible/Collapsible.stories.js +44 -0
  12. package/dist/components/Collapsible/Collapsible.styles.js +47 -0
  13. package/dist/components/Collapsible/CollapsibleContext.js +25 -0
  14. package/dist/components/Collapsible/index.js +1 -0
  15. package/dist/esm/bundle.css +45 -0
  16. package/dist/esm/bundle.js +3 -3
  17. package/dist/esm/bundle.js.map +1 -1
  18. package/dist/esm/types/components/Collapsible/Collapsible.d.ts +23 -0
  19. package/dist/esm/types/components/Collapsible/Collapsible.stories.d.ts +8 -0
  20. package/dist/esm/types/components/Collapsible/Collapsible.styles.d.ts +11 -0
  21. package/dist/esm/types/components/Collapsible/CollapsibleContext.d.ts +16 -0
  22. package/dist/esm/types/components/Collapsible/index.d.ts +1 -0
  23. package/dist/esm/types/index.d.ts +1 -0
  24. package/dist/index.d.ts +23 -1
  25. package/dist/index.js +1 -0
  26. package/dist/src/theme/global.css +56 -0
  27. package/package.json +1 -1
  28. package/src/components/Collapsible/Collapsible.stories.tsx +65 -0
  29. package/src/components/Collapsible/Collapsible.styles.ts +62 -0
  30. package/src/components/Collapsible/Collapsible.tsx +113 -0
  31. package/src/components/Collapsible/CollapsibleContext.tsx +61 -0
  32. package/src/components/Collapsible/index.ts +1 -0
  33. 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,8 @@
1
+ declare const meta: any;
2
+ export default meta;
3
+ export declare const Default: {
4
+ args: {
5
+ size: string;
6
+ };
7
+ render: (args: {}) => import("react/jsx-runtime").JSX.Element;
8
+ };
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rovula/ui",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "main": "dist/cjs/bundle.js",
5
5
  "module": "dist/esm/bundle.js",
6
6
  "types": "dist/index.d.ts",
@@ -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";