@lanrenbang/basecoat-ultra 0.1.2

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 (55) hide show
  1. package/CHANGELOG-cn.md +54 -0
  2. package/CHANGELOG.md +54 -0
  3. package/LICENSE +21 -0
  4. package/README-cn.md +186 -0
  5. package/README.md +173 -0
  6. package/dist/css/basecoat.cdn.css +7389 -0
  7. package/dist/css/basecoat.cdn.min.css +2 -0
  8. package/dist/css/basecoat.css +1797 -0
  9. package/dist/css/datepicker.css +382 -0
  10. package/dist/css/datepicker.min.css +1 -0
  11. package/dist/css/resizable.css +96 -0
  12. package/dist/css/resizable.min.css +1 -0
  13. package/dist/js/accordion.js +20 -0
  14. package/dist/js/accordion.min.js +13 -0
  15. package/dist/js/all.js +17 -0
  16. package/dist/js/all.min.js +17 -0
  17. package/dist/js/basecoat.js +75 -0
  18. package/dist/js/basecoat.min.js +56 -0
  19. package/dist/js/carousel.js +104 -0
  20. package/dist/js/carousel.min.js +41 -0
  21. package/dist/js/catppuccin-theme-switcher.js +136 -0
  22. package/dist/js/catppuccin-theme-switcher.min.js +73 -0
  23. package/dist/js/command.js +132 -0
  24. package/dist/js/command.min.js +76 -0
  25. package/dist/js/datepicker.js +2367 -0
  26. package/dist/js/datepicker.min.js +1422 -0
  27. package/dist/js/dialog.js +20 -0
  28. package/dist/js/dialog.min.js +11 -0
  29. package/dist/js/dropdown-menu.js +148 -0
  30. package/dist/js/dropdown-menu.min.js +75 -0
  31. package/dist/js/input-otp.js +94 -0
  32. package/dist/js/input-otp.min.js +38 -0
  33. package/dist/js/lighting.js +80 -0
  34. package/dist/js/lighting.min.js +44 -0
  35. package/dist/js/popover.js +72 -0
  36. package/dist/js/popover.min.js +34 -0
  37. package/dist/js/resizable.js +534 -0
  38. package/dist/js/resizable.min.js +284 -0
  39. package/dist/js/select.js +246 -0
  40. package/dist/js/select.min.js +131 -0
  41. package/dist/js/sheet.js +85 -0
  42. package/dist/js/sheet.min.js +40 -0
  43. package/dist/js/sidebar.js +87 -0
  44. package/dist/js/sidebar.min.js +53 -0
  45. package/dist/js/slider.js +18 -0
  46. package/dist/js/slider.min.js +10 -0
  47. package/dist/js/tabs.js +53 -0
  48. package/dist/js/tabs.min.js +40 -0
  49. package/dist/js/toast.js +137 -0
  50. package/dist/js/toast.min.js +83 -0
  51. package/dist/js/toggle.js +36 -0
  52. package/dist/js/toggle.min.js +20 -0
  53. package/dist/theme/catppuccin/index.css +448 -0
  54. package/dist/theme/catppuccin/index.min.css +1 -0
  55. package/package.json +46 -0
@@ -0,0 +1,20 @@
1
+ (() => {
2
+ const initDialog = (dialog) => {
3
+ if (dialog.getAttribute("role") !== "alertdialog") {
4
+ dialog.addEventListener("click", (event) => {
5
+ if (dialog.open) {
6
+ const rect = dialog.getBoundingClientRect();
7
+ const isInDialog = rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
8
+ if (!isInDialog) {
9
+ dialog.close();
10
+ }
11
+ }
12
+ });
13
+ }
14
+ dialog.dataset.dialogInitialized = true;
15
+ dialog.dispatchEvent(new CustomEvent("basecoat:initialized"));
16
+ };
17
+ if (window.basecoat) {
18
+ window.basecoat.register("dialog", "dialog.dialog:not([data-dialog-initialized])", initDialog);
19
+ }
20
+ })();
@@ -0,0 +1,11 @@
1
+ (() => {
2
+ const n = (t) => {
3
+ t.getAttribute("role") !== "alertdialog" && t.addEventListener("click", (e) => {
4
+ if (t.open) {
5
+ const i = t.getBoundingClientRect();
6
+ i.top <= e.clientY && e.clientY <= i.top + i.height && i.left <= e.clientX && e.clientX <= i.left + i.width || t.close();
7
+ }
8
+ }), t.dataset.dialogInitialized = !0, t.dispatchEvent(new CustomEvent("basecoat:initialized"));
9
+ };
10
+ window.basecoat && window.basecoat.register("dialog", "dialog.dialog:not([data-dialog-initialized])", n);
11
+ })();
@@ -0,0 +1,148 @@
1
+ (() => {
2
+ const initDropdownMenu = (dropdownMenuComponent) => {
3
+ const trigger = dropdownMenuComponent.querySelector(":scope > button");
4
+ const popover = dropdownMenuComponent.querySelector(":scope > [data-popover]");
5
+ const menu = popover?.matches('[role="menu"]') ? popover : popover?.querySelector('[role="menu"]');
6
+ if (!trigger || !menu || !popover) {
7
+ const missing = [];
8
+ if (!trigger) missing.push("trigger");
9
+ if (!menu) missing.push("menu");
10
+ if (!popover) missing.push("popover");
11
+ console.error(`Dropdown menu initialisation failed. Missing element(s): ${missing.join(", ")}`, dropdownMenuComponent);
12
+ return;
13
+ }
14
+ let menuItems = [];
15
+ let activeIndex = -1;
16
+ const closePopover = (focusOnTrigger = true) => {
17
+ if (trigger.getAttribute("aria-expanded") === "false") return;
18
+ trigger.setAttribute("aria-expanded", "false");
19
+ trigger.removeAttribute("aria-activedescendant");
20
+ popover.setAttribute("aria-hidden", "true");
21
+ if (focusOnTrigger) {
22
+ trigger.focus();
23
+ }
24
+ setActiveItem(-1);
25
+ };
26
+ const openPopover = (initialSelection = false) => {
27
+ document.dispatchEvent(new CustomEvent("basecoat:popover", {
28
+ detail: { source: dropdownMenuComponent }
29
+ }));
30
+ trigger.setAttribute("aria-expanded", "true");
31
+ popover.setAttribute("aria-hidden", "false");
32
+ menuItems = Array.from(menu.querySelectorAll('[role^="menuitem"]')).filter(
33
+ (item) => !item.hasAttribute("disabled") && item.getAttribute("aria-disabled") !== "true"
34
+ );
35
+ if (menuItems.length > 0 && initialSelection) {
36
+ if (initialSelection === "first") {
37
+ setActiveItem(0);
38
+ } else if (initialSelection === "last") {
39
+ setActiveItem(menuItems.length - 1);
40
+ }
41
+ }
42
+ };
43
+ const setActiveItem = (index) => {
44
+ if (activeIndex > -1 && menuItems[activeIndex]) {
45
+ menuItems[activeIndex].classList.remove("active");
46
+ }
47
+ activeIndex = index;
48
+ if (activeIndex > -1 && menuItems[activeIndex]) {
49
+ const activeItem = menuItems[activeIndex];
50
+ activeItem.classList.add("active");
51
+ trigger.setAttribute("aria-activedescendant", activeItem.id);
52
+ } else {
53
+ trigger.removeAttribute("aria-activedescendant");
54
+ }
55
+ };
56
+ trigger.addEventListener("click", () => {
57
+ const isExpanded = trigger.getAttribute("aria-expanded") === "true";
58
+ if (isExpanded) {
59
+ closePopover();
60
+ } else {
61
+ openPopover(false);
62
+ }
63
+ });
64
+ dropdownMenuComponent.addEventListener("keydown", (event) => {
65
+ const isExpanded = trigger.getAttribute("aria-expanded") === "true";
66
+ if (event.key === "Escape") {
67
+ if (isExpanded) closePopover();
68
+ return;
69
+ }
70
+ if (!isExpanded) {
71
+ if (["Enter", " "].includes(event.key)) {
72
+ event.preventDefault();
73
+ openPopover(false);
74
+ } else if (event.key === "ArrowDown") {
75
+ event.preventDefault();
76
+ openPopover("first");
77
+ } else if (event.key === "ArrowUp") {
78
+ event.preventDefault();
79
+ openPopover("last");
80
+ }
81
+ return;
82
+ }
83
+ if (menuItems.length === 0) return;
84
+ let nextIndex = activeIndex;
85
+ switch (event.key) {
86
+ case "ArrowDown":
87
+ event.preventDefault();
88
+ nextIndex = activeIndex === -1 ? 0 : Math.min(activeIndex + 1, menuItems.length - 1);
89
+ break;
90
+ case "ArrowUp":
91
+ event.preventDefault();
92
+ nextIndex = activeIndex === -1 ? menuItems.length - 1 : Math.max(activeIndex - 1, 0);
93
+ break;
94
+ case "Home":
95
+ event.preventDefault();
96
+ nextIndex = 0;
97
+ break;
98
+ case "End":
99
+ event.preventDefault();
100
+ nextIndex = menuItems.length - 1;
101
+ break;
102
+ case "Enter":
103
+ case " ":
104
+ event.preventDefault();
105
+ menuItems[activeIndex]?.click();
106
+ closePopover();
107
+ return;
108
+ }
109
+ if (nextIndex !== activeIndex) {
110
+ setActiveItem(nextIndex);
111
+ }
112
+ });
113
+ menu.addEventListener("mousemove", (event) => {
114
+ const menuItem = event.target.closest('[role^="menuitem"]');
115
+ if (menuItem && menuItems.includes(menuItem)) {
116
+ const index = menuItems.indexOf(menuItem);
117
+ if (index !== activeIndex) {
118
+ setActiveItem(index);
119
+ }
120
+ }
121
+ });
122
+ menu.addEventListener("mouseleave", () => {
123
+ setActiveItem(-1);
124
+ });
125
+ menu.addEventListener("click", (event) => {
126
+ if (event.target.closest('[role^="menuitem"]')) {
127
+ closePopover();
128
+ }
129
+ });
130
+ document.addEventListener("click", (event) => {
131
+ if (!dropdownMenuComponent.contains(event.target)) {
132
+ closePopover();
133
+ }
134
+ });
135
+ document.addEventListener("basecoat:popover", (event) => {
136
+ if (event.detail.source !== dropdownMenuComponent) {
137
+ closePopover(false);
138
+ }
139
+ });
140
+ trigger.setAttribute("aria-expanded", "false");
141
+ popover.setAttribute("aria-hidden", "true");
142
+ dropdownMenuComponent.dataset.dropdownMenuInitialized = true;
143
+ dropdownMenuComponent.dispatchEvent(new CustomEvent("basecoat:initialized"));
144
+ };
145
+ if (window.basecoat) {
146
+ window.basecoat.register("dropdown-menu", ".dropdown-menu:not([data-dropdown-menu-initialized])", initDropdownMenu);
147
+ }
148
+ })();
@@ -0,0 +1,75 @@
1
+ (() => {
2
+ const f = (s) => {
3
+ const i = s.querySelector(":scope > button"), d = s.querySelector(":scope > [data-popover]"), c = d?.matches('[role="menu"]') ? d : d?.querySelector('[role="menu"]');
4
+ if (!i || !c || !d) {
5
+ const e = [];
6
+ i || e.push("trigger"), c || e.push("menu"), d || e.push("popover"), console.error(`Dropdown menu initialisation failed. Missing element(s): ${e.join(", ")}`, s);
7
+ return;
8
+ }
9
+ let a = [], t = -1;
10
+ const l = (e = !0) => {
11
+ i.getAttribute("aria-expanded") !== "false" && (i.setAttribute("aria-expanded", "false"), i.removeAttribute("aria-activedescendant"), d.setAttribute("aria-hidden", "true"), e && i.focus(), u(-1));
12
+ }, o = (e = !1) => {
13
+ document.dispatchEvent(new CustomEvent("basecoat:popover", {
14
+ detail: { source: s }
15
+ })), i.setAttribute("aria-expanded", "true"), d.setAttribute("aria-hidden", "false"), a = Array.from(c.querySelectorAll('[role^="menuitem"]')).filter(
16
+ (r) => !r.hasAttribute("disabled") && r.getAttribute("aria-disabled") !== "true"
17
+ ), a.length > 0 && e && (e === "first" ? u(0) : e === "last" && u(a.length - 1));
18
+ }, u = (e) => {
19
+ if (t > -1 && a[t] && a[t].classList.remove("active"), t = e, t > -1 && a[t]) {
20
+ const r = a[t];
21
+ r.classList.add("active"), i.setAttribute("aria-activedescendant", r.id);
22
+ } else
23
+ i.removeAttribute("aria-activedescendant");
24
+ };
25
+ i.addEventListener("click", () => {
26
+ i.getAttribute("aria-expanded") === "true" ? l() : o(!1);
27
+ }), s.addEventListener("keydown", (e) => {
28
+ const r = i.getAttribute("aria-expanded") === "true";
29
+ if (e.key === "Escape") {
30
+ r && l();
31
+ return;
32
+ }
33
+ if (!r) {
34
+ ["Enter", " "].includes(e.key) ? (e.preventDefault(), o(!1)) : e.key === "ArrowDown" ? (e.preventDefault(), o("first")) : e.key === "ArrowUp" && (e.preventDefault(), o("last"));
35
+ return;
36
+ }
37
+ if (a.length === 0) return;
38
+ let n = t;
39
+ switch (e.key) {
40
+ case "ArrowDown":
41
+ e.preventDefault(), n = t === -1 ? 0 : Math.min(t + 1, a.length - 1);
42
+ break;
43
+ case "ArrowUp":
44
+ e.preventDefault(), n = t === -1 ? a.length - 1 : Math.max(t - 1, 0);
45
+ break;
46
+ case "Home":
47
+ e.preventDefault(), n = 0;
48
+ break;
49
+ case "End":
50
+ e.preventDefault(), n = a.length - 1;
51
+ break;
52
+ case "Enter":
53
+ case " ":
54
+ e.preventDefault(), a[t]?.click(), l();
55
+ return;
56
+ }
57
+ n !== t && u(n);
58
+ }), c.addEventListener("mousemove", (e) => {
59
+ const r = e.target.closest('[role^="menuitem"]');
60
+ if (r && a.includes(r)) {
61
+ const n = a.indexOf(r);
62
+ n !== t && u(n);
63
+ }
64
+ }), c.addEventListener("mouseleave", () => {
65
+ u(-1);
66
+ }), c.addEventListener("click", (e) => {
67
+ e.target.closest('[role^="menuitem"]') && l();
68
+ }), document.addEventListener("click", (e) => {
69
+ s.contains(e.target) || l();
70
+ }), document.addEventListener("basecoat:popover", (e) => {
71
+ e.detail.source !== s && l(!1);
72
+ }), i.setAttribute("aria-expanded", "false"), d.setAttribute("aria-hidden", "true"), s.dataset.dropdownMenuInitialized = !0, s.dispatchEvent(new CustomEvent("basecoat:initialized"));
73
+ };
74
+ window.basecoat && window.basecoat.register("dropdown-menu", ".dropdown-menu:not([data-dropdown-menu-initialized])", f);
75
+ })();
@@ -0,0 +1,94 @@
1
+ const initOTP = (root = document) => {
2
+ const containers = root.querySelectorAll(".input-otp");
3
+ containers.forEach((container) => {
4
+ if (container.hasAttribute("data-initialized")) return;
5
+ const inputs = Array.from(container.querySelectorAll("input"));
6
+ inputs.forEach((input, index) => {
7
+ input.type = "text";
8
+ input.inputMode = "text";
9
+ input.setAttribute("maxlength", "1");
10
+ input.setAttribute("autocomplete", "one-time-code");
11
+ input.addEventListener("focus", () => {
12
+ input.select();
13
+ });
14
+ input.addEventListener("input", (e) => {
15
+ const val = e.target.value;
16
+ if (val === "") {
17
+ return;
18
+ }
19
+ if (val.length > 1) {
20
+ input.value = val.slice(-1);
21
+ }
22
+ if (input.value.length === 1 && index < inputs.length - 1) {
23
+ inputs[index + 1].focus();
24
+ }
25
+ });
26
+ input.addEventListener("keydown", (e) => {
27
+ if (e.key === "Backspace") {
28
+ e.preventDefault();
29
+ if (input.value !== "") {
30
+ input.value = "";
31
+ } else if (index > 0) {
32
+ inputs[index - 1].focus();
33
+ }
34
+ } else if (e.key === "ArrowLeft") {
35
+ if (index > 0) {
36
+ e.preventDefault();
37
+ inputs[index - 1].focus();
38
+ }
39
+ } else if (e.key === "ArrowRight") {
40
+ if (index < inputs.length - 1) {
41
+ e.preventDefault();
42
+ inputs[index + 1].focus();
43
+ }
44
+ } else if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
45
+ if (input.value.length >= 1 && input.selectionStart === input.selectionEnd) {
46
+ input.value = "";
47
+ }
48
+ }
49
+ });
50
+ input.addEventListener("paste", (e) => {
51
+ e.preventDefault();
52
+ const pasteData = (e.clipboardData || window.clipboardData).getData("text");
53
+ const chars = pasteData.split("");
54
+ let currentIndex = index;
55
+ chars.forEach((char) => {
56
+ if (currentIndex < inputs.length) {
57
+ inputs[currentIndex].value = char;
58
+ currentIndex++;
59
+ }
60
+ });
61
+ if (currentIndex < inputs.length) {
62
+ inputs[currentIndex].focus();
63
+ } else {
64
+ inputs[inputs.length - 1].focus();
65
+ }
66
+ });
67
+ });
68
+ container.setAttribute("data-initialized", "true");
69
+ });
70
+ };
71
+ if (typeof window !== "undefined") {
72
+ const observer = new MutationObserver((mutations) => {
73
+ mutations.forEach((mutation) => {
74
+ if (mutation.type === "childList") {
75
+ mutation.addedNodes.forEach((node) => {
76
+ if (node.nodeType === 1) {
77
+ if (node.classList?.contains("input-otp")) {
78
+ initOTP(node.parentNode);
79
+ } else if (node.querySelector?.(".input-otp")) {
80
+ initOTP(node);
81
+ }
82
+ }
83
+ });
84
+ }
85
+ });
86
+ });
87
+ document.addEventListener("DOMContentLoaded", () => {
88
+ initOTP();
89
+ observer.observe(document.body, { childList: true, subtree: true });
90
+ });
91
+ }
92
+ export {
93
+ initOTP
94
+ };
@@ -0,0 +1,38 @@
1
+ const f = (c = document) => {
2
+ c.querySelectorAll(".input-otp").forEach((s) => {
3
+ if (s.hasAttribute("data-initialized")) return;
4
+ const e = Array.from(s.querySelectorAll("input"));
5
+ e.forEach((t, r) => {
6
+ t.type = "text", t.inputMode = "text", t.setAttribute("maxlength", "1"), t.setAttribute("autocomplete", "one-time-code"), t.addEventListener("focus", () => {
7
+ t.select();
8
+ }), t.addEventListener("input", (a) => {
9
+ const o = a.target.value;
10
+ o !== "" && (o.length > 1 && (t.value = o.slice(-1)), t.value.length === 1 && r < e.length - 1 && e[r + 1].focus());
11
+ }), t.addEventListener("keydown", (a) => {
12
+ a.key === "Backspace" ? (a.preventDefault(), t.value !== "" ? t.value = "" : r > 0 && e[r - 1].focus()) : a.key === "ArrowLeft" ? r > 0 && (a.preventDefault(), e[r - 1].focus()) : a.key === "ArrowRight" ? r < e.length - 1 && (a.preventDefault(), e[r + 1].focus()) : a.key.length === 1 && !a.ctrlKey && !a.metaKey && !a.altKey && t.value.length >= 1 && t.selectionStart === t.selectionEnd && (t.value = "");
13
+ }), t.addEventListener("paste", (a) => {
14
+ a.preventDefault();
15
+ const n = (a.clipboardData || window.clipboardData).getData("text").split("");
16
+ let l = r;
17
+ n.forEach((u) => {
18
+ l < e.length && (e[l].value = u, l++);
19
+ }), l < e.length ? e[l].focus() : e[e.length - 1].focus();
20
+ });
21
+ }), s.setAttribute("data-initialized", "true");
22
+ });
23
+ };
24
+ if (typeof window < "u") {
25
+ const c = new MutationObserver((i) => {
26
+ i.forEach((s) => {
27
+ s.type === "childList" && s.addedNodes.forEach((e) => {
28
+ e.nodeType === 1 && (e.classList?.contains("input-otp") ? f(e.parentNode) : e.querySelector?.(".input-otp") && f(e));
29
+ });
30
+ });
31
+ });
32
+ document.addEventListener("DOMContentLoaded", () => {
33
+ f(), c.observe(document.body, { childList: !0, subtree: !0 });
34
+ });
35
+ }
36
+ export {
37
+ f as initOTP
38
+ };
@@ -0,0 +1,80 @@
1
+ (() => {
2
+ const LIGHTING_CONFIG = {
3
+ maxOffset: 12,
4
+ variableX: "--light-x",
5
+ variableY: "--light-y",
6
+ // Selectors that require dynamic lighting
7
+ selector: ".neu-panel, .neu-field, .neu-btn"
8
+ };
9
+ let isTracking = false;
10
+ let isTicking = false;
11
+ const updateLightSource = (e) => {
12
+ const centerX = window.innerWidth / 2;
13
+ const centerY = window.innerHeight / 2;
14
+ const normX = (e.clientX - centerX) / centerX;
15
+ const normY = (e.clientY - centerY) / centerY;
16
+ const x = normX * LIGHTING_CONFIG.maxOffset * -1;
17
+ const y = normY * LIGHTING_CONFIG.maxOffset * -1;
18
+ document.documentElement.style.setProperty(LIGHTING_CONFIG.variableX, `${x}px`);
19
+ document.documentElement.style.setProperty(LIGHTING_CONFIG.variableY, `${y}px`);
20
+ };
21
+ const onMouseMove = (e) => {
22
+ if (!isTicking) {
23
+ window.requestAnimationFrame(() => {
24
+ updateLightSource(e);
25
+ isTicking = false;
26
+ });
27
+ isTicking = true;
28
+ }
29
+ };
30
+ const startTracking = () => {
31
+ if (isTracking) return;
32
+ window.addEventListener("mousemove", onMouseMove);
33
+ isTracking = true;
34
+ };
35
+ const checkRequirement = () => {
36
+ if (isTracking) return;
37
+ if (document.querySelector(LIGHTING_CONFIG.selector)) {
38
+ startTracking();
39
+ }
40
+ };
41
+ const init = () => {
42
+ if (typeof window === "undefined") return;
43
+ checkRequirement();
44
+ let timeout;
45
+ const observer = new MutationObserver((mutations) => {
46
+ if (isTracking) {
47
+ observer.disconnect();
48
+ return;
49
+ }
50
+ clearTimeout(timeout);
51
+ timeout = setTimeout(() => {
52
+ const mightHaveNeu = mutations.some((m) => {
53
+ if (m.type === "childList") {
54
+ return Array.from(m.addedNodes).some(
55
+ (node) => node.nodeType === 1 && (node.matches(LIGHTING_CONFIG.selector) || node.querySelector(LIGHTING_CONFIG.selector))
56
+ );
57
+ }
58
+ if (m.type === "attributes" && m.attributeName === "class") {
59
+ return m.target.matches(LIGHTING_CONFIG.selector);
60
+ }
61
+ return false;
62
+ });
63
+ if (mightHaveNeu) {
64
+ checkRequirement();
65
+ }
66
+ }, 100);
67
+ });
68
+ observer.observe(document.body, {
69
+ childList: true,
70
+ subtree: true,
71
+ attributes: true,
72
+ attributeFilter: ["class"]
73
+ });
74
+ };
75
+ if (document.readyState === "loading") {
76
+ document.addEventListener("DOMContentLoaded", init);
77
+ } else {
78
+ init();
79
+ }
80
+ })();
@@ -0,0 +1,44 @@
1
+ (() => {
2
+ const e = {
3
+ maxOffset: 12,
4
+ variableX: "--light-x",
5
+ variableY: "--light-y",
6
+ // Selectors that require dynamic lighting
7
+ selector: ".neu-panel, .neu-field, .neu-btn"
8
+ };
9
+ let o = !1, c = !1;
10
+ const d = (t) => {
11
+ const r = window.innerWidth / 2, s = window.innerHeight / 2, l = (t.clientX - r) / r, n = (t.clientY - s) / s, i = l * e.maxOffset * -1, y = n * e.maxOffset * -1;
12
+ document.documentElement.style.setProperty(e.variableX, `${i}px`), document.documentElement.style.setProperty(e.variableY, `${y}px`);
13
+ }, m = (t) => {
14
+ c || (window.requestAnimationFrame(() => {
15
+ d(t), c = !1;
16
+ }), c = !0);
17
+ }, f = () => {
18
+ o || (window.addEventListener("mousemove", m), o = !0);
19
+ }, a = () => {
20
+ o || document.querySelector(e.selector) && f();
21
+ }, u = () => {
22
+ if (typeof window > "u") return;
23
+ a();
24
+ let t;
25
+ const r = new MutationObserver((s) => {
26
+ if (o) {
27
+ r.disconnect();
28
+ return;
29
+ }
30
+ clearTimeout(t), t = setTimeout(() => {
31
+ s.some((n) => n.type === "childList" ? Array.from(n.addedNodes).some(
32
+ (i) => i.nodeType === 1 && (i.matches(e.selector) || i.querySelector(e.selector))
33
+ ) : n.type === "attributes" && n.attributeName === "class" ? n.target.matches(e.selector) : !1) && a();
34
+ }, 100);
35
+ });
36
+ r.observe(document.body, {
37
+ childList: !0,
38
+ subtree: !0,
39
+ attributes: !0,
40
+ attributeFilter: ["class"]
41
+ });
42
+ };
43
+ document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", u) : u();
44
+ })();
@@ -0,0 +1,72 @@
1
+ (() => {
2
+ const initPopover = (popoverComponent) => {
3
+ const trigger = popoverComponent.querySelector(":scope > button");
4
+ const content = popoverComponent.querySelector(":scope > [data-popover]");
5
+ if (!trigger || !content) {
6
+ const missing = [];
7
+ if (!trigger) missing.push("trigger");
8
+ if (!content) missing.push("content");
9
+ console.error(`Popover initialisation failed. Missing element(s): ${missing.join(", ")}`, popoverComponent);
10
+ return;
11
+ }
12
+ if (!trigger.hasAttribute("aria-expanded")) {
13
+ trigger.setAttribute("aria-expanded", "false");
14
+ }
15
+ if (!content.hasAttribute("aria-hidden")) {
16
+ content.setAttribute("aria-hidden", "true");
17
+ }
18
+ const handleDocumentClick = (event) => {
19
+ if (!popoverComponent.contains(event.target)) {
20
+ closePopover();
21
+ }
22
+ };
23
+ const closePopover = (focusOnTrigger = true) => {
24
+ if (trigger.getAttribute("aria-expanded") === "false") return;
25
+ trigger.setAttribute("aria-expanded", "false");
26
+ content.setAttribute("aria-hidden", "true");
27
+ document.removeEventListener("click", handleDocumentClick);
28
+ if (focusOnTrigger) {
29
+ trigger.focus();
30
+ }
31
+ };
32
+ const openPopover = () => {
33
+ document.dispatchEvent(new CustomEvent("basecoat:popover", {
34
+ detail: { source: popoverComponent }
35
+ }));
36
+ const elementToFocus = content.querySelector("[autofocus]");
37
+ if (elementToFocus) {
38
+ content.addEventListener("transitionend", () => {
39
+ elementToFocus.focus();
40
+ }, { once: true });
41
+ }
42
+ trigger.setAttribute("aria-expanded", "true");
43
+ content.setAttribute("aria-hidden", "false");
44
+ setTimeout(() => {
45
+ document.addEventListener("click", handleDocumentClick);
46
+ }, 0);
47
+ };
48
+ trigger.addEventListener("click", () => {
49
+ const isExpanded = trigger.getAttribute("aria-expanded") === "true";
50
+ if (isExpanded) {
51
+ closePopover();
52
+ } else {
53
+ openPopover();
54
+ }
55
+ });
56
+ popoverComponent.addEventListener("keydown", (event) => {
57
+ if (event.key === "Escape") {
58
+ closePopover();
59
+ }
60
+ });
61
+ document.addEventListener("basecoat:popover", (event) => {
62
+ if (event.detail.source !== popoverComponent) {
63
+ closePopover(false);
64
+ }
65
+ });
66
+ popoverComponent.dataset.popoverInitialized = true;
67
+ popoverComponent.dispatchEvent(new CustomEvent("basecoat:initialized"));
68
+ };
69
+ if (window.basecoat) {
70
+ window.basecoat.register("popover", ".popover:not([data-popover-initialized])", initPopover);
71
+ }
72
+ })();
@@ -0,0 +1,34 @@
1
+ (() => {
2
+ const n = (i) => {
3
+ const t = i.querySelector(":scope > button"), a = i.querySelector(":scope > [data-popover]");
4
+ if (!t || !a) {
5
+ const e = [];
6
+ t || e.push("trigger"), a || e.push("content"), console.error(`Popover initialisation failed. Missing element(s): ${e.join(", ")}`, i);
7
+ return;
8
+ }
9
+ t.hasAttribute("aria-expanded") || t.setAttribute("aria-expanded", "false"), a.hasAttribute("aria-hidden") || a.setAttribute("aria-hidden", "true");
10
+ const r = (e) => {
11
+ i.contains(e.target) || s();
12
+ }, s = (e = !0) => {
13
+ t.getAttribute("aria-expanded") !== "false" && (t.setAttribute("aria-expanded", "false"), a.setAttribute("aria-hidden", "true"), document.removeEventListener("click", r), e && t.focus());
14
+ }, d = () => {
15
+ document.dispatchEvent(new CustomEvent("basecoat:popover", {
16
+ detail: { source: i }
17
+ }));
18
+ const e = a.querySelector("[autofocus]");
19
+ e && a.addEventListener("transitionend", () => {
20
+ e.focus();
21
+ }, { once: !0 }), t.setAttribute("aria-expanded", "true"), a.setAttribute("aria-hidden", "false"), setTimeout(() => {
22
+ document.addEventListener("click", r);
23
+ }, 0);
24
+ };
25
+ t.addEventListener("click", () => {
26
+ t.getAttribute("aria-expanded") === "true" ? s() : d();
27
+ }), i.addEventListener("keydown", (e) => {
28
+ e.key === "Escape" && s();
29
+ }), document.addEventListener("basecoat:popover", (e) => {
30
+ e.detail.source !== i && s(!1);
31
+ }), i.dataset.popoverInitialized = !0, i.dispatchEvent(new CustomEvent("basecoat:initialized"));
32
+ };
33
+ window.basecoat && window.basecoat.register("popover", ".popover:not([data-popover-initialized])", n);
34
+ })();