@orbitkit/components 0.1.0 → 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 (133) hide show
  1. package/README.md +25 -25
  2. package/dist/astro/accordion/Accordion.astro +34 -0
  3. package/dist/astro/accordion/AccordionItem.astro +16 -0
  4. package/dist/astro/accordion/AccordionTrigger.astro +33 -0
  5. package/dist/astro/accordion/AcordionContent.astro +26 -0
  6. package/dist/astro/accordion/accordion.ts +125 -0
  7. package/dist/astro/accordion/index.ts +6 -0
  8. package/dist/astro/alert/Alert.astro +30 -30
  9. package/dist/astro/alert/AlertDescription.astro +10 -10
  10. package/dist/astro/alert/AlertTitle.astro +15 -15
  11. package/dist/astro/alert/alertVariants.ts +51 -51
  12. package/dist/astro/alert/index.ts +6 -6
  13. package/dist/astro/avatar/Avatar.astro +16 -16
  14. package/dist/astro/avatar/AvatarFallback.astro +18 -18
  15. package/dist/astro/avatar/AvatarImage.astro +14 -14
  16. package/dist/astro/avatar/avatarVariants.ts +23 -23
  17. package/dist/astro/avatar/index.ts +6 -6
  18. package/dist/astro/badge/Badge.astro +22 -22
  19. package/dist/astro/badge/badgeVariants.ts +37 -37
  20. package/dist/astro/badge/index.ts +4 -4
  21. package/dist/astro/breadcrumb/Breadcrumb.astro +12 -12
  22. package/dist/astro/breadcrumb/BreadcrumbEllipsis.astro +20 -20
  23. package/dist/astro/breadcrumb/BreadcrumbItem.astro +15 -15
  24. package/dist/astro/breadcrumb/BreadcrumbLink.astro +18 -18
  25. package/dist/astro/breadcrumb/BreadcrumbList.astro +18 -18
  26. package/dist/astro/breadcrumb/BreadcrumbPage.astro +18 -18
  27. package/dist/astro/breadcrumb/BreadcrumbSeparator.astro +17 -17
  28. package/dist/astro/breadcrumb/index.ts +17 -17
  29. package/dist/astro/button/Button.astro +29 -29
  30. package/dist/astro/button/buttonVariants.ts +61 -61
  31. package/dist/astro/button/index.ts +4 -4
  32. package/dist/astro/card/Card.astro +18 -18
  33. package/dist/astro/card/CardContent.astro +12 -12
  34. package/dist/astro/card/CardDescription.astro +12 -12
  35. package/dist/astro/card/CardFooter.astro +15 -15
  36. package/dist/astro/card/CardHeader.astro +12 -12
  37. package/dist/astro/card/CardTitle.astro +18 -18
  38. package/dist/astro/card/index.ts +15 -15
  39. package/dist/astro/checkbox/Checkbox.astro +38 -38
  40. package/dist/astro/checkbox/index.ts +3 -3
  41. package/dist/astro/collapsible/Collapsible.astro +34 -0
  42. package/dist/astro/collapsible/CollapsibleContent.astro +20 -0
  43. package/dist/astro/collapsible/collapsible.ts +81 -0
  44. package/dist/astro/collapsible/index.ts +4 -0
  45. package/dist/astro/divider/Divider.astro +22 -22
  46. package/dist/astro/divider/index.ts +3 -3
  47. package/dist/astro/drawer/Drawer.astro +19 -0
  48. package/dist/astro/drawer/DrawerContent.astro +74 -0
  49. package/dist/astro/drawer/DrawerDescription.astro +12 -0
  50. package/dist/astro/drawer/DrawerFooter.astro +15 -0
  51. package/dist/astro/drawer/DrawerHeader.astro +12 -0
  52. package/dist/astro/drawer/DrawerTitle.astro +18 -0
  53. package/dist/astro/drawer/drawer.ts +104 -0
  54. package/dist/astro/drawer/drawerVariants.ts +83 -0
  55. package/dist/astro/drawer/index.ts +15 -0
  56. package/dist/astro/dropdown/DropdownMenu.astro +19 -0
  57. package/dist/astro/dropdown/DropdownMenuContent.astro +42 -0
  58. package/dist/astro/dropdown/DropdownMenuGroup.astro +3 -0
  59. package/dist/astro/dropdown/DropdownMenuItem.astro +27 -0
  60. package/dist/astro/dropdown/DropdownMenuLabel.astro +3 -0
  61. package/dist/astro/dropdown/DropdownMenuSeparator.astro +6 -0
  62. package/dist/astro/dropdown/dropdown.ts +157 -0
  63. package/dist/astro/dropdown/dropdownVariants.ts +134 -0
  64. package/dist/astro/dropdown/index.ts +15 -0
  65. package/dist/astro/input/Input.astro +18 -18
  66. package/dist/astro/input/index.ts +4 -4
  67. package/dist/astro/input/inputVariants.ts +30 -30
  68. package/dist/astro/kbd/Kbd.astro +18 -0
  69. package/dist/astro/kbd/index.ts +3 -0
  70. package/dist/astro/label/Label.astro +14 -14
  71. package/dist/astro/label/index.ts +3 -3
  72. package/dist/astro/list/List.astro +25 -25
  73. package/dist/astro/list/ListItem.astro +39 -39
  74. package/dist/astro/list/ListVariants.ts +65 -65
  75. package/dist/astro/list/index.ts +5 -5
  76. package/dist/astro/modal/Modal.astro +19 -0
  77. package/dist/astro/modal/ModalContent.astro +71 -0
  78. package/dist/astro/modal/ModalDescription.astro +12 -0
  79. package/dist/astro/modal/ModalFooter.astro +15 -0
  80. package/dist/astro/modal/ModalHeader.astro +12 -0
  81. package/dist/astro/modal/ModalTitle.astro +18 -0
  82. package/dist/astro/modal/index.ts +15 -0
  83. package/dist/astro/modal/modal.ts +101 -0
  84. package/dist/astro/pagination/Pagination.astro +12 -0
  85. package/dist/astro/pagination/PaginationContent.astro +15 -0
  86. package/dist/astro/pagination/PaginationEllipsis.astro +33 -0
  87. package/dist/astro/pagination/PaginationItem.astro +12 -0
  88. package/dist/astro/pagination/PaginationLink.astro +21 -0
  89. package/dist/astro/pagination/PaginationNext.astro +29 -0
  90. package/dist/astro/pagination/PaginationPrevious.astro +34 -0
  91. package/dist/astro/pagination/index.ts +13 -0
  92. package/dist/astro/pagination/paginationVariants.ts +26 -0
  93. package/dist/astro/popover/Popover.astro +17 -0
  94. package/dist/astro/popover/PopoverContent.astro +39 -0
  95. package/dist/astro/popover/index.ts +4 -0
  96. package/dist/astro/popover/popover.ts +113 -0
  97. package/dist/astro/popover/popoverVariants.ts +115 -0
  98. package/dist/astro/progress/Progress.astro +23 -23
  99. package/dist/astro/progress/index.ts +4 -4
  100. package/dist/astro/progress/progressContainer.astro +17 -17
  101. package/dist/astro/radio/Radio.astro +26 -26
  102. package/dist/astro/radio/index.ts +3 -3
  103. package/dist/astro/select/Option.astro +11 -11
  104. package/dist/astro/select/Select.astro +39 -39
  105. package/dist/astro/select/index.ts +5 -5
  106. package/dist/astro/select/selectVariants.ts +30 -30
  107. package/dist/astro/skeleton/Skeleton.astro +12 -12
  108. package/dist/astro/skeleton/SkeletonItem.astro +18 -18
  109. package/dist/astro/skeleton/index.ts +4 -4
  110. package/dist/astro/stat/Stat.astro +12 -0
  111. package/dist/astro/stat/StatDescription.astro +12 -0
  112. package/dist/astro/stat/StatTitle.astro +18 -0
  113. package/dist/astro/stat/StatValue.astro +12 -0
  114. package/dist/astro/stat/index.ts +6 -0
  115. package/dist/astro/switch/Switch.astro +19 -19
  116. package/dist/astro/switch/index.ts +3 -3
  117. package/dist/astro/tab/Tab.astro +33 -0
  118. package/dist/astro/tab/TabContent.astro +19 -0
  119. package/dist/astro/tab/TabList.astro +19 -0
  120. package/dist/astro/tab/TabTrigger.astro +24 -0
  121. package/dist/astro/tab/index.ts +6 -0
  122. package/dist/astro/tab/tab.ts +142 -0
  123. package/dist/astro/textarea/Textarea.astro +19 -19
  124. package/dist/astro/textarea/TextareaVariants.ts +30 -30
  125. package/dist/astro/textarea/index.ts +4 -4
  126. package/dist/astro/tooltip/Tooltip.astro +40 -0
  127. package/dist/astro/tooltip/TooltipContent.astro +39 -0
  128. package/dist/astro/tooltip/index.ts +6 -0
  129. package/dist/astro/tooltip/tooltip.ts +137 -0
  130. package/dist/astro/tooltip/tooltipVariants.ts +115 -0
  131. package/dist/index.js +44 -0
  132. package/dist/index.js.map +1 -1
  133. package/package.json +54 -54
@@ -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
+ }
@@ -0,0 +1,83 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ const baseClass =
4
+ "hidden fixed flex-col z-50 p-6 bg-surface text-foreground border-border shadow-sm transform duration-200 transition-all ease-in-out data-[state=closed]:opacity-0 data-[state=open]:opacity-100";
5
+
6
+ const drawerVariants = cva(baseClass, {
7
+ variants: {
8
+ position: {
9
+ top: "w-full top-0 left-0 border-b data-[state=closed]:-translate-y-full data-[state=open]:translate-y-0 mb-8",
10
+ bottom:
11
+ "w-full bottom-0 left-0 border-t data-[state=closed]:translate-y-full data-[state=open]:translate-y-0 mt-8",
12
+ left: "h-dvh top-0 left-0 border-r data-[state=closed]:-translate-x-full data-[state=open]:translate-x-0 mr-8",
13
+ right:
14
+ "h-dvh top-0 right-0 border-l data-[state=closed]:translate-x-full data-[state=open]:translate-x-0 ml-8",
15
+ },
16
+ size: {
17
+ xs: "",
18
+ sm: "",
19
+ md: "",
20
+ lg: "",
21
+ xl: "",
22
+ full: "",
23
+ },
24
+ },
25
+ compoundVariants: [
26
+ {
27
+ position: ["left", "right"],
28
+ size: "sm",
29
+ class: "max-w-sm",
30
+ },
31
+ {
32
+ position: ["left", "right"],
33
+ size: "md",
34
+ class: "max-w-md",
35
+ },
36
+ {
37
+ position: ["left", "right"],
38
+ size: "lg",
39
+ class: "max-w-lg",
40
+ },
41
+ {
42
+ position: ["left", "right"],
43
+ size: "xl",
44
+ class: "max-w-xl",
45
+ },
46
+ {
47
+ position: ["left", "right"],
48
+ size: "full",
49
+ class: "w-full",
50
+ },
51
+ {
52
+ position: ["top", "bottom"],
53
+ size: "sm",
54
+ class: "max-h-[var(--container-sm)]",
55
+ },
56
+ {
57
+ position: ["top", "bottom"],
58
+ size: "md",
59
+ class: "max-h-[var(--container-md)]",
60
+ },
61
+ {
62
+ position: ["top", "bottom"],
63
+ size: "lg",
64
+ class: "max-h-[var(--container-lg)]",
65
+ },
66
+ {
67
+ position: ["top", "bottom"],
68
+ size: "xl",
69
+ class: "max-h-[var(--container-xl)]",
70
+ },
71
+ {
72
+ position: ["top", "bottom"],
73
+ size: "full",
74
+ class: "h-dvh",
75
+ },
76
+ ],
77
+ defaultVariants: {
78
+ position: "right",
79
+ size: "sm",
80
+ },
81
+ });
82
+
83
+ export { drawerVariants };
@@ -0,0 +1,15 @@
1
+ import Drawer from "./Drawer.astro";
2
+ import DrawerContent from "./DrawerContent.astro";
3
+ import DrawerDescription from "./DrawerDescription.astro";
4
+ import DrawerFooter from "./DrawerFooter.astro";
5
+ import DrawerHeader from "./DrawerHeader.astro";
6
+ import DrawerTitle from "./DrawerTitle.astro";
7
+
8
+ export {
9
+ Drawer,
10
+ DrawerContent,
11
+ DrawerDescription,
12
+ DrawerFooter,
13
+ DrawerHeader,
14
+ DrawerTitle,
15
+ };
@@ -0,0 +1,19 @@
1
+ <div class="relative" data-dropdown-menu>
2
+ <slot />
3
+ </div>
4
+
5
+ <script>
6
+ import { DowndownMenu } from "./dropdown";
7
+
8
+ function init() {
9
+ const dropdowns = document.querySelectorAll<HTMLElement>(
10
+ "[data-dropdown-menu]",
11
+ );
12
+ dropdowns.forEach((dropdown) => {
13
+ new DowndownMenu(dropdown);
14
+ });
15
+ }
16
+
17
+ init();
18
+ document.addEventListener("astro:page-load", () => init());
19
+ </script>
@@ -0,0 +1,42 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { HTMLAttributes } from "astro/types";
4
+ import type { VariantProps } from "class-variance-authority";
5
+ import {
6
+ dropdownArrowVariants,
7
+ dropdownMenuVariants,
8
+ } from "./dropdownVariants";
9
+
10
+ interface Props
11
+ extends HTMLAttributes<"div">,
12
+ VariantProps<typeof dropdownMenuVariants> {
13
+ sideOffset?: number;
14
+ arrow?: boolean;
15
+ }
16
+
17
+ const {
18
+ class: className,
19
+ side,
20
+ alignment,
21
+ sideOffset = 2,
22
+ arrow = false,
23
+ ...attrs
24
+ } = Astro.props;
25
+ ---
26
+
27
+ <div
28
+ {...attrs}
29
+ role="menu"
30
+ data-dropdown-content
31
+ aria-hidden="true"
32
+ data-state="closed"
33
+ data-side={sideOffset}
34
+ data-alignment={alignment}
35
+ class={cn(dropdownMenuVariants({ side, alignment, className }))}
36
+ style={{
37
+ "--tooltip-offset": `calc(var(--spacing) * ${sideOffset})`,
38
+ }}
39
+ >
40
+ <slot />
41
+ {arrow && <span class={cn(dropdownArrowVariants({ side, alignment }))} />}
42
+ </div>
@@ -0,0 +1,3 @@
1
+ <div role="group">
2
+ <slot />
3
+ </div>
@@ -0,0 +1,27 @@
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import type { VariantProps } from "class-variance-authority";
4
+ import { dropdownMenuItemVariants } from "./dropdownVariants";
5
+
6
+ import type { HTMLTag, Polymorphic } from "astro/types";
7
+
8
+ type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> &
9
+ VariantProps<typeof dropdownMenuItemVariants>;
10
+
11
+ const {
12
+ class: className,
13
+ as: Tag = "div",
14
+ disabled = false,
15
+ ...attrs
16
+ } = Astro.props;
17
+ ---
18
+
19
+ <Tag
20
+ role="menuitem"
21
+ tabindex={disabled ? "-1" : "0"}
22
+ data-disabled={disabled}
23
+ class={cn(dropdownMenuItemVariants({ disabled, className }))}
24
+ {...attrs}
25
+ >
26
+ <slot />
27
+ </Tag>
@@ -0,0 +1,3 @@
1
+ <div class="px-2 py-1.5 text-sm font-medium">
2
+ <slot />
3
+ </div>
@@ -0,0 +1,6 @@
1
+ <div
2
+ role="separator"
3
+ aria-orientation="horizontal"
4
+ class="bg-border -mx-1 my-1 h-px"
5
+ >
6
+ </div>
@@ -0,0 +1,157 @@
1
+ export class DowndownMenu {
2
+ // References to tooltip elements
3
+ private dropdownMenu: HTMLElement;
4
+ private trigger: HTMLElement | null;
5
+ private content: HTMLElement | null;
6
+ private menuItems: HTMLElement[] = [];
7
+
8
+ constructor(dropowndMenu: HTMLElement) {
9
+ this.dropdownMenu = dropowndMenu;
10
+ this.content = this.dropdownMenu.querySelector("[data-dropdown-content]");
11
+ this.trigger = this.dropdownMenu.querySelector("[data-trigger]");
12
+ this.menuItems = Array.from(
13
+ this.content?.querySelectorAll(
14
+ '[role="menuitem"]:not([data-disabled="true"])',
15
+ ) || [],
16
+ );
17
+
18
+ if (!this.content || !this.trigger) {
19
+ console.error("Dropdown not initialized properly", {
20
+ content: this.content,
21
+ trigger: this.trigger,
22
+ });
23
+ return;
24
+ }
25
+
26
+ this.init();
27
+ }
28
+
29
+ private init() {
30
+ this.setupAccessibility();
31
+ this.setupEventListeners();
32
+ }
33
+
34
+ private setupAccessibility() {
35
+ if (!this.trigger || !this.content) return;
36
+
37
+ const id =
38
+ this.content.id ||
39
+ `dropdown-id-${Math.random().toString(36).substring(2, 9)}`;
40
+ this.content.id = id;
41
+ this.trigger.setAttribute("aria-describedby", id);
42
+ this.setState("closed");
43
+ }
44
+
45
+ private setupEventListeners() {
46
+ if (!this.trigger || !this.content) return;
47
+
48
+ this.trigger.addEventListener("click", () => this.toggleDropdown());
49
+
50
+ this.content.addEventListener("click", (e) => {
51
+ const target = e.target as HTMLElement;
52
+ const item = target.closest('[role="menuitem"]') as HTMLElement;
53
+
54
+ if (item && item.dataset.disabled !== "true") {
55
+ this.closeDropdown();
56
+ }
57
+ });
58
+
59
+ document.addEventListener("click", (e) => {
60
+ const target = e.target as HTMLElement;
61
+ if (
62
+ this.content &&
63
+ !this.content.contains(target) &&
64
+ target !== this.trigger
65
+ ) {
66
+ this.closeDropdown();
67
+ }
68
+ });
69
+
70
+ this.trigger.addEventListener("keydown", (e) => {
71
+ const isOpen = this.content?.dataset.state === "open";
72
+ if (e.key === "Enter" || e.key === " ") {
73
+ e.preventDefault();
74
+ this.toggleDropdown();
75
+ } else if (e.key === "Escape" && isOpen) {
76
+ e.preventDefault();
77
+ this.closeDropdown();
78
+ } else if (isOpen && e.key === "ArrowDown") {
79
+ e.preventDefault();
80
+ this.setFocusItem(0);
81
+ } else if (isOpen && e.key === "ArrowUp") {
82
+ e.preventDefault();
83
+ this.setFocusItem(this.menuItems.length - 1);
84
+ }
85
+ });
86
+
87
+ this.menuItems.forEach((menuItem) => {
88
+ menuItem.addEventListener("keydown", (e) =>
89
+ this.handleMenuKeydown(e, menuItem),
90
+ );
91
+ });
92
+ document.addEventListener("keydown", (e) => this.handleKeydown(e));
93
+ }
94
+
95
+ private toggleDropdown() {
96
+ if (this.content?.dataset.state === "open") {
97
+ this.closeDropdown();
98
+ } else {
99
+ this.openDropdown();
100
+ }
101
+ }
102
+
103
+ private openDropdown() {
104
+ this.content?.classList.remove("hidden");
105
+
106
+ window.setTimeout(() => {
107
+ this.setState("open");
108
+ }, 0);
109
+ }
110
+
111
+ private closeDropdown() {
112
+ this.trigger?.focus();
113
+ this.setState("closed");
114
+ window.setTimeout(() => {
115
+ this.content?.classList.add("hidden");
116
+ }, 100);
117
+ }
118
+
119
+ private setState(state: "open" | "closed") {
120
+ this.content?.setAttribute("aria-hidden", `${state === "closed"}`);
121
+ this.content?.setAttribute("data-state", state);
122
+ }
123
+
124
+ private handleKeydown = (event: KeyboardEvent) => {
125
+ if (event.key === "Escape" && this.content!.dataset.state === "open") {
126
+ this.closeDropdown();
127
+ event.preventDefault();
128
+ }
129
+ };
130
+
131
+ private handleMenuKeydown(event: KeyboardEvent, item: HTMLElement) {
132
+ const currentItemIndex = this.menuItems.indexOf(item);
133
+
134
+ const keyActions: Record<string, () => void> = {
135
+ ArrowDown: () => this.setFocusItem(currentItemIndex + 1),
136
+ ArrowUp: () => this.setFocusItem(currentItemIndex - 1),
137
+ Home: () => this.setFocusItem(0),
138
+ End: () => this.setFocusItem(this.menuItems.length - 1),
139
+ Enter: () => item.click(),
140
+ " ": () => item.click(),
141
+ };
142
+
143
+ const action = keyActions[event.key];
144
+ if (action) {
145
+ event.preventDefault();
146
+ action();
147
+ }
148
+ }
149
+
150
+ private setFocusItem(index: number) {
151
+ const newIndex = (index + this.menuItems.length) % this.menuItems.length;
152
+
153
+ if (this.menuItems[newIndex]) {
154
+ this.menuItems[newIndex].focus();
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,134 @@
1
+ import { cva } from "class-variance-authority";
2
+
3
+ const baseClass = [
4
+ "hidden absolute z-50 bg-surface border border-border p-1 rounded-md",
5
+ "transform duration-100 transition-all ease-in data-[state=closed]:opacity-0 data-[state=closed]:scale-95 data[state=open]:opacity-100 data[state=open]:scale-100",
6
+ ];
7
+
8
+ const dropdownMenuVariants = cva(baseClass, {
9
+ variants: {
10
+ side: {
11
+ top: "bottom-full mb-(--tooltip-offset)",
12
+ bottom: "top-full mt-(--tooltip-offset)",
13
+ left: "right-full mr-(--tooltip-offset)",
14
+ right: "left-full ml-(--tooltip-offset)",
15
+ },
16
+ alignment: {
17
+ start: "",
18
+ center: "",
19
+ end: "",
20
+ },
21
+ },
22
+ compoundVariants: [
23
+ {
24
+ side: ["top", "bottom"],
25
+ alignment: "start",
26
+ class: "left-0",
27
+ },
28
+ {
29
+ side: ["top", "bottom"],
30
+ alignment: "end",
31
+ class: "left-full -translate-x-full",
32
+ },
33
+ {
34
+ side: ["top", "bottom"],
35
+ alignment: "center",
36
+ class: "left-1/2 -translate-x-1/2",
37
+ },
38
+ {
39
+ side: ["left", "right"],
40
+ alignment: "start",
41
+ class: "top-0 -translate-y-0",
42
+ },
43
+ {
44
+ side: ["left", "right"],
45
+ alignment: "center",
46
+ class: "top-1/2 -translate-y-1/2",
47
+ },
48
+ {
49
+ side: ["left", "right"],
50
+ alignment: "end",
51
+ class: "top-full -translate-y-full",
52
+ },
53
+ ],
54
+ defaultVariants: {
55
+ side: "bottom",
56
+ alignment: "center",
57
+ },
58
+ });
59
+
60
+ const dropdownMenuItemBaseClass =
61
+ "flex justify-between items-center gap-2 px-2 py-1.5 text-sm cursor-default rounded-md outline-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4";
62
+
63
+ const dropdownMenuItemVariants = cva(dropdownMenuItemBaseClass, {
64
+ variants: {
65
+ disabled: {
66
+ false: "hover:bg-foreground/5 focus:bg-foreground/5 ",
67
+ true: "opacity-70 pointer-events-none",
68
+ },
69
+ },
70
+ defaultVariants: {
71
+ disabled: false,
72
+ },
73
+ });
74
+
75
+ const arrowClass =
76
+ "absolute w-0 h-0 transition-all transform ease-in size-2 bg-surface transform rotate-45 border-border";
77
+
78
+ const dropdownArrowVariants = cva(arrowClass, {
79
+ variants: {
80
+ side: {
81
+ top: "top-full -mt-1 border-b border-r",
82
+ bottom: "bottom-full -mb-1 border-t border-l",
83
+ left: "left-full -ml-1 border-t border-r",
84
+ right: "right-full -mr-1 border-b border-l",
85
+ },
86
+ alignment: {
87
+ start: "",
88
+ center: "",
89
+ end: "",
90
+ },
91
+ },
92
+ compoundVariants: [
93
+ {
94
+ side: ["top", "bottom"],
95
+ alignment: "start",
96
+ class: "left-0 ml-3 ",
97
+ },
98
+ {
99
+ side: ["top", "bottom"],
100
+ alignment: "end",
101
+ class: "right-0 mr-3",
102
+ },
103
+ {
104
+ side: ["top", "bottom"],
105
+ alignment: "center",
106
+ class: "left-1/2 -translate-x-1/2",
107
+ },
108
+ {
109
+ side: ["left", "right"],
110
+ alignment: "start",
111
+ class: "top-0 mt-3",
112
+ },
113
+ {
114
+ side: ["left", "right"],
115
+ alignment: "center",
116
+ class: "top-1/2 -translate-y-1/2",
117
+ },
118
+ {
119
+ side: ["left", "right"],
120
+ alignment: "end",
121
+ class: "bottom-0 mb-3",
122
+ },
123
+ ],
124
+ defaultVariants: {
125
+ side: "bottom",
126
+ alignment: "center",
127
+ },
128
+ });
129
+
130
+ export {
131
+ dropdownArrowVariants,
132
+ dropdownMenuItemVariants,
133
+ dropdownMenuVariants,
134
+ };
@@ -0,0 +1,15 @@
1
+ import DropdownMenu from "./DropdownMenu.astro";
2
+ import DropdownMenuContent from "./DropdownMenuContent.astro";
3
+ import DropdownMenuGroup from "./DropdownMenuGroup.astro";
4
+ import DropdownMenuItem from "./DropdownMenuItem.astro";
5
+ import DropdownMenuLabel from "./DropdownMenuLabel.astro";
6
+ import DropdownMenuSeparator from "./DropdownMenuSeparator.astro";
7
+
8
+ export {
9
+ DropdownMenu,
10
+ DropdownMenuContent,
11
+ DropdownMenuGroup,
12
+ DropdownMenuItem,
13
+ DropdownMenuLabel,
14
+ DropdownMenuSeparator,
15
+ };
@@ -1,18 +1,18 @@
1
- ---
2
- import { cn } from "@/utils/cn";
3
- import { type HTMLAttributes } from "astro/types";
4
- import type { VariantProps } from "class-variance-authority";
5
- import { inputVariants } from "./inputVariants";
6
-
7
- interface Props
8
- extends Omit<HTMLAttributes<"input">, "disabled">,
9
- VariantProps<typeof inputVariants> {}
10
-
11
- const { class: className, variant, disabled, ...attrs } = Astro.props;
12
- ---
13
-
14
- <input
15
- {...attrs}
16
- disabled={disabled}
17
- class={cn(inputVariants({ variant, disabled, className }))}
18
- />
1
+ ---
2
+ import { cn } from "@/utils/cn";
3
+ import { type HTMLAttributes } from "astro/types";
4
+ import type { VariantProps } from "class-variance-authority";
5
+ import { inputVariants } from "./inputVariants";
6
+
7
+ interface Props
8
+ extends Omit<HTMLAttributes<"input">, "disabled">,
9
+ VariantProps<typeof inputVariants> {}
10
+
11
+ const { class: className, variant, disabled, ...attrs } = Astro.props;
12
+ ---
13
+
14
+ <input
15
+ {...attrs}
16
+ disabled={disabled}
17
+ class={cn(inputVariants({ variant, disabled, className }))}
18
+ />
@@ -1,4 +1,4 @@
1
- import Input from "./Input.astro";
2
- import { inputVariants } from "./inputVariants";
3
-
4
- export { Input, inputVariants };
1
+ import Input from "./Input.astro";
2
+ import { inputVariants } from "./inputVariants";
3
+
4
+ export { Input, inputVariants };