@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,56 @@
1
+ (() => {
2
+ const i = {};
3
+ let r = null;
4
+ const l = (e, o, t) => {
5
+ i[e] = {
6
+ selector: o,
7
+ init: t
8
+ };
9
+ }, c = () => {
10
+ Object.entries(i).forEach(([e, { selector: o, init: t }]) => {
11
+ document.querySelectorAll(o).forEach(t);
12
+ });
13
+ }, a = (e) => {
14
+ e.nodeType === Node.ELEMENT_NODE && Object.entries(i).forEach(([o, { selector: t, init: n }]) => {
15
+ e.matches(t) && n(e), e.querySelectorAll(t).forEach(n);
16
+ });
17
+ }, s = () => {
18
+ if (r) return;
19
+ let e;
20
+ r = new MutationObserver((o) => {
21
+ clearTimeout(e), e = setTimeout(() => {
22
+ o.forEach((t) => {
23
+ t.addedNodes.forEach(a);
24
+ });
25
+ }, 50);
26
+ }), r.observe(document.body, { childList: !0, subtree: !0 });
27
+ }, u = () => {
28
+ r && (r.disconnect(), r = null);
29
+ }, d = (e) => {
30
+ const o = i[e];
31
+ if (!o) {
32
+ console.warn(`Component '${e}' not found in registry`);
33
+ return;
34
+ }
35
+ const t = `data-${e}-initialized`;
36
+ document.querySelectorAll(`[${t}]`).forEach((n) => {
37
+ n.removeAttribute(t);
38
+ }), document.querySelectorAll(o.selector).forEach(o.init);
39
+ }, f = () => {
40
+ Object.entries(i).forEach(([e, { selector: o }]) => {
41
+ const t = `data-${e}-initialized`;
42
+ document.querySelectorAll(`[${t}]`).forEach((n) => {
43
+ n.removeAttribute(t);
44
+ });
45
+ }), c();
46
+ };
47
+ window.basecoat = {
48
+ register: l,
49
+ init: d,
50
+ initAll: f,
51
+ start: s,
52
+ stop: u
53
+ }, document.addEventListener("DOMContentLoaded", () => {
54
+ c(), s();
55
+ });
56
+ })();
@@ -0,0 +1,104 @@
1
+ (() => {
2
+ const initCarousel = (carousel) => {
3
+ const content = carousel.querySelector(".carousel-content");
4
+ const prevBtn = carousel.querySelector(".carousel-previous");
5
+ const nextBtn = carousel.querySelector(".carousel-next");
6
+ const orientation = carousel.dataset.orientation || "horizontal";
7
+ if (!content) return;
8
+ const getScrollAmount = () => {
9
+ const firstItem = content.querySelector(".carousel-item");
10
+ if (!firstItem) return orientation === "vertical" ? content.offsetHeight : content.offsetWidth;
11
+ const style = window.getComputedStyle(firstItem);
12
+ if (orientation === "vertical") {
13
+ const itemHeight = firstItem.offsetHeight;
14
+ const marginTop = parseFloat(style.marginTop);
15
+ const marginBottom = parseFloat(style.marginBottom);
16
+ return itemHeight + marginTop + marginBottom;
17
+ } else {
18
+ const itemWidth = firstItem.offsetWidth;
19
+ const marginLeft = parseFloat(style.marginLeft);
20
+ const marginRight = parseFloat(style.marginRight);
21
+ return itemWidth + marginLeft + marginRight;
22
+ }
23
+ };
24
+ const scroll = (direction) => {
25
+ const amount = getScrollAmount();
26
+ const value = direction === "next" ? amount : -amount;
27
+ if (orientation === "vertical") {
28
+ content.scrollBy({ top: value, behavior: "smooth" });
29
+ } else {
30
+ content.scrollBy({ left: value, behavior: "smooth" });
31
+ }
32
+ };
33
+ const updateButtons = () => {
34
+ if (!prevBtn && !nextBtn) return;
35
+ const { scrollLeft, scrollTop, scrollWidth, scrollHeight, clientWidth, clientHeight } = content;
36
+ if (orientation === "vertical") {
37
+ const canScrollPrev = scrollTop > 1;
38
+ const canScrollNext = scrollTop < scrollHeight - clientHeight - 1;
39
+ if (prevBtn) {
40
+ prevBtn.disabled = !canScrollPrev;
41
+ prevBtn.setAttribute("aria-disabled", String(!canScrollPrev));
42
+ }
43
+ if (nextBtn) {
44
+ nextBtn.disabled = !canScrollNext;
45
+ nextBtn.setAttribute("aria-disabled", String(!canScrollNext));
46
+ }
47
+ } else {
48
+ const canScrollPrev = scrollLeft > 1;
49
+ const canScrollNext = scrollLeft < scrollWidth - clientWidth - 1;
50
+ if (prevBtn) {
51
+ prevBtn.disabled = !canScrollPrev;
52
+ prevBtn.setAttribute("aria-disabled", String(!canScrollPrev));
53
+ }
54
+ if (nextBtn) {
55
+ nextBtn.disabled = !canScrollNext;
56
+ nextBtn.setAttribute("aria-disabled", String(!canScrollNext));
57
+ }
58
+ }
59
+ };
60
+ if (prevBtn) {
61
+ prevBtn.addEventListener("click", () => scroll("prev"));
62
+ }
63
+ if (nextBtn) {
64
+ nextBtn.addEventListener("click", () => scroll("next"));
65
+ }
66
+ let ticking = false;
67
+ content.addEventListener("scroll", () => {
68
+ if (!ticking) {
69
+ window.requestAnimationFrame(() => {
70
+ updateButtons();
71
+ ticking = false;
72
+ });
73
+ ticking = true;
74
+ }
75
+ }, { passive: true });
76
+ carousel.addEventListener("keydown", (e) => {
77
+ if (orientation === "vertical") {
78
+ if (e.key === "ArrowUp") {
79
+ e.preventDefault();
80
+ prevBtn?.click();
81
+ } else if (e.key === "ArrowDown") {
82
+ e.preventDefault();
83
+ nextBtn?.click();
84
+ }
85
+ } else {
86
+ if (e.key === "ArrowLeft") {
87
+ e.preventDefault();
88
+ prevBtn?.click();
89
+ } else if (e.key === "ArrowRight") {
90
+ e.preventDefault();
91
+ nextBtn?.click();
92
+ }
93
+ }
94
+ });
95
+ const resizeObserver = new ResizeObserver(updateButtons);
96
+ resizeObserver.observe(content);
97
+ updateButtons();
98
+ carousel.dataset.carouselInitialized = true;
99
+ carousel.dispatchEvent(new CustomEvent("basecoat:initialized"));
100
+ };
101
+ if (window.basecoat) {
102
+ window.basecoat.register("carousel", ".carousel:not([data-carousel-initialized])", initCarousel);
103
+ }
104
+ })();
@@ -0,0 +1,41 @@
1
+ (() => {
2
+ const m = (s) => {
3
+ const o = s.querySelector(".carousel-content"), e = s.querySelector(".carousel-previous"), i = s.querySelector(".carousel-next"), a = s.dataset.orientation || "horizontal";
4
+ if (!o) return;
5
+ const b = () => {
6
+ const t = o.querySelector(".carousel-item");
7
+ if (!t) return a === "vertical" ? o.offsetHeight : o.offsetWidth;
8
+ const r = window.getComputedStyle(t);
9
+ if (a === "vertical") {
10
+ const n = t.offsetHeight, l = parseFloat(r.marginTop), c = parseFloat(r.marginBottom);
11
+ return n + l + c;
12
+ } else {
13
+ const n = t.offsetWidth, l = parseFloat(r.marginLeft), c = parseFloat(r.marginRight);
14
+ return n + l + c;
15
+ }
16
+ }, g = (t) => {
17
+ const r = b(), n = t === "next" ? r : -r;
18
+ a === "vertical" ? o.scrollBy({ top: n, behavior: "smooth" }) : o.scrollBy({ left: n, behavior: "smooth" });
19
+ }, u = () => {
20
+ if (!e && !i) return;
21
+ const { scrollLeft: t, scrollTop: r, scrollWidth: n, scrollHeight: l, clientWidth: c, clientHeight: p } = o;
22
+ if (a === "vertical") {
23
+ const d = r > 1, f = r < l - p - 1;
24
+ e && (e.disabled = !d, e.setAttribute("aria-disabled", String(!d))), i && (i.disabled = !f, i.setAttribute("aria-disabled", String(!f)));
25
+ } else {
26
+ const d = t > 1, f = t < n - c - 1;
27
+ e && (e.disabled = !d, e.setAttribute("aria-disabled", String(!d))), i && (i.disabled = !f, i.setAttribute("aria-disabled", String(!f)));
28
+ }
29
+ };
30
+ e && e.addEventListener("click", () => g("prev")), i && i.addEventListener("click", () => g("next"));
31
+ let v = !1;
32
+ o.addEventListener("scroll", () => {
33
+ v || (window.requestAnimationFrame(() => {
34
+ u(), v = !1;
35
+ }), v = !0);
36
+ }, { passive: !0 }), s.addEventListener("keydown", (t) => {
37
+ a === "vertical" ? t.key === "ArrowUp" ? (t.preventDefault(), e?.click()) : t.key === "ArrowDown" && (t.preventDefault(), i?.click()) : t.key === "ArrowLeft" ? (t.preventDefault(), e?.click()) : t.key === "ArrowRight" && (t.preventDefault(), i?.click());
38
+ }), new ResizeObserver(u).observe(o), u(), s.dataset.carouselInitialized = !0, s.dispatchEvent(new CustomEvent("basecoat:initialized"));
39
+ };
40
+ window.basecoat && window.basecoat.register("carousel", ".carousel:not([data-carousel-initialized])", m);
41
+ })();
@@ -0,0 +1,136 @@
1
+ (() => {
2
+ const THEMES = ["latte", "frappe", "macchiato", "mocha"];
3
+ const DARK_THEMES = ["frappe", "macchiato", "mocha"];
4
+ const ACCENTS = [
5
+ "rosewater",
6
+ "flamingo",
7
+ "pink",
8
+ "mauve",
9
+ "red",
10
+ "maroon",
11
+ "peach",
12
+ "yellow",
13
+ "green",
14
+ "teal",
15
+ "sky",
16
+ "sapphire",
17
+ "blue",
18
+ "lavender"
19
+ ];
20
+ function getThemePreviewColors(theme) {
21
+ if (!THEMES.includes(theme)) return {};
22
+ const colors = { background: `var(--ctp-${theme}-base)` };
23
+ ACCENTS.forEach((accent) => {
24
+ colors[accent] = `var(--ctp-${theme}-${accent})`;
25
+ });
26
+ return colors;
27
+ }
28
+ function setTheme(theme, accent) {
29
+ const root = document.documentElement;
30
+ THEMES.forEach((t) => root.classList.remove(`theme-${t}`));
31
+ ACCENTS.forEach((a) => root.classList.remove(`accent-${a}`));
32
+ root.classList.add(`theme-${theme}`);
33
+ root.classList.add(`accent-${accent}`);
34
+ if (DARK_THEMES.includes(theme)) {
35
+ root.classList.add("dark");
36
+ } else {
37
+ root.classList.remove("dark");
38
+ }
39
+ try {
40
+ localStorage.setItem("catppuccin-theme", theme);
41
+ localStorage.setItem("catppuccin-accent", accent);
42
+ } catch (e) {
43
+ }
44
+ }
45
+ function initTheme() {
46
+ try {
47
+ const savedTheme = localStorage.getItem("catppuccin-theme");
48
+ const savedAccent = localStorage.getItem("catppuccin-accent");
49
+ if (savedTheme && savedAccent) {
50
+ setTheme(savedTheme, savedAccent);
51
+ }
52
+ } catch (e) {
53
+ }
54
+ }
55
+ initTheme();
56
+ const init = (container) => {
57
+ const flavorGroup = container.querySelector(".theme-flavors");
58
+ const accentGrid = container.querySelector(".theme-accents");
59
+ const resetButton = container.querySelector(".theme-reset");
60
+ let currentFlavor = localStorage.getItem("catppuccin-theme") || "latte";
61
+ if (!THEMES.includes(currentFlavor)) currentFlavor = "latte";
62
+ if (flavorGroup) {
63
+ flavorGroup.innerHTML = "";
64
+ flavorGroup.className = "button-group w-full";
65
+ THEMES.forEach((t) => {
66
+ const btn = document.createElement("button");
67
+ btn.type = "button";
68
+ btn.className = "btn btn-sm capitalize flex-1";
69
+ btn.textContent = t;
70
+ btn.dataset.flavor = t;
71
+ flavorGroup.appendChild(btn);
72
+ });
73
+ }
74
+ const updateFlavorUI = () => {
75
+ if (!flavorGroup) return;
76
+ const buttons = flavorGroup.querySelectorAll("[data-flavor]");
77
+ buttons.forEach((btn) => {
78
+ if (btn.dataset.flavor === currentFlavor) {
79
+ btn.classList.remove("btn-outline", "btn-ghost");
80
+ btn.classList.add("btn-primary");
81
+ } else {
82
+ btn.classList.remove("btn-primary");
83
+ btn.classList.add("btn-ghost");
84
+ }
85
+ });
86
+ };
87
+ const renderAccents = () => {
88
+ if (!accentGrid) return;
89
+ accentGrid.innerHTML = "";
90
+ const colors = getThemePreviewColors(currentFlavor);
91
+ accentGrid.className = "theme-accents grid grid-cols-7 gap-3 place-items-center p-4 rounded-xl border border-border/50 mt-4 transition-colors duration-300";
92
+ accentGrid.style.backgroundColor = colors.background;
93
+ ACCENTS.forEach((acc) => {
94
+ const btn = document.createElement("button");
95
+ btn.type = "button";
96
+ btn.className = "size-6 rounded-full border border-border/20 shadow-sm transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring";
97
+ btn.title = acc;
98
+ btn.style.backgroundColor = colors[acc];
99
+ btn.dataset.tooltip = acc;
100
+ btn.dataset.side = "top";
101
+ btn.onclick = () => {
102
+ setTheme(currentFlavor, acc);
103
+ };
104
+ accentGrid.appendChild(btn);
105
+ });
106
+ };
107
+ if (flavorGroup) {
108
+ flavorGroup.addEventListener("click", (e) => {
109
+ const btn = e.target.closest("[data-flavor]");
110
+ if (!btn) return;
111
+ currentFlavor = btn.dataset.flavor;
112
+ updateFlavorUI();
113
+ renderAccents();
114
+ });
115
+ }
116
+ if (resetButton) {
117
+ resetButton.addEventListener("click", () => {
118
+ const root = document.documentElement;
119
+ THEMES.forEach((t) => root.classList.remove(`theme-${t}`));
120
+ ACCENTS.forEach((a) => root.classList.remove(`accent-${a}`));
121
+ localStorage.removeItem("catppuccin-theme");
122
+ localStorage.removeItem("catppuccin-accent");
123
+ if (DARK_THEMES.includes(currentFlavor)) {
124
+ root.classList.add("dark");
125
+ } else {
126
+ root.classList.remove("dark");
127
+ }
128
+ });
129
+ }
130
+ updateFlavorUI();
131
+ renderAccents();
132
+ };
133
+ if (window.basecoat) {
134
+ window.basecoat.register("catppuccin-theme-switcher", ".catppuccin-theme-switcher", init);
135
+ }
136
+ })();
@@ -0,0 +1,73 @@
1
+ (() => {
2
+ const l = ["latte", "frappe", "macchiato", "mocha"], d = ["frappe", "macchiato", "mocha"], i = [
3
+ "rosewater",
4
+ "flamingo",
5
+ "pink",
6
+ "mauve",
7
+ "red",
8
+ "maroon",
9
+ "peach",
10
+ "yellow",
11
+ "green",
12
+ "teal",
13
+ "sky",
14
+ "sapphire",
15
+ "blue",
16
+ "lavender"
17
+ ];
18
+ function f(c) {
19
+ if (!l.includes(c)) return {};
20
+ const t = { background: `var(--ctp-${c}-base)` };
21
+ return i.forEach((o) => {
22
+ t[o] = `var(--ctp-${c}-${o})`;
23
+ }), t;
24
+ }
25
+ function u(c, t) {
26
+ const o = document.documentElement;
27
+ l.forEach((s) => o.classList.remove(`theme-${s}`)), i.forEach((s) => o.classList.remove(`accent-${s}`)), o.classList.add(`theme-${c}`), o.classList.add(`accent-${t}`), d.includes(c) ? o.classList.add("dark") : o.classList.remove("dark");
28
+ try {
29
+ localStorage.setItem("catppuccin-theme", c), localStorage.setItem("catppuccin-accent", t);
30
+ } catch {
31
+ }
32
+ }
33
+ function h() {
34
+ try {
35
+ const c = localStorage.getItem("catppuccin-theme"), t = localStorage.getItem("catppuccin-accent");
36
+ c && t && u(c, t);
37
+ } catch {
38
+ }
39
+ }
40
+ h();
41
+ const v = (c) => {
42
+ const t = c.querySelector(".theme-flavors"), o = c.querySelector(".theme-accents"), s = c.querySelector(".theme-reset");
43
+ let n = localStorage.getItem("catppuccin-theme") || "latte";
44
+ l.includes(n) || (n = "latte"), t && (t.innerHTML = "", t.className = "button-group w-full", l.forEach((a) => {
45
+ const e = document.createElement("button");
46
+ e.type = "button", e.className = "btn btn-sm capitalize flex-1", e.textContent = a, e.dataset.flavor = a, t.appendChild(e);
47
+ }));
48
+ const m = () => {
49
+ if (!t) return;
50
+ t.querySelectorAll("[data-flavor]").forEach((e) => {
51
+ e.dataset.flavor === n ? (e.classList.remove("btn-outline", "btn-ghost"), e.classList.add("btn-primary")) : (e.classList.remove("btn-primary"), e.classList.add("btn-ghost"));
52
+ });
53
+ }, p = () => {
54
+ if (!o) return;
55
+ o.innerHTML = "";
56
+ const a = f(n);
57
+ o.className = "theme-accents grid grid-cols-7 gap-3 place-items-center p-4 rounded-xl border border-border/50 mt-4 transition-colors duration-300", o.style.backgroundColor = a.background, i.forEach((e) => {
58
+ const r = document.createElement("button");
59
+ r.type = "button", r.className = "size-6 rounded-full border border-border/20 shadow-sm transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring", r.title = e, r.style.backgroundColor = a[e], r.dataset.tooltip = e, r.dataset.side = "top", r.onclick = () => {
60
+ u(n, e);
61
+ }, o.appendChild(r);
62
+ });
63
+ };
64
+ t && t.addEventListener("click", (a) => {
65
+ const e = a.target.closest("[data-flavor]");
66
+ e && (n = e.dataset.flavor, m(), p());
67
+ }), s && s.addEventListener("click", () => {
68
+ const a = document.documentElement;
69
+ l.forEach((e) => a.classList.remove(`theme-${e}`)), i.forEach((e) => a.classList.remove(`accent-${e}`)), localStorage.removeItem("catppuccin-theme"), localStorage.removeItem("catppuccin-accent"), d.includes(n) ? a.classList.add("dark") : a.classList.remove("dark");
70
+ }), m(), p();
71
+ };
72
+ window.basecoat && window.basecoat.register("catppuccin-theme-switcher", ".catppuccin-theme-switcher", v);
73
+ })();
@@ -0,0 +1,132 @@
1
+ (() => {
2
+ const initCommand = (container) => {
3
+ const input = container.querySelector("header input");
4
+ const menu = container.querySelector('[role="menu"]');
5
+ if (!input || !menu) {
6
+ const missing = [];
7
+ if (!input) missing.push("input");
8
+ if (!menu) missing.push("menu");
9
+ console.error(`Command component initialization failed. Missing element(s): ${missing.join(", ")}`, container);
10
+ return;
11
+ }
12
+ const allMenuItems = Array.from(menu.querySelectorAll('[role="menuitem"]'));
13
+ const menuItems = allMenuItems.filter(
14
+ (item) => !item.hasAttribute("disabled") && item.getAttribute("aria-disabled") !== "true"
15
+ );
16
+ let visibleMenuItems = [...menuItems];
17
+ let activeIndex = -1;
18
+ const setActiveItem = (index) => {
19
+ if (activeIndex > -1 && menuItems[activeIndex]) {
20
+ menuItems[activeIndex].classList.remove("active");
21
+ }
22
+ activeIndex = index;
23
+ if (activeIndex > -1) {
24
+ const activeItem = menuItems[activeIndex];
25
+ activeItem.classList.add("active");
26
+ if (activeItem.id) {
27
+ input.setAttribute("aria-activedescendant", activeItem.id);
28
+ } else {
29
+ input.removeAttribute("aria-activedescendant");
30
+ }
31
+ } else {
32
+ input.removeAttribute("aria-activedescendant");
33
+ }
34
+ };
35
+ const filterMenuItems = () => {
36
+ const searchTerm = input.value.trim().toLowerCase();
37
+ setActiveItem(-1);
38
+ visibleMenuItems = [];
39
+ allMenuItems.forEach((item) => {
40
+ if (item.hasAttribute("data-force")) {
41
+ item.setAttribute("aria-hidden", "false");
42
+ if (menuItems.includes(item)) {
43
+ visibleMenuItems.push(item);
44
+ }
45
+ return;
46
+ }
47
+ const itemText = (item.dataset.filter || item.textContent).trim().toLowerCase();
48
+ const keywordList = (item.dataset.keywords || "").toLowerCase().split(/[\s,]+/).filter(Boolean);
49
+ const matchesKeyword = keywordList.some((keyword) => keyword.includes(searchTerm));
50
+ const matches = itemText.includes(searchTerm) || matchesKeyword;
51
+ item.setAttribute("aria-hidden", String(!matches));
52
+ if (matches && menuItems.includes(item)) {
53
+ visibleMenuItems.push(item);
54
+ }
55
+ });
56
+ if (visibleMenuItems.length > 0) {
57
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
58
+ visibleMenuItems[0].scrollIntoView({ block: "nearest" });
59
+ }
60
+ };
61
+ input.addEventListener("input", filterMenuItems);
62
+ const handleKeyNavigation = (event) => {
63
+ if (!["ArrowDown", "ArrowUp", "Enter", "Home", "End"].includes(event.key)) {
64
+ return;
65
+ }
66
+ if (event.key === "Enter") {
67
+ event.preventDefault();
68
+ if (activeIndex > -1) {
69
+ menuItems[activeIndex]?.click();
70
+ }
71
+ return;
72
+ }
73
+ if (visibleMenuItems.length === 0) return;
74
+ event.preventDefault();
75
+ const currentVisibleIndex = activeIndex > -1 ? visibleMenuItems.indexOf(menuItems[activeIndex]) : -1;
76
+ let nextVisibleIndex = currentVisibleIndex;
77
+ switch (event.key) {
78
+ case "ArrowDown":
79
+ if (currentVisibleIndex < visibleMenuItems.length - 1) {
80
+ nextVisibleIndex = currentVisibleIndex + 1;
81
+ }
82
+ break;
83
+ case "ArrowUp":
84
+ if (currentVisibleIndex > 0) {
85
+ nextVisibleIndex = currentVisibleIndex - 1;
86
+ } else if (currentVisibleIndex === -1) {
87
+ nextVisibleIndex = 0;
88
+ }
89
+ break;
90
+ case "Home":
91
+ nextVisibleIndex = 0;
92
+ break;
93
+ case "End":
94
+ nextVisibleIndex = visibleMenuItems.length - 1;
95
+ break;
96
+ }
97
+ if (nextVisibleIndex !== currentVisibleIndex) {
98
+ const newActiveItem = visibleMenuItems[nextVisibleIndex];
99
+ setActiveItem(menuItems.indexOf(newActiveItem));
100
+ newActiveItem.scrollIntoView({ block: "nearest", behavior: "smooth" });
101
+ }
102
+ };
103
+ menu.addEventListener("mousemove", (event) => {
104
+ const menuItem = event.target.closest('[role="menuitem"]');
105
+ if (menuItem && visibleMenuItems.includes(menuItem)) {
106
+ const index = menuItems.indexOf(menuItem);
107
+ if (index !== activeIndex) {
108
+ setActiveItem(index);
109
+ }
110
+ }
111
+ });
112
+ menu.addEventListener("click", (event) => {
113
+ const clickedItem = event.target.closest('[role="menuitem"]');
114
+ if (clickedItem && visibleMenuItems.includes(clickedItem)) {
115
+ const dialog = container.closest("dialog.command-dialog");
116
+ if (dialog && !clickedItem.hasAttribute("data-keep-command-open")) {
117
+ dialog.close();
118
+ }
119
+ }
120
+ });
121
+ input.addEventListener("keydown", handleKeyNavigation);
122
+ if (visibleMenuItems.length > 0) {
123
+ setActiveItem(menuItems.indexOf(visibleMenuItems[0]));
124
+ visibleMenuItems[0].scrollIntoView({ block: "nearest" });
125
+ }
126
+ container.dataset.commandInitialized = true;
127
+ container.dispatchEvent(new CustomEvent("basecoat:initialized"));
128
+ };
129
+ if (window.basecoat) {
130
+ window.basecoat.register("command", ".command:not([data-command-initialized])", initCommand);
131
+ }
132
+ })();
@@ -0,0 +1,76 @@
1
+ (() => {
2
+ const f = (r) => {
3
+ const o = r.querySelector("header input"), c = r.querySelector('[role="menu"]');
4
+ if (!o || !c) {
5
+ const t = [];
6
+ o || t.push("input"), c || t.push("menu"), console.error(`Command component initialization failed. Missing element(s): ${t.join(", ")}`, r);
7
+ return;
8
+ }
9
+ const u = Array.from(c.querySelectorAll('[role="menuitem"]')), s = u.filter(
10
+ (t) => !t.hasAttribute("disabled") && t.getAttribute("aria-disabled") !== "true"
11
+ );
12
+ let i = [...s], a = -1;
13
+ const d = (t) => {
14
+ if (a > -1 && s[a] && s[a].classList.remove("active"), a = t, a > -1) {
15
+ const e = s[a];
16
+ e.classList.add("active"), e.id ? o.setAttribute("aria-activedescendant", e.id) : o.removeAttribute("aria-activedescendant");
17
+ } else
18
+ o.removeAttribute("aria-activedescendant");
19
+ }, b = () => {
20
+ const t = o.value.trim().toLowerCase();
21
+ d(-1), i = [], u.forEach((e) => {
22
+ if (e.hasAttribute("data-force")) {
23
+ e.setAttribute("aria-hidden", "false"), s.includes(e) && i.push(e);
24
+ return;
25
+ }
26
+ const n = (e.dataset.filter || e.textContent).trim().toLowerCase(), w = (e.dataset.keywords || "").toLowerCase().split(/[\s,]+/).filter(Boolean).some((v) => v.includes(t)), m = n.includes(t) || w;
27
+ e.setAttribute("aria-hidden", String(!m)), m && s.includes(e) && i.push(e);
28
+ }), i.length > 0 && (d(s.indexOf(i[0])), i[0].scrollIntoView({ block: "nearest" }));
29
+ };
30
+ o.addEventListener("input", b);
31
+ const h = (t) => {
32
+ if (!["ArrowDown", "ArrowUp", "Enter", "Home", "End"].includes(t.key))
33
+ return;
34
+ if (t.key === "Enter") {
35
+ t.preventDefault(), a > -1 && s[a]?.click();
36
+ return;
37
+ }
38
+ if (i.length === 0) return;
39
+ t.preventDefault();
40
+ const e = a > -1 ? i.indexOf(s[a]) : -1;
41
+ let n = e;
42
+ switch (t.key) {
43
+ case "ArrowDown":
44
+ e < i.length - 1 && (n = e + 1);
45
+ break;
46
+ case "ArrowUp":
47
+ e > 0 ? n = e - 1 : e === -1 && (n = 0);
48
+ break;
49
+ case "Home":
50
+ n = 0;
51
+ break;
52
+ case "End":
53
+ n = i.length - 1;
54
+ break;
55
+ }
56
+ if (n !== e) {
57
+ const l = i[n];
58
+ d(s.indexOf(l)), l.scrollIntoView({ block: "nearest", behavior: "smooth" });
59
+ }
60
+ };
61
+ c.addEventListener("mousemove", (t) => {
62
+ const e = t.target.closest('[role="menuitem"]');
63
+ if (e && i.includes(e)) {
64
+ const n = s.indexOf(e);
65
+ n !== a && d(n);
66
+ }
67
+ }), c.addEventListener("click", (t) => {
68
+ const e = t.target.closest('[role="menuitem"]');
69
+ if (e && i.includes(e)) {
70
+ const n = r.closest("dialog.command-dialog");
71
+ n && !e.hasAttribute("data-keep-command-open") && n.close();
72
+ }
73
+ }), o.addEventListener("keydown", h), i.length > 0 && (d(s.indexOf(i[0])), i[0].scrollIntoView({ block: "nearest" })), r.dataset.commandInitialized = !0, r.dispatchEvent(new CustomEvent("basecoat:initialized"));
74
+ };
75
+ window.basecoat && window.basecoat.register("command", ".command:not([data-command-initialized])", f);
76
+ })();