@orbitkit/components 0.0.1 → 0.2.0-beta.1

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 (132) hide show
  1. package/dist/astro/accordion/Accordion.astro +34 -0
  2. package/dist/astro/accordion/AccordionItem.astro +16 -0
  3. package/dist/astro/accordion/AccordionTrigger.astro +33 -0
  4. package/dist/astro/accordion/AcordionContent.astro +26 -0
  5. package/dist/astro/accordion/accordion.ts +125 -0
  6. package/dist/astro/accordion/index.ts +6 -0
  7. package/dist/astro/alert/Alert.astro +30 -30
  8. package/dist/astro/alert/AlertDescription.astro +10 -10
  9. package/dist/astro/alert/AlertTitle.astro +15 -15
  10. package/dist/astro/alert/alertVariants.ts +51 -51
  11. package/dist/astro/alert/index.ts +6 -6
  12. package/dist/astro/avatar/Avatar.astro +16 -16
  13. package/dist/astro/avatar/AvatarFallback.astro +18 -18
  14. package/dist/astro/avatar/AvatarImage.astro +14 -14
  15. package/dist/astro/avatar/avatarVariants.ts +23 -23
  16. package/dist/astro/avatar/index.ts +6 -6
  17. package/dist/astro/badge/Badge.astro +22 -22
  18. package/dist/astro/badge/badgeVariants.ts +37 -37
  19. package/dist/astro/badge/index.ts +4 -4
  20. package/dist/astro/breadcrumb/Breadcrumb.astro +12 -12
  21. package/dist/astro/breadcrumb/BreadcrumbEllipsis.astro +20 -20
  22. package/dist/astro/breadcrumb/BreadcrumbItem.astro +15 -15
  23. package/dist/astro/breadcrumb/BreadcrumbLink.astro +18 -18
  24. package/dist/astro/breadcrumb/BreadcrumbList.astro +18 -18
  25. package/dist/astro/breadcrumb/BreadcrumbPage.astro +18 -18
  26. package/dist/astro/breadcrumb/BreadcrumbSeparator.astro +17 -17
  27. package/dist/astro/breadcrumb/index.ts +17 -17
  28. package/dist/astro/button/Button.astro +29 -29
  29. package/dist/astro/button/buttonVariants.ts +61 -61
  30. package/dist/astro/button/index.ts +4 -4
  31. package/dist/astro/card/Card.astro +18 -18
  32. package/dist/astro/card/CardContent.astro +12 -12
  33. package/dist/astro/card/CardDescription.astro +12 -12
  34. package/dist/astro/card/CardFooter.astro +15 -15
  35. package/dist/astro/card/CardHeader.astro +12 -12
  36. package/dist/astro/card/CardTitle.astro +18 -18
  37. package/dist/astro/card/index.ts +15 -15
  38. package/dist/astro/checkbox/Checkbox.astro +38 -38
  39. package/dist/astro/checkbox/index.ts +3 -3
  40. package/dist/astro/collapsible/Collapsible.astro +34 -0
  41. package/dist/astro/collapsible/CollapsibleContent.astro +20 -0
  42. package/dist/astro/collapsible/collapsible.ts +81 -0
  43. package/dist/astro/collapsible/index.ts +4 -0
  44. package/dist/astro/divider/Divider.astro +22 -0
  45. package/dist/astro/divider/index.ts +3 -0
  46. package/dist/astro/drawer/Drawer.astro +19 -0
  47. package/dist/astro/drawer/DrawerContent.astro +74 -0
  48. package/dist/astro/drawer/DrawerDescription.astro +12 -0
  49. package/dist/astro/drawer/DrawerFooter.astro +15 -0
  50. package/dist/astro/drawer/DrawerHeader.astro +12 -0
  51. package/dist/astro/drawer/DrawerTitle.astro +18 -0
  52. package/dist/astro/drawer/drawer.ts +104 -0
  53. package/dist/astro/drawer/drawerVariants.ts +83 -0
  54. package/dist/astro/drawer/index.ts +15 -0
  55. package/dist/astro/dropdown/DropdownMenu.astro +19 -0
  56. package/dist/astro/dropdown/DropdownMenuContent.astro +42 -0
  57. package/dist/astro/dropdown/DropdownMenuGroup.astro +3 -0
  58. package/dist/astro/dropdown/DropdownMenuItem.astro +27 -0
  59. package/dist/astro/dropdown/DropdownMenuLabel.astro +3 -0
  60. package/dist/astro/dropdown/DropdownMenuSeparator.astro +6 -0
  61. package/dist/astro/dropdown/dropdown.ts +157 -0
  62. package/dist/astro/dropdown/dropdownVariants.ts +134 -0
  63. package/dist/astro/dropdown/index.ts +15 -0
  64. package/dist/astro/input/Input.astro +18 -18
  65. package/dist/astro/input/index.ts +4 -4
  66. package/dist/astro/input/inputVariants.ts +30 -30
  67. package/dist/astro/kbd/Kbd.astro +18 -0
  68. package/dist/astro/kbd/index.ts +3 -0
  69. package/dist/astro/label/Label.astro +14 -14
  70. package/dist/astro/label/index.ts +3 -3
  71. package/dist/astro/list/List.astro +25 -0
  72. package/dist/astro/list/ListItem.astro +39 -0
  73. package/dist/astro/list/ListVariants.ts +65 -0
  74. package/dist/astro/list/index.ts +5 -0
  75. package/dist/astro/modal/Modal.astro +19 -0
  76. package/dist/astro/modal/ModalContent.astro +71 -0
  77. package/dist/astro/modal/ModalDescription.astro +12 -0
  78. package/dist/astro/modal/ModalFooter.astro +15 -0
  79. package/dist/astro/modal/ModalHeader.astro +12 -0
  80. package/dist/astro/modal/ModalTitle.astro +18 -0
  81. package/dist/astro/modal/index.ts +15 -0
  82. package/dist/astro/modal/modal.ts +101 -0
  83. package/dist/astro/pagination/Pagination.astro +12 -0
  84. package/dist/astro/pagination/PaginationContent.astro +15 -0
  85. package/dist/astro/pagination/PaginationEllipsis.astro +33 -0
  86. package/dist/astro/pagination/PaginationItem.astro +12 -0
  87. package/dist/astro/pagination/PaginationLink.astro +21 -0
  88. package/dist/astro/pagination/PaginationNext.astro +29 -0
  89. package/dist/astro/pagination/PaginationPrevious.astro +34 -0
  90. package/dist/astro/pagination/index.ts +13 -0
  91. package/dist/astro/pagination/paginationVariants.ts +26 -0
  92. package/dist/astro/popover/Popover.astro +17 -0
  93. package/dist/astro/popover/PopoverContent.astro +39 -0
  94. package/dist/astro/popover/index.ts +4 -0
  95. package/dist/astro/popover/popover.ts +113 -0
  96. package/dist/astro/popover/popoverVariants.ts +115 -0
  97. package/dist/astro/progress/Progress.astro +23 -23
  98. package/dist/astro/progress/index.ts +4 -4
  99. package/dist/astro/progress/progressContainer.astro +17 -17
  100. package/dist/astro/radio/Radio.astro +26 -26
  101. package/dist/astro/radio/index.ts +3 -3
  102. package/dist/astro/select/Option.astro +11 -11
  103. package/dist/astro/select/Select.astro +39 -39
  104. package/dist/astro/select/index.ts +5 -5
  105. package/dist/astro/select/selectVariants.ts +30 -30
  106. package/dist/astro/skeleton/Skeleton.astro +12 -0
  107. package/dist/astro/skeleton/SkeletonItem.astro +18 -0
  108. package/dist/astro/skeleton/index.ts +4 -0
  109. package/dist/astro/stat/Stat.astro +12 -0
  110. package/dist/astro/stat/StatDescription.astro +12 -0
  111. package/dist/astro/stat/StatTitle.astro +18 -0
  112. package/dist/astro/stat/StatValue.astro +12 -0
  113. package/dist/astro/stat/index.ts +6 -0
  114. package/dist/astro/switch/Switch.astro +19 -19
  115. package/dist/astro/switch/index.ts +3 -3
  116. package/dist/astro/tab/Tab.astro +33 -0
  117. package/dist/astro/tab/TabContent.astro +19 -0
  118. package/dist/astro/tab/TabList.astro +19 -0
  119. package/dist/astro/tab/TabTrigger.astro +24 -0
  120. package/dist/astro/tab/index.ts +6 -0
  121. package/dist/astro/tab/tab.ts +142 -0
  122. package/dist/astro/textarea/Textarea.astro +19 -19
  123. package/dist/astro/textarea/TextareaVariants.ts +30 -30
  124. package/dist/astro/textarea/index.ts +4 -4
  125. package/dist/astro/tooltip/Tooltip.astro +40 -0
  126. package/dist/astro/tooltip/TooltipContent.astro +39 -0
  127. package/dist/astro/tooltip/index.ts +6 -0
  128. package/dist/astro/tooltip/tooltip.ts +137 -0
  129. package/dist/astro/tooltip/tooltipVariants.ts +115 -0
  130. package/dist/index.js +57 -1
  131. package/dist/index.js.map +1 -1
  132. package/package.json +9 -2
@@ -1,12 +1,12 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
-
5
- interface Props extends HTMLAttributes<"p"> {}
6
-
7
- const { class: className, ...attrs } = Astro.props;
8
- ---
9
-
10
- <p {...attrs} class={cn("font-normal text-muted-foreground", className)}>
11
- <slot />
12
- </p>
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"p"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <p {...attrs} class={cn("font-normal text-muted-foreground", className)}>
11
+ <slot />
12
+ </p>
@@ -1,15 +1,15 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
-
5
- interface Props extends HTMLAttributes<"div"> {}
6
-
7
- const { class: className, ...attrs } = Astro.props;
8
- ---
9
-
10
- <div
11
- {...attrs}
12
- class={cn("p-6 pt-0 flex items-center justify-between gap-2", className)}
13
- >
14
- <slot />
15
- </div>
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div
11
+ {...attrs}
12
+ class={cn("p-6 pt-0 flex items-center justify-between gap-2", className)}
13
+ >
14
+ <slot />
15
+ </div>
@@ -1,12 +1,12 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
-
5
- interface Props extends HTMLAttributes<"div"> {}
6
-
7
- const { class: className, ...attrs } = Astro.props;
8
- ---
9
-
10
- <div {...attrs} class={cn("p-6 pb-0 flex flex-col gap-1", className)}>
11
- <slot />
12
- </div>
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div {...attrs} class={cn("p-6 pb-0 flex flex-col gap-1", className)}>
11
+ <slot />
12
+ </div>
@@ -1,18 +1,18 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
-
5
- interface Props extends HTMLAttributes<"h5"> {}
6
-
7
- const { class: className, ...attrs } = Astro.props;
8
- ---
9
-
10
- <h5
11
- {...attrs}
12
- class={cn(
13
- "flex items-center justify-start gap-2 text-2xl font-semibold tracking-tight",
14
- className,
15
- )}
16
- >
17
- <slot />
18
- </h5>
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"h5"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <h5
11
+ {...attrs}
12
+ class={cn(
13
+ "flex items-center justify-start gap-2 text-2xl font-semibold tracking-tight",
14
+ className,
15
+ )}
16
+ >
17
+ <slot />
18
+ </h5>
@@ -1,15 +1,15 @@
1
- import Card from "./Card.astro";
2
- import CardContent from "./CardContent.astro";
3
- import CardDescription from "./CardDescription.astro";
4
- import CardFooter from "./CardFooter.astro";
5
- import CardHeader from "./CardHeader.astro";
6
- import CardTitle from "./CardTitle.astro";
7
-
8
- export {
9
- Card,
10
- CardContent,
11
- CardDescription,
12
- CardFooter,
13
- CardHeader,
14
- CardTitle,
15
- };
1
+ import Card from "./Card.astro";
2
+ import CardContent from "./CardContent.astro";
3
+ import CardDescription from "./CardDescription.astro";
4
+ import CardFooter from "./CardFooter.astro";
5
+ import CardHeader from "./CardHeader.astro";
6
+ import CardTitle from "./CardTitle.astro";
7
+
8
+ export {
9
+ Card,
10
+ CardContent,
11
+ CardDescription,
12
+ CardFooter,
13
+ CardHeader,
14
+ CardTitle,
15
+ };
@@ -1,38 +1,38 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
-
5
- interface Props extends Omit<HTMLAttributes<"input">, "type"> {}
6
-
7
- const { class: className, id, ...attrs } = Astro.props;
8
- ---
9
-
10
- <div class="inline-flex items-center">
11
- <label class="relative flex cursor-pointer items-center" for={id}>
12
- <input
13
- {...attrs}
14
- id={id}
15
- type="checkbox"
16
- class={"peer h-5 w-5 cursor-pointer transition-all appearance-none rounded border border-border checked:bg-primary disabled:opacity-50 disabled:cursor-not-allowed"}
17
- />
18
- <span
19
- class={cn(
20
- "text-primary-foreground pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform opacity-0 peer-checked:opacity-100",
21
- className,
22
- )}
23
- >
24
- <slot>
25
- <svg
26
- xmlns="http://www.w3.org/2000/svg"
27
- class="h-3.5 w-3.5"
28
- viewBox="0 0 24 24"
29
- fill="none"
30
- stroke="currentColor"
31
- stroke-width="4"
32
- >
33
- <path d="M20 6 9 17l-5-5"></path>
34
- </svg>
35
- </slot>
36
- </span>
37
- </label>
38
- </div>
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends Omit<HTMLAttributes<"input">, "type"> {}
6
+
7
+ const { class: className, id, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div class="inline-flex items-center">
11
+ <label class="relative flex cursor-pointer items-center" for={id}>
12
+ <input
13
+ {...attrs}
14
+ id={id}
15
+ type="checkbox"
16
+ class={"peer h-5 w-5 cursor-pointer transition-all appearance-none rounded border border-border checked:bg-primary disabled:opacity-50 disabled:cursor-not-allowed"}
17
+ />
18
+ <span
19
+ class={cn(
20
+ "text-primary-foreground pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 transform opacity-0 peer-checked:opacity-100",
21
+ className,
22
+ )}
23
+ >
24
+ <slot>
25
+ <svg
26
+ xmlns="http://www.w3.org/2000/svg"
27
+ class="h-3.5 w-3.5"
28
+ viewBox="0 0 24 24"
29
+ fill="none"
30
+ stroke="currentColor"
31
+ stroke-width="4"
32
+ >
33
+ <path d="M20 6 9 17l-5-5"></path>
34
+ </svg>
35
+ </slot>
36
+ </span>
37
+ </label>
38
+ </div>
@@ -1,3 +1,3 @@
1
- import Checkbox from "./Checkbox.astro";
2
-
3
- export { Checkbox };
1
+ import Checkbox from "./Checkbox.astro";
2
+
3
+ export { Checkbox };
@@ -0,0 +1,34 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {
6
+ isOpen?: boolean;
7
+ }
8
+
9
+ const { class: className, isOpen = false, ...attrs } = Astro.props;
10
+ ---
11
+
12
+ <div
13
+ {...attrs}
14
+ data-collapsible
15
+ data-open={isOpen}
16
+ class={cn("w-full", className)}
17
+ >
18
+ <slot />
19
+ </div>
20
+
21
+ <script>
22
+ import { Collapsible } from "./collapsible";
23
+
24
+ function init() {
25
+ const collapsibles =
26
+ document.querySelectorAll<HTMLElement>("[data-collapsible]");
27
+ collapsibles.forEach((collapsible) => {
28
+ new Collapsible(collapsible);
29
+ });
30
+ }
31
+
32
+ init();
33
+ document.addEventListener("astro:page-load", () => init());
34
+ </script>
@@ -0,0 +1,20 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div
11
+ data-collapsible-content
12
+ class={cn(
13
+ "overflow-hidden transition-all duration-300 ease-in-out",
14
+ className,
15
+ )}
16
+ hidden
17
+ {...attrs}
18
+ >
19
+ <slot />
20
+ </div>
@@ -0,0 +1,81 @@
1
+ export class Collapsible {
2
+ private wrapper: HTMLElement;
3
+ private content: HTMLElement | null;
4
+ private trigger: HTMLElement | null;
5
+
6
+ constructor(collapsibleWrapper: HTMLElement) {
7
+ this.wrapper = collapsibleWrapper;
8
+ this.content = this.wrapper.querySelector("[data-collapsible-content]");
9
+ this.trigger = this.wrapper.querySelector("[data-trigger]");
10
+
11
+ this.init();
12
+ }
13
+
14
+ private init() {
15
+ this.setupAccessibility();
16
+ this.setupEventListeners();
17
+ }
18
+
19
+ private setupAccessibility() {
20
+ if (!this.trigger || !this.content) return;
21
+
22
+ const id =
23
+ this.content.id ||
24
+ `collapsible-id-${Math.random().toString(36).substring(2, 9)}`;
25
+
26
+ this.content.id = id;
27
+ this.trigger.setAttribute("aria-controls", id);
28
+
29
+ if (this.wrapper.dataset.open === "true") {
30
+ this.setState("open");
31
+ this.content?.removeAttribute("hidden");
32
+ const height = this.content?.scrollHeight + "px";
33
+ this.content!.style.maxHeight = height;
34
+ } else {
35
+ this.setState("closed");
36
+ this.content?.setAttribute("hidden", "");
37
+ this.content!.style.maxHeight = "0px";
38
+ }
39
+ }
40
+
41
+ private setupEventListeners() {
42
+ this.trigger?.addEventListener("click", () => this.toggleCollapsible());
43
+ this.trigger?.addEventListener("keydown", (e) => this.handleKeyDown(e));
44
+ }
45
+
46
+ private toggleCollapsible() {
47
+ if (this.trigger?.dataset.state === "open") {
48
+ this.closeCollapsible();
49
+ } else {
50
+ this.openCollapsible();
51
+ }
52
+ }
53
+
54
+ private openCollapsible() {
55
+ this.content?.removeAttribute("hidden");
56
+ this.setState("open");
57
+ const height = this.content?.scrollHeight + "px";
58
+ this.content!.style.maxHeight = height;
59
+ }
60
+
61
+ private closeCollapsible() {
62
+ this.setState("closed");
63
+ this.content!.style.maxHeight = "0px";
64
+ window.setTimeout(() => {
65
+ this.content?.setAttribute("hidden", "");
66
+ }, 300);
67
+ }
68
+
69
+ private setState(state: "closed" | "open") {
70
+ this.trigger?.setAttribute("data-state", state);
71
+ this.trigger?.setAttribute("aria-expanded", `${state === "open"}`);
72
+ this.content?.setAttribute("data-state", state);
73
+ }
74
+
75
+ private handleKeyDown = (event: KeyboardEvent) => {
76
+ if (event.key === "Escape" && this.content!.dataset.status === "open") {
77
+ this.closeCollapsible();
78
+ event.preventDefault();
79
+ }
80
+ };
81
+ }
@@ -0,0 +1,4 @@
1
+ import Collapsible from "./Collapsible.astro";
2
+ import CollapsibleContent from "./CollapsibleContent.astro";
3
+
4
+ export { Collapsible, CollapsibleContent };
@@ -0,0 +1,22 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {
6
+ orientation?: "horizontal" | "vertical";
7
+ }
8
+
9
+ const { class: className, orientation = "horizontal", ...attrs } = Astro.props;
10
+ ---
11
+
12
+ <div
13
+ {...attrs}
14
+ aria-orientation={orientation}
15
+ role="separator"
16
+ class={cn(
17
+ "shrink-0 bg-border",
18
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
19
+ className,
20
+ )}
21
+ >
22
+ </div>
@@ -0,0 +1,3 @@
1
+ import Divider from "./Divider.astro";
2
+
3
+ export { Divider };
@@ -0,0 +1,19 @@
1
+ <div data-drawer-wrapper>
2
+ <slot />
3
+ </div>
4
+
5
+ <script>
6
+ import { Drawer } from "./drawer";
7
+
8
+ function init() {
9
+ const drawers = document.querySelectorAll<HTMLElement>(
10
+ "[data-drawer-wrapper]",
11
+ );
12
+ drawers.forEach((modal) => {
13
+ new Drawer(modal);
14
+ });
15
+ }
16
+
17
+ init();
18
+ document.addEventListener("astro:page-load", () => init());
19
+ </script>
@@ -0,0 +1,74 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { HTMLAttributes } from "astro/types";
4
+ import type { VariantProps } from "class-variance-authority";
5
+ import { drawerVariants } from "./drawerVariants";
6
+
7
+ interface Props
8
+ extends HTMLAttributes<"div">,
9
+ VariantProps<typeof drawerVariants> {
10
+ showCloseButton?: boolean;
11
+ backdrop?: boolean;
12
+ allowOutsideClick?: boolean;
13
+ }
14
+
15
+ const {
16
+ class: className,
17
+ showCloseButton = true,
18
+ backdrop = true,
19
+ allowOutsideClick = true,
20
+ position = "right",
21
+ size = "sm",
22
+ ...attrs
23
+ } = Astro.props;
24
+ ---
25
+
26
+ {
27
+ backdrop && (
28
+ <div
29
+ aria-hidden="true"
30
+ data-state="closed"
31
+ data-drawer-backdrop
32
+ class="bg-background/10 backdrop-blur-xs fixed inset-0 left-0 top-0 z-50 hidden h-dvh w-full transition-opacity duration-200"
33
+ />
34
+ )
35
+ }
36
+
37
+ <div
38
+ data-drawer-content
39
+ aria-hidden="true"
40
+ data-state="closed"
41
+ data-position={position}
42
+ data-show-close-button={showCloseButton}
43
+ data-allow-outside-click={allowOutsideClick}
44
+ class={cn(drawerVariants({ position, size, className }))}
45
+ {...attrs}
46
+ >
47
+ {
48
+ showCloseButton && (
49
+ <button
50
+ class="text-foreground hover:bg-muted absolute right-3 top-3 cursor-pointer rounded-lg p-1 transition-colors duration-150"
51
+ aria-label="close modal"
52
+ data-close
53
+ >
54
+ <svg
55
+ xmlns="http://www.w3.org/2000/svg"
56
+ viewBox="0 0 24 24"
57
+ fill="none"
58
+ stroke="currentColor"
59
+ stroke-width="2"
60
+ stroke-linecap="round"
61
+ stroke-linejoin="round"
62
+ class="size-4"
63
+ >
64
+ <>
65
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
66
+ <path d="M18 6l-12 12" />
67
+ <path d="M6 6l12 12" />
68
+ </>
69
+ </svg>
70
+ </button>
71
+ )
72
+ }
73
+ <slot />
74
+ </div>
@@ -0,0 +1,12 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"p"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <p {...attrs} class={cn("font-normal text-muted-foreground", className)}>
11
+ <slot />
12
+ </p>
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div
11
+ class={cn("pt-4 flex items-center justify-end gap-2", className)}
12
+ {...attrs}
13
+ >
14
+ <slot />
15
+ </div>
@@ -0,0 +1,12 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <div class={cn("flex flex-col gap-1 pb-4", className)} {...attrs}>
11
+ <slot />
12
+ </div>
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"h5"> {}
6
+
7
+ const { class: className, ...attrs } = Astro.props;
8
+ ---
9
+
10
+ <h2
11
+ {...attrs}
12
+ class={cn(
13
+ "flex items-center justify-start gap-2 text-2xl font-semibold tracking-tight",
14
+ className,
15
+ )}
16
+ >
17
+ <slot />
18
+ </h2>
@@ -0,0 +1,104 @@
1
+ export class Drawer {
2
+ private wrapper: HTMLElement;
3
+ private drawer: HTMLElement | null;
4
+ private trigger: HTMLElement | null;
5
+ private backdrop: HTMLElement | null;
6
+ private closeButtons: NodeListOf<HTMLElement> | null;
7
+
8
+ constructor(drawerWrraper: HTMLElement) {
9
+ this.wrapper = drawerWrraper;
10
+ this.drawer = this.wrapper.querySelector("[data-drawer-content]");
11
+ this.backdrop = this.wrapper.querySelector("[data-drawer-backdrop]");
12
+ this.trigger = this.wrapper.querySelector("[data-trigger]");
13
+ this.closeButtons =
14
+ this.wrapper.querySelectorAll<HTMLElement>("[data-close]");
15
+
16
+ if (!this.drawer || !this.trigger) {
17
+ console.error("Drawer not initialized properly", {
18
+ drawer: this.drawer,
19
+ trigger: this.trigger,
20
+ });
21
+ return;
22
+ }
23
+
24
+ this.init();
25
+ }
26
+
27
+ private init() {
28
+ this.setupAccessibility();
29
+ this.setupEventListeners();
30
+ }
31
+
32
+ private setupAccessibility() {
33
+ const title = this.drawer?.querySelector<HTMLElement>(
34
+ "h1, h2, h3, h4, h5, h6",
35
+ );
36
+
37
+ if (title) {
38
+ const id =
39
+ title.id || `drawer-id-${Math.random().toString(36).substring(2, 9)}`;
40
+ title.id = id;
41
+ this.drawer?.setAttribute("aria-describedby", id);
42
+ }
43
+
44
+ this.setState("closed");
45
+ }
46
+
47
+ private setupEventListeners() {
48
+ this.trigger!.addEventListener("click", () => this.openDrawer());
49
+
50
+ if (this.drawer?.dataset.allowOutsideClick === "true") {
51
+ this.backdrop?.addEventListener("click", () => this.closeDrawer());
52
+ document.addEventListener("click", (e) => {
53
+ const target = e.target as HTMLElement;
54
+ if (
55
+ this.drawer &&
56
+ !this.drawer.contains(target) &&
57
+ target !== this.trigger
58
+ ) {
59
+ this.closeDrawer();
60
+ }
61
+ });
62
+ }
63
+
64
+ this.closeButtons?.forEach((trigger) => {
65
+ trigger.addEventListener("click", () => this.closeDrawer());
66
+ });
67
+
68
+ document.addEventListener("keydown", (e) => this.handleKeyDown(e));
69
+ }
70
+
71
+ private openDrawer() {
72
+ this.backdrop?.classList.remove("hidden");
73
+ this.drawer?.classList.replace("hidden", "flex");
74
+
75
+ document.body.classList.add("overflow-hidden");
76
+ setTimeout(() => {
77
+ this.setState("open");
78
+ }, 0);
79
+ }
80
+
81
+ private closeDrawer() {
82
+ this.setState("closed");
83
+ setTimeout(() => {
84
+ this.backdrop?.classList.add("hidden");
85
+ this.drawer?.classList.replace("flex", "hidden");
86
+ document.body.classList.remove("overflow-hidden");
87
+ }, 200);
88
+ }
89
+
90
+ private setState(state: "open" | "closed") {
91
+ this.trigger?.focus();
92
+ this.drawer?.setAttribute("aria-hidden", `${state === "closed"}`);
93
+ this.drawer?.setAttribute("data-state", state);
94
+ this.backdrop?.setAttribute("aria-hidden", `${state === "closed"}`);
95
+ this.backdrop?.setAttribute("data-state", state);
96
+ }
97
+
98
+ private handleKeyDown = (event: KeyboardEvent) => {
99
+ if (event.key === "Escape" && this.drawer!.dataset.status === "open") {
100
+ this.closeDrawer();
101
+ event.preventDefault();
102
+ }
103
+ };
104
+ }