@orbitkit/components 0.2.0 → 0.3.0
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/astro/accordion/Accordion.astro +34 -34
- package/dist/astro/accordion/AccordionItem.astro +19 -19
- package/dist/astro/accordion/AccordionTrigger.astro +33 -33
- package/dist/astro/accordion/AcordionContent.astro +23 -23
- package/dist/astro/accordion/accordion.ts +151 -151
- package/dist/astro/accordion/index.ts +6 -6
- package/dist/astro/collapsible/Collapsible.astro +34 -34
- package/dist/astro/collapsible/CollapsibleContent.astro +20 -20
- package/dist/astro/collapsible/collapsible.ts +81 -81
- package/dist/astro/collapsible/index.ts +4 -4
- package/dist/astro/drawer/DrawerContent.astro +74 -74
- package/dist/astro/drawer/drawer.ts +104 -104
- package/dist/astro/drawer/index.ts +17 -17
- package/dist/astro/dropdown/DropdownMenu.astro +19 -19
- package/dist/astro/dropdown/DropdownMenuContent.astro +42 -42
- package/dist/astro/dropdown/DropdownMenuGroup.astro +3 -3
- package/dist/astro/dropdown/DropdownMenuItem.astro +27 -27
- package/dist/astro/dropdown/DropdownMenuLabel.astro +3 -3
- package/dist/astro/dropdown/DropdownMenuSeparator.astro +6 -6
- package/dist/astro/dropdown/dropdown.ts +157 -157
- package/dist/astro/dropdown/dropdownVariants.ts +134 -134
- package/dist/astro/dropdown/index.ts +23 -23
- package/dist/astro/marquee/Marquee.astro +53 -0
- package/dist/astro/marquee/index.ts +3 -0
- package/dist/astro/modal/Modal.astro +19 -19
- package/dist/astro/modal/ModalContent.astro +71 -71
- package/dist/astro/modal/ModalDescription.astro +12 -12
- package/dist/astro/modal/ModalFooter.astro +15 -15
- package/dist/astro/modal/ModalHeader.astro +12 -12
- package/dist/astro/modal/ModalTitle.astro +18 -18
- package/dist/astro/modal/index.ts +15 -15
- package/dist/astro/modal/modal.ts +101 -101
- package/dist/astro/pagination/index.ts +15 -15
- package/dist/astro/popover/Popover.astro +17 -17
- package/dist/astro/popover/PopoverContent.astro +39 -39
- package/dist/astro/popover/index.ts +5 -5
- package/dist/astro/popover/popover.ts +113 -113
- package/dist/astro/popover/popoverVariants.ts +115 -115
- package/dist/astro/scroll-progress/ScrollProgress.astro +41 -0
- package/dist/astro/scroll-progress/ScrollProgressBar.astro +19 -0
- package/dist/astro/scroll-progress/index.ts +4 -0
- package/dist/astro/stat/Stat.astro +12 -12
- package/dist/astro/stat/StatDescription.astro +12 -12
- package/dist/astro/stat/StatTitle.astro +18 -18
- package/dist/astro/stat/StatValue.astro +12 -12
- package/dist/astro/stat/index.ts +6 -6
- package/dist/astro/tab/TabList.astro +19 -19
- package/dist/astro/toast/Toast.astro +36 -0
- package/dist/astro/toast/ToastDescription.astro +10 -0
- package/dist/astro/toast/ToastTitle.astro +18 -0
- package/dist/astro/toast/Toaster.astro +78 -0
- package/dist/astro/toast/assets.ts +6 -0
- package/dist/astro/toast/index.ts +30 -0
- package/dist/astro/toast/toast.ts +277 -0
- package/dist/astro/tooltip/Tooltip.astro +40 -40
- package/dist/astro/tooltip/TooltipContent.astro +39 -39
- package/dist/astro/tooltip/index.ts +5 -5
- package/dist/astro/tooltip/tooltip.ts +137 -137
- package/dist/astro/tooltip/tooltipVariants.ts +115 -115
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/package.json +54 -54
|
@@ -1,81 +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
|
-
}
|
|
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
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Collapsible from "./Collapsible.astro";
|
|
2
|
-
import CollapsibleContent from "./CollapsibleContent.astro";
|
|
3
|
-
|
|
4
|
-
export { Collapsible, CollapsibleContent };
|
|
1
|
+
import Collapsible from "./Collapsible.astro";
|
|
2
|
+
import CollapsibleContent from "./CollapsibleContent.astro";
|
|
3
|
+
|
|
4
|
+
export { Collapsible, CollapsibleContent };
|
|
@@ -1,74 +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 fixed inset-0 left-0 top-0 z-50 hidden h-dvh w-full transition-opacity duration-100 data-[state=closed]:opacity-0 data-[state=open]:opacity-80"
|
|
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>
|
|
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 fixed inset-0 left-0 top-0 z-50 hidden h-dvh w-full transition-opacity duration-100 data-[state=closed]:opacity-0 data-[state=open]:opacity-80"
|
|
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>
|
|
@@ -1,104 +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
|
-
}
|
|
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
|
+
}
|
|
@@ -1,17 +1,17 @@
|
|
|
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
|
-
import { drawerVariants } from "./drawerVariants";
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
Drawer,
|
|
11
|
-
DrawerContent,
|
|
12
|
-
DrawerDescription,
|
|
13
|
-
DrawerFooter,
|
|
14
|
-
DrawerHeader,
|
|
15
|
-
DrawerTitle,
|
|
16
|
-
drawerVariants,
|
|
17
|
-
};
|
|
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
|
+
import { drawerVariants } from "./drawerVariants";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
Drawer,
|
|
11
|
+
DrawerContent,
|
|
12
|
+
DrawerDescription,
|
|
13
|
+
DrawerFooter,
|
|
14
|
+
DrawerHeader,
|
|
15
|
+
DrawerTitle,
|
|
16
|
+
drawerVariants,
|
|
17
|
+
};
|
|
@@ -1,19 +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>
|
|
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>
|