wpheadless-lib 1.1.10 → 1.1.11

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 (119) hide show
  1. package/dist/api/categories.d.ts +1 -1
  2. package/dist/api/categories.js +18 -2
  3. package/dist/api/index.d.ts +7 -6
  4. package/dist/api/index.js +7 -6
  5. package/dist/api/mappers.d.ts +1 -1
  6. package/dist/api/mappers.js +1 -1
  7. package/dist/api/menus.d.ts +18 -0
  8. package/dist/api/menus.js +39 -0
  9. package/dist/api/posts.js +30 -2
  10. package/dist/api/translations.js +7 -1
  11. package/dist/api/wpClient.d.ts +5 -8
  12. package/dist/api/wpClient.js +14 -0
  13. package/dist/app/config.d.ts +2 -1
  14. package/dist/app/config.js +4 -0
  15. package/dist/app/globals.css +33 -121
  16. package/dist/base/category/index.d.ts +3 -3
  17. package/dist/base/category/index.js +9 -8
  18. package/dist/base/category/pagination.d.ts +2 -2
  19. package/dist/base/category/pagination.js +12 -10
  20. package/dist/base/home/index.js +1 -1
  21. package/dist/base/home/pagination.js +3 -3
  22. package/dist/base/index.d.ts +7 -7
  23. package/dist/base/index.js +7 -7
  24. package/dist/base/layout/RootLayoutBase.d.ts +6 -7
  25. package/dist/base/layout/RootLayoutBase.js +4 -4
  26. package/dist/base/layout/RootLayoutBase.module.css +10 -0
  27. package/dist/base/legal/index.d.ts +4 -4
  28. package/dist/base/legal/index.js +36 -24
  29. package/dist/base/post/index.d.ts +1 -1
  30. package/dist/base/post/index.js +15 -12
  31. package/dist/components/Breadcrumbs/index.js +4 -4
  32. package/dist/components/JsonLd.d.ts +5 -0
  33. package/dist/components/JsonLd.js +9 -0
  34. package/dist/components/Paginator/index.d.ts +1 -1
  35. package/dist/components/Paginator/index.js +5 -5
  36. package/dist/components/PostCard/index.d.ts +3 -2
  37. package/dist/components/PostCard/index.js +8 -6
  38. package/dist/components/PostCard/index.module.css +7 -7
  39. package/dist/components/PostCard/index.types.d.ts +2 -1
  40. package/dist/components/PostCard/index.utils.d.ts +5 -5
  41. package/dist/components/PostCard/index.utils.js +8 -6
  42. package/dist/components/index.d.ts +6 -5
  43. package/dist/components/index.js +6 -5
  44. package/dist/components/layout/Footer/index.d.ts +5 -5
  45. package/dist/components/layout/Footer/index.js +11 -22
  46. package/dist/components/layout/Footer/index.module.css +59 -9
  47. package/dist/components/layout/Header/HeaderClient.d.ts +1 -1
  48. package/dist/components/layout/Header/HeaderClient.js +22 -2
  49. package/dist/components/layout/Header/index.d.ts +5 -5
  50. package/dist/components/layout/Header/index.js +10 -29
  51. package/dist/components/layout/Header/index.module.css +77 -16
  52. package/dist/components/ui/alert.d.ts +8 -0
  53. package/dist/components/ui/alert.js +12 -0
  54. package/dist/components/ui/alert.module.css +26 -0
  55. package/dist/components/ui/badge.d.ts +3 -0
  56. package/dist/components/ui/badge.js +9 -0
  57. package/dist/components/ui/badge.module.css +23 -0
  58. package/dist/components/ui/breadcrumb.d.ts +8 -0
  59. package/dist/components/ui/breadcrumb.js +22 -0
  60. package/dist/components/ui/breadcrumb.module.css +37 -0
  61. package/dist/components/ui/button.d.ts +7 -0
  62. package/dist/components/ui/button.js +16 -0
  63. package/dist/components/ui/button.module.css +72 -0
  64. package/dist/components/ui/card.d.ts +11 -0
  65. package/dist/components/ui/card.js +16 -0
  66. package/dist/components/ui/card.module.css +37 -0
  67. package/dist/components/ui/cn.d.ts +1 -0
  68. package/dist/components/ui/cn.js +3 -0
  69. package/dist/components/ui/index.d.ts +6 -0
  70. package/dist/components/ui/index.js +6 -0
  71. package/dist/components/ui/pagination.d.ts +14 -0
  72. package/dist/components/ui/pagination.js +25 -0
  73. package/dist/components/ui/pagination.module.css +62 -0
  74. package/dist/index.d.ts +6 -6
  75. package/dist/index.js +6 -6
  76. package/dist/plugins/index.d.ts +1 -1
  77. package/dist/plugins/index.js +1 -1
  78. package/dist/plugins/yoast/index.js +10 -7
  79. package/dist/utils/hreflang.d.ts +4 -7
  80. package/dist/utils/hreflang.js +11 -6
  81. package/dist/utils/html.d.ts +2 -0
  82. package/dist/utils/html.js +25 -0
  83. package/dist/utils/index.d.ts +7 -6
  84. package/dist/utils/index.js +7 -6
  85. package/dist/utils/language.d.ts +37 -0
  86. package/dist/utils/language.js +75 -0
  87. package/dist/utils/seo.d.ts +1 -6
  88. package/dist/utils/seo.js +9 -5
  89. package/dist/utils/sitemap.d.ts +1 -1
  90. package/dist/utils/sitemap.js +107 -56
  91. package/dist/views/CategoryListView/index.d.ts +1 -1
  92. package/dist/views/CategoryListView/index.js +6 -6
  93. package/dist/views/CategoryListView/index.utils.d.ts +1 -1
  94. package/dist/views/CategoryListView/index.utils.js +1 -1
  95. package/dist/views/CategoryPaginationView/index.d.ts +1 -1
  96. package/dist/views/CategoryPaginationView/index.js +6 -6
  97. package/dist/views/CategoryPaginationView/index.utils.d.ts +1 -1
  98. package/dist/views/CategoryPaginationView/index.utils.js +1 -1
  99. package/dist/views/HomePaginationView/index.d.ts +1 -1
  100. package/dist/views/HomePaginationView/index.js +5 -4
  101. package/dist/views/HomePaginationView/index.utils.d.ts +1 -1
  102. package/dist/views/HomePaginationView/index.utils.js +1 -1
  103. package/dist/views/HomeView/index.d.ts +1 -1
  104. package/dist/views/HomeView/index.js +13 -12
  105. package/dist/views/HomeView/index.module.css +51 -8
  106. package/dist/views/HomeView/index.utils.d.ts +1 -1
  107. package/dist/views/HomeView/index.utils.js +2 -2
  108. package/dist/views/LegalPageView/index.d.ts +2 -1
  109. package/dist/views/LegalPageView/index.js +5 -5
  110. package/dist/views/LegalPageView/index.module.css +3 -3
  111. package/dist/views/LegalPageView/index.utils.js +1 -1
  112. package/dist/views/PostView/index.d.ts +3 -2
  113. package/dist/views/PostView/index.js +9 -7
  114. package/dist/views/PostView/index.module.css +46 -13
  115. package/dist/views/PostView/index.utils.d.ts +3 -3
  116. package/dist/views/PostView/index.utils.js +2 -2
  117. package/dist/views/index.d.ts +6 -6
  118. package/dist/views/index.js +6 -6
  119. package/package.json +47 -10
@@ -1,23 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import Link from "next/link";
3
- import { createMenuEndpoints, createAuth } from "wpjsapi-lib";
4
- import { convertWpUrl, getTranslator } from "../../../utils";
3
+ import { getTranslator } from "../../../utils/index.js";
4
+ import { fetchMenuLinks } from "../../../api/menus.js";
5
5
  import styles from "./index.module.css";
6
6
  export const dynamic = "force-static";
7
7
  export const revalidate = 3600;
8
8
  export default async function Footer({ menuId, wpApiUrl, wpUsername, wpAppPassword, siteName, locale, logo, }) {
9
- const auth = createAuth({
10
- method: "basic",
11
- credentials: {
12
- username: wpUsername,
13
- password: wpAppPassword,
14
- },
15
- });
16
- const menusApi = createMenuEndpoints({
17
- baseUrl: wpApiUrl,
18
- auth,
19
- });
20
- let menuItems = [];
9
+ let menuLinks = [];
21
10
  const t = getTranslator(locale);
22
11
  const logoData = logo?.src ? logo : null;
23
12
  const logoAlt = logoData?.alt || siteName;
@@ -28,17 +17,17 @@ export default async function Footer({ menuId, wpApiUrl, wpUsername, wpAppPasswo
28
17
  }
29
18
  : undefined;
30
19
  try {
31
- const parsedMenuId = parseInt(menuId);
32
- const itemsResponse = await menusApi.items.list({
33
- menus: [parsedMenuId],
34
- per_page: 100,
35
- orderby: "menu_order",
36
- order: "asc",
20
+ menuLinks = await fetchMenuLinks({
21
+ baseApiUrl: wpApiUrl || "",
22
+ menuId,
23
+ username: wpUsername,
24
+ appPassword: wpAppPassword,
37
25
  });
38
- menuItems = itemsResponse.items;
39
26
  }
40
27
  catch (e) {
41
28
  console.error("Error obteniendo menú footer:", e);
42
29
  }
43
- return (_jsx("footer", { className: styles.footer, children: _jsx("div", { className: "container", children: _jsxs("div", { className: styles.wrapper, children: [_jsxs("div", { className: styles.grid, children: [_jsxs("div", { children: [_jsx("h3", { className: styles.siteName, children: logoData ? (_jsx("img", { src: logoData.src, alt: logoAlt, className: styles.logoImage, width: logoData.width, height: logoData.height, style: logoStyle })) : (siteName) }), _jsx("p", { className: `${styles.muted} text-muted`, children: t("footer.tagline") })] }), menuItems.length > 0 && (_jsxs("nav", { "aria-label": t("footer.navAria"), className: styles.nav, children: [_jsx("h4", { className: styles.navTitle, children: t("footer.navTitle") }), _jsx("ul", { className: styles.list, children: menuItems.map((item) => (_jsx("li", { children: _jsx(Link, { href: convertWpUrl(item.url, wpApiUrl), className: "footer-link", children: item.title.rendered }) }, item.id))) })] }))] }), _jsxs("div", { className: styles.bottomBar, children: [_jsxs("span", { children: ["\u00A9 ", new Date().getFullYear(), " ", siteName] }), _jsx("span", { children: t("footer.noCookies") })] })] }) }) }));
30
+ return (_jsx("footer", { className: styles.footer, children: _jsx("div", { className: styles.container, children: _jsxs("div", { className: styles.wrapper, children: [_jsxs("div", { className: styles.grid, children: [_jsxs("div", { children: [_jsx("div", { className: styles.siteName, children: logoData ? (_jsx("img", { src: logoData.src, alt: logoAlt, className: styles.logoImage, width: logoData.width, height: logoData.height, style: logoStyle })) : (siteName) }), _jsx("p", { className: `${styles.muted} text-muted`, children: t("footer.tagline") })] }), menuLinks.length > 0 && (_jsxs("nav", { "aria-label": t("footer.navAria"), className: styles.nav, children: [_jsx("h4", { className: styles.navTitle, children: t("footer.navTitle") }), _jsx("ul", { className: styles.list, children: menuLinks.map((item) => (_jsx("li", { children: _jsx(Link, { href: item.href, className: styles.footerLink, target: item.target || undefined, rel: item.target === "_blank"
31
+ ? "noopener noreferrer"
32
+ : undefined, children: item.label }) }, item.id))) })] }))] }), _jsxs("div", { className: styles.bottomBar, children: [_jsxs("span", { children: ["\u00A9 ", new Date().getFullYear(), " ", siteName] }), _jsx("span", { children: t("footer.noCookies") })] })] }) }) }));
44
33
  }
@@ -1,18 +1,28 @@
1
1
  .footer {
2
- background: var(--background-alt);
3
- border-top: 1px solid var(--border);
2
+ background:
3
+ linear-gradient(180deg, transparent, color-mix(in srgb, var(--background-alt) 82%, transparent) 28%),
4
+ var(--background-alt);
5
+ border-top: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
4
6
  margin-top: var(--spacing-xl);
5
7
  }
6
8
 
9
+ .container {
10
+ width: 100%;
11
+ max-width: var(--container-width);
12
+ margin: 0 auto;
13
+ padding-inline: clamp(1rem, 4vw, 2rem);
14
+ }
15
+
7
16
  .wrapper {
8
- padding: var(--spacing-xl) 0 var(--spacing-lg);
17
+ padding: clamp(2.25rem, 5vw, 3.5rem) 0 var(--spacing-lg);
9
18
  }
10
19
 
11
20
  .grid {
12
21
  display: grid;
13
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
14
- gap: var(--spacing-lg);
15
- margin-bottom: var(--spacing-lg);
22
+ grid-template-columns: minmax(0, 1.4fr) minmax(220px, 0.6fr);
23
+ gap: clamp(2rem, 7vw, 5rem);
24
+ align-items: start;
25
+ margin-bottom: clamp(2rem, 4vw, 3rem);
16
26
  }
17
27
 
18
28
  .siteName {
@@ -25,18 +35,22 @@
25
35
  }
26
36
 
27
37
  .logoImage {
28
- height: 64px;
38
+ height: 56px;
29
39
  width: auto;
30
40
  display: block;
31
41
  object-fit: contain;
32
42
  }
33
43
 
34
44
  .muted {
35
- font-size: 0.875rem;
45
+ max-width: 36rem;
46
+ font-size: 0.95rem;
47
+ line-height: 1.7;
36
48
  }
37
49
 
38
50
  .nav {
39
51
  display: block;
52
+ justify-self: end;
53
+ min-width: min(100%, 240px);
40
54
  }
41
55
 
42
56
  .navTitle {
@@ -52,11 +66,31 @@
52
66
  list-style: none;
53
67
  display: flex;
54
68
  flex-direction: column;
55
- gap: 0.5rem;
69
+ gap: 0.35rem;
56
70
  margin: 0;
57
71
  padding: 0;
58
72
  }
59
73
 
74
+ .footerLink {
75
+ display: inline-flex;
76
+ width: 100%;
77
+ align-items: center;
78
+ border-radius: 0.65rem;
79
+ padding: 0.45rem 0.65rem;
80
+ color: var(--foreground-light);
81
+ font-size: 0.92rem;
82
+ font-weight: 550;
83
+ text-decoration: none;
84
+ transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
85
+ }
86
+
87
+ .footerLink:hover,
88
+ .footerLink:focus-visible {
89
+ background: color-mix(in srgb, var(--primary) 10%, transparent);
90
+ color: var(--primary);
91
+ transform: translateX(2px);
92
+ }
93
+
60
94
  .bottomBar {
61
95
  display: flex;
62
96
  justify-content: space-between;
@@ -68,3 +102,19 @@
68
102
  gap: var(--spacing-md);
69
103
  flex-wrap: wrap;
70
104
  }
105
+
106
+ @media (max-width: 760px) {
107
+ .grid {
108
+ grid-template-columns: 1fr;
109
+ gap: 1.75rem;
110
+ }
111
+
112
+ .nav {
113
+ justify-self: stretch;
114
+ }
115
+
116
+ .bottomBar {
117
+ align-items: flex-start;
118
+ flex-direction: column;
119
+ }
120
+ }
@@ -1,4 +1,4 @@
1
- import type { LogoProps } from "../types";
1
+ import type { LogoProps } from "../types.js";
2
2
  type MenuLink = {
3
3
  id: number;
4
4
  href: string;
@@ -1,11 +1,14 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Link from "next/link";
4
- import { useEffect, useState } from "react";
4
+ import { useEffect, useRef, useState } from "react";
5
5
  import styles from "./index.module.css";
6
+ import { Button } from "../../ui/index.js";
6
7
  export default function HeaderClient({ menuLinks, siteName, homeHref, labels, logo, }) {
7
8
  const [isMenuOpen, setIsMenuOpen] = useState(false);
8
9
  const [isMobileView, setIsMobileView] = useState(false);
10
+ const menuButtonRef = useRef(null);
11
+ const navRef = useRef(null);
9
12
  useEffect(() => {
10
13
  const handleResize = () => {
11
14
  const isMobile = window.innerWidth < 900;
@@ -18,6 +21,23 @@ export default function HeaderClient({ menuLinks, siteName, homeHref, labels, lo
18
21
  window.addEventListener("resize", handleResize);
19
22
  return () => window.removeEventListener("resize", handleResize);
20
23
  }, []);
24
+ useEffect(() => {
25
+ if (!isMenuOpen)
26
+ return;
27
+ const handleKeyDown = (event) => {
28
+ if (event.key !== "Escape")
29
+ return;
30
+ setIsMenuOpen(false);
31
+ menuButtonRef.current?.focus();
32
+ };
33
+ window.addEventListener("keydown", handleKeyDown);
34
+ return () => window.removeEventListener("keydown", handleKeyDown);
35
+ }, [isMenuOpen]);
36
+ useEffect(() => {
37
+ if (!isMenuOpen || !isMobileView)
38
+ return;
39
+ navRef.current?.querySelector("a")?.focus();
40
+ }, [isMenuOpen, isMobileView]);
21
41
  const toggleMenu = () => setIsMenuOpen((prev) => !prev);
22
42
  const handleLinkClick = () => setIsMenuOpen(false);
23
43
  const menuLabel = isMenuOpen ? labels.closeMenu : labels.openMenu;
@@ -29,7 +49,7 @@ export default function HeaderClient({ menuLinks, siteName, homeHref, labels, lo
29
49
  ...(logoData.width ? { width: logoData.width } : {}),
30
50
  }
31
51
  : undefined;
32
- return (_jsxs("div", { className: styles.inner, children: [_jsx(Link, { href: homeHref, className: styles.logo, children: logoData ? (_jsx("img", { src: logoData.src, alt: logoAlt, className: styles.logoImage, width: logoData.width, height: logoData.height, style: logoStyle })) : (siteName) }), menuLinks.length > 0 && (_jsxs("div", { className: styles.navWrapper, children: [_jsxs("button", { type: "button", className: styles.menuButton, "aria-expanded": isMenuOpen, "aria-controls": "primary-navigation", "aria-label": menuLabel, onClick: toggleMenu, children: [_jsxs("span", { className: styles.menuIcon, "aria-hidden": "true", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }), _jsx("span", { className: styles.menuText, children: menuLabel })] }), _jsx("nav", { id: "primary-navigation", "aria-label": labels.navAria, className: `${styles.nav} ${isMenuOpen ? styles.navOpen : ""}`, "aria-hidden": !isMenuOpen && isMobileView, hidden: !isMenuOpen && isMobileView, children: _jsx("ul", { className: styles.list, children: menuLinks.map((item) => (_jsx("li", { children: _jsx(Link, { href: item.href, className: "header-link", onClick: handleLinkClick, target: item.target || undefined, rel: item.target === "_blank"
52
+ return (_jsxs("div", { className: styles.inner, children: [_jsx(Link, { href: homeHref, className: styles.logo, children: logoData ? (_jsx("img", { src: logoData.src, alt: logoAlt, className: styles.logoImage, width: logoData.width, height: logoData.height, style: logoStyle })) : (siteName) }), menuLinks.length > 0 && (_jsxs("div", { className: styles.navWrapper, children: [_jsxs(Button, { type: "button", variant: "ghost", className: styles.menuButton, ref: menuButtonRef, "aria-expanded": isMenuOpen, "aria-controls": "primary-navigation", "aria-label": menuLabel, onClick: toggleMenu, children: [_jsxs("span", { className: styles.menuIcon, "aria-hidden": "true", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }), _jsx("span", { className: styles.menuText, children: menuLabel })] }), _jsx("nav", { id: "primary-navigation", ref: navRef, "aria-label": labels.navAria, className: `${styles.nav} ${isMenuOpen ? styles.navOpen : ""}`, "aria-hidden": !isMenuOpen && isMobileView, hidden: !isMenuOpen && isMobileView, children: _jsx("ul", { className: styles.list, children: menuLinks.map((item) => (_jsx("li", { children: _jsx(Link, { href: item.href, className: styles.navLink, onClick: handleLinkClick, tabIndex: !isMenuOpen && isMobileView ? -1 : undefined, target: item.target || undefined, rel: item.target === "_blank"
33
53
  ? "noopener noreferrer"
34
54
  : undefined, children: item.label }) }, item.id))) }) })] }))] }));
35
55
  }
@@ -1,11 +1,11 @@
1
- import type { LogoProps } from "../types";
1
+ import type { LogoProps } from "../types.js";
2
2
  export declare const dynamic = "force-static";
3
3
  export declare const revalidate = 3600;
4
4
  type HeaderProps = {
5
- menuId: string;
6
- wpApiUrl: string;
7
- wpUsername: string;
8
- wpAppPassword: string;
5
+ menuId?: string;
6
+ wpApiUrl?: string;
7
+ wpUsername?: string;
8
+ wpAppPassword?: string;
9
9
  siteName: string;
10
10
  homeHref?: string;
11
11
  locale?: string;
@@ -1,47 +1,28 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createMenuEndpoints, createAuth } from "wpjsapi-lib";
3
- import { convertWpUrl, getTranslator } from "../../../utils";
4
- import HeaderClient from "./HeaderClient";
2
+ import { getTranslator } from "../../../utils/index.js";
3
+ import { fetchMenuLinks } from "../../../api/menus.js";
4
+ import HeaderClient from "./HeaderClient.js";
5
5
  import styles from "./index.module.css";
6
6
  export const dynamic = "force-static";
7
7
  export const revalidate = 3600;
8
8
  export default async function Header({ menuId, wpApiUrl, wpUsername, wpAppPassword, siteName, homeHref = "/", locale, logo, }) {
9
9
  const t = getTranslator(locale);
10
- const auth = createAuth({
11
- method: "basic",
12
- credentials: {
13
- username: wpUsername,
14
- password: wpAppPassword,
15
- },
16
- });
17
- const menusApi = createMenuEndpoints({
18
- baseUrl: wpApiUrl,
19
- auth,
20
- });
21
- let menuItems = [];
10
+ let menuLinks = [];
22
11
  try {
23
- const parsedMenuId = parseInt(menuId);
24
- const itemsResponse = await menusApi.items.list({
25
- menus: [parsedMenuId],
26
- per_page: 100,
27
- orderby: "menu_order",
28
- order: "asc",
12
+ menuLinks = await fetchMenuLinks({
13
+ baseApiUrl: wpApiUrl || "",
14
+ menuId,
15
+ username: wpUsername,
16
+ appPassword: wpAppPassword,
29
17
  });
30
- menuItems = itemsResponse.items;
31
18
  }
32
19
  catch (e) {
33
20
  console.error("Error obteniendo menú:", e);
34
21
  }
35
- const menuLinks = menuItems.map((item) => ({
36
- id: item.id,
37
- href: convertWpUrl(item.url, wpApiUrl),
38
- label: item.title.rendered,
39
- target: item.target || undefined,
40
- }));
41
22
  const labels = {
42
23
  navAria: t("header.navAria"),
43
24
  openMenu: t("header.openMenu"),
44
25
  closeMenu: t("header.closeMenu"),
45
26
  };
46
- return (_jsx("header", { className: styles.header, children: _jsx("div", { className: "container", children: _jsx(HeaderClient, { menuLinks: menuLinks, siteName: siteName, homeHref: homeHref, labels: labels, logo: logo }) }) }));
27
+ return (_jsx("header", { className: styles.header, children: _jsx("div", { className: styles.container, children: _jsx(HeaderClient, { menuLinks: menuLinks, siteName: siteName, homeHref: homeHref, labels: labels, logo: logo }) }) }));
47
28
  }
@@ -3,18 +3,25 @@
3
3
  position: sticky;
4
4
  top: 0;
5
5
  z-index: 100;
6
- border-bottom: 1px solid var(--border);
6
+ border-bottom: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
7
7
  backdrop-filter: blur(20px);
8
- background: var(--card-bg);
9
- box-shadow: 0 1px 3px var(--shadow);
8
+ background: color-mix(in srgb, var(--card-bg) 92%, transparent);
9
+ box-shadow: 0 1px 0 color-mix(in srgb, var(--shadow) 45%, transparent);
10
+ }
11
+
12
+ .container {
13
+ width: 100%;
14
+ max-width: var(--container-width);
15
+ margin: 0 auto;
16
+ padding-inline: clamp(1rem, 4vw, 2rem);
10
17
  }
11
18
 
12
19
  .inner {
13
20
  display: flex;
14
21
  align-items: center;
15
22
  justify-content: space-between;
16
- padding: 1.25rem 0;
17
- gap: 3rem;
23
+ padding: 0.75rem 0;
24
+ gap: clamp(1rem, 4vw, 3rem);
18
25
  position: relative;
19
26
  min-height: var(--header-height);
20
27
  }
@@ -29,10 +36,12 @@
29
36
  font-family: var(--font-display);
30
37
  letter-spacing: -0.02em;
31
38
  text-decoration: none;
39
+ border-radius: 0.75rem;
40
+ flex: 0 0 auto;
32
41
  }
33
42
 
34
43
  .logoImage {
35
- height: 64px;
44
+ height: 56px;
36
45
  width: auto;
37
46
  display: block;
38
47
  object-fit: contain;
@@ -42,15 +51,19 @@
42
51
  flex: 1;
43
52
  display: flex;
44
53
  justify-content: flex-end;
54
+ min-width: 0;
45
55
  }
46
56
 
47
57
  .list {
48
58
  display: flex;
49
- gap: 2.5rem;
59
+ gap: 0.1rem;
50
60
  list-style: none;
51
61
  align-items: center;
52
62
  margin: 0;
53
63
  padding: 0;
64
+ max-width: 100%;
65
+ padding: 0.25rem;
66
+ box-shadow: none;
54
67
  }
55
68
 
56
69
  .navWrapper {
@@ -59,15 +72,16 @@
59
72
  gap: 1.5rem;
60
73
  flex: 1;
61
74
  justify-content: flex-end;
75
+ min-width: 0;
62
76
  }
63
77
 
64
78
  .menuButton {
65
- display: none;
79
+ display: none !important;
66
80
  align-items: center;
67
81
  gap: 0.5rem;
68
82
  padding: 0.6rem 0.75rem;
69
83
  border-radius: 10px;
70
- border: 1px solid var(--border);
84
+ border: 0;
71
85
  background: var(--background);
72
86
  color: var(--foreground);
73
87
  font-weight: 600;
@@ -77,8 +91,39 @@
77
91
  z-index: 120;
78
92
  }
79
93
 
94
+ .navLink {
95
+ display: inline-flex;
96
+ min-height: 2.25rem;
97
+ align-items: center;
98
+ justify-content: center;
99
+ border-radius: 999px;
100
+ padding: 0.4rem 0.62rem;
101
+ color: var(--foreground);
102
+ font-size: 0.92rem;
103
+ font-weight: 650;
104
+ line-height: 1.12;
105
+ max-width: 9.75rem;
106
+ text-align: center;
107
+ text-decoration: none;
108
+ transition:
109
+ color 0.2s ease,
110
+ background-color 0.2s ease,
111
+ box-shadow 0.2s ease;
112
+ white-space: normal;
113
+ overflow-wrap: anywhere;
114
+ }
115
+
116
+ .navLink:hover {
117
+ color: var(--primary);
118
+ }
119
+
120
+ .navLink:focus-visible {
121
+ color: var(--primary);
122
+ background: color-mix(in srgb, var(--primary) 8%, transparent);
123
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary) 28%, transparent);
124
+ }
125
+
80
126
  .menuButton:hover {
81
- border-color: var(--primary);
82
127
  color: var(--primary);
83
128
  }
84
129
 
@@ -96,7 +141,9 @@
96
141
  height: 2px;
97
142
  background: currentColor;
98
143
  border-radius: 999px;
99
- transition: transform 0.3s ease, opacity 0.3s ease;
144
+ transition:
145
+ transform 0.3s ease,
146
+ opacity 0.3s ease;
100
147
  }
101
148
 
102
149
  .menuIcon span:nth-child(1) {
@@ -148,13 +195,15 @@
148
195
  bottom: 0;
149
196
  height: calc(100vh - var(--header-height));
150
197
  padding: 1.5rem 1.25rem 2.5rem;
151
- background: var(--card-bg);
198
+ background: color-mix(in srgb, var(--card-bg) 97%, transparent);
152
199
  display: block;
153
200
  overflow: hidden;
154
201
  opacity: 0;
155
202
  pointer-events: none;
156
203
  transform: translateY(-8px);
157
- transition: opacity 0.25s ease, transform 0.25s ease;
204
+ transition:
205
+ opacity 0.25s ease,
206
+ transform 0.25s ease;
158
207
  z-index: 90;
159
208
  }
160
209
 
@@ -168,11 +217,23 @@
168
217
  .list {
169
218
  flex-direction: column;
170
219
  align-items: flex-start;
171
- gap: 1rem;
172
- padding: 1rem 0 1.25rem;
220
+ gap: 0.15rem;
221
+ width: min(100%, 440px);
222
+ border-radius: 1rem;
223
+ padding: 0.35rem;
224
+ box-shadow: none;
173
225
  }
174
226
 
175
227
  .menuButton {
176
- display: inline-flex;
228
+ display: inline-flex !important;
229
+ }
230
+
231
+ .navLink {
232
+ width: 100%;
233
+ justify-content: flex-start;
234
+ min-height: 2.45rem;
235
+ max-width: none;
236
+ padding: 0.62rem 0.75rem;
237
+ text-align: left;
177
238
  }
178
239
  }
@@ -0,0 +1,8 @@
1
+ import type { ComponentPropsWithoutRef } from "react";
2
+ type AlertProps = ComponentPropsWithoutRef<"div"> & {
3
+ variant?: "default" | "destructive";
4
+ };
5
+ export declare function Alert({ className, variant, ...props }: AlertProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function AlertTitle({ className, ...props }: ComponentPropsWithoutRef<"div">): import("react/jsx-runtime").JSX.Element;
7
+ export declare function AlertDescription({ className, ...props }: ComponentPropsWithoutRef<"div">): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "./cn.js";
3
+ import styles from "./alert.module.css";
4
+ export function Alert({ className, variant = "default", ...props }) {
5
+ return (_jsx("div", { "data-slot": "alert", role: "alert", className: cn(styles.alert, variant === "destructive" && styles.destructive, className), ...props }));
6
+ }
7
+ export function AlertTitle({ className, ...props }) {
8
+ return (_jsx("div", { "data-slot": "alert-title", className: cn(styles.title, className), ...props }));
9
+ }
10
+ export function AlertDescription({ className, ...props }) {
11
+ return (_jsx("div", { "data-slot": "alert-description", className: cn(styles.description, className), ...props }));
12
+ }
@@ -0,0 +1,26 @@
1
+ .alert {
2
+ position: relative;
3
+ display: grid;
4
+ width: 100%;
5
+ gap: 0.25rem;
6
+ border: 1px solid var(--border);
7
+ border-radius: 0.5rem;
8
+ background: var(--card-bg);
9
+ color: var(--foreground);
10
+ padding: 0.5rem 0.75rem;
11
+ font-size: 0.875rem;
12
+ }
13
+
14
+ .destructive {
15
+ border-color: color-mix(in srgb, var(--destructive) 40%, var(--border));
16
+ color: var(--destructive);
17
+ }
18
+
19
+ .title {
20
+ font-weight: 600;
21
+ }
22
+
23
+ .description {
24
+ color: var(--foreground-light);
25
+ font-size: 0.875rem;
26
+ }
@@ -0,0 +1,3 @@
1
+ import type { ComponentPropsWithoutRef } from "react";
2
+ export declare function badgeClassName(className?: string): string;
3
+ export declare function Badge({ className, ...props }: ComponentPropsWithoutRef<"span">): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "./cn.js";
3
+ import styles from "./badge.module.css";
4
+ export function badgeClassName(className) {
5
+ return cn(styles.badge, className);
6
+ }
7
+ export function Badge({ className, ...props }) {
8
+ return _jsx("span", { "data-slot": "badge", className: badgeClassName(className), ...props });
9
+ }
@@ -0,0 +1,23 @@
1
+ .badge {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ border: 1px solid transparent;
5
+ border-radius: 0.375rem;
6
+ background: var(--primary);
7
+ color: var(--primary-foreground);
8
+ padding: 0.125rem 0.5rem;
9
+ font-size: 0.75rem;
10
+ font-weight: 600;
11
+ line-height: 1.35;
12
+ text-decoration: none;
13
+ box-shadow: 0 1px 2px var(--shadow);
14
+ transition:
15
+ color 0.2s ease,
16
+ background-color 0.2s ease,
17
+ box-shadow 0.2s ease;
18
+ }
19
+
20
+ .badge:hover {
21
+ background: var(--primary-hover);
22
+ color: var(--primary-foreground);
23
+ }
@@ -0,0 +1,8 @@
1
+ import Link from "next/link";
2
+ import type { ComponentPropsWithoutRef } from "react";
3
+ export declare function Breadcrumb({ className, ...props }: ComponentPropsWithoutRef<"nav">): import("react/jsx-runtime").JSX.Element;
4
+ export declare function BreadcrumbList({ className, ...props }: ComponentPropsWithoutRef<"ol">): import("react/jsx-runtime").JSX.Element;
5
+ export declare function BreadcrumbItem({ className, ...props }: ComponentPropsWithoutRef<"li">): import("react/jsx-runtime").JSX.Element;
6
+ export declare function BreadcrumbLink({ className, ...props }: ComponentPropsWithoutRef<typeof Link>): import("react/jsx-runtime").JSX.Element;
7
+ export declare function BreadcrumbPage({ className, ...props }: ComponentPropsWithoutRef<"span">): import("react/jsx-runtime").JSX.Element;
8
+ export declare function BreadcrumbSeparator({ className, children, ...props }: ComponentPropsWithoutRef<"span">): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Link from "next/link";
3
+ import { cn } from "./cn.js";
4
+ import styles from "./breadcrumb.module.css";
5
+ export function Breadcrumb({ className, ...props }) {
6
+ return (_jsx("nav", { "aria-label": "breadcrumb", "data-slot": "breadcrumb", className: cn(className), ...props }));
7
+ }
8
+ export function BreadcrumbList({ className, ...props }) {
9
+ return (_jsx("ol", { "data-slot": "breadcrumb-list", className: cn(styles.list, className), ...props }));
10
+ }
11
+ export function BreadcrumbItem({ className, ...props }) {
12
+ return (_jsx("li", { "data-slot": "breadcrumb-item", className: cn(styles.item, className), ...props }));
13
+ }
14
+ export function BreadcrumbLink({ className, ...props }) {
15
+ return (_jsx(Link, { "data-slot": "breadcrumb-link", className: cn(styles.link, className), ...props }));
16
+ }
17
+ export function BreadcrumbPage({ className, ...props }) {
18
+ return (_jsx("span", { "data-slot": "breadcrumb-page", "aria-current": "page", className: cn(styles.page, className), ...props }));
19
+ }
20
+ export function BreadcrumbSeparator({ className, children, ...props }) {
21
+ return (_jsx("span", { "data-slot": "breadcrumb-separator", "aria-hidden": "true", className: cn(styles.separator, className), ...props, children: children ?? "/" }));
22
+ }
@@ -0,0 +1,37 @@
1
+ .list {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ align-items: center;
5
+ gap: 0.375rem;
6
+ color: var(--foreground-light);
7
+ font-size: 0.875rem;
8
+ list-style: none;
9
+ margin: 0;
10
+ padding: 0;
11
+ }
12
+
13
+ .item {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: 0.375rem;
17
+ min-width: 0;
18
+ }
19
+
20
+ .link {
21
+ color: var(--foreground-light);
22
+ text-decoration: none;
23
+ transition: color 0.2s ease;
24
+ }
25
+
26
+ .link:hover {
27
+ color: var(--foreground);
28
+ }
29
+
30
+ .page {
31
+ color: var(--foreground);
32
+ font-weight: 400;
33
+ }
34
+
35
+ .separator {
36
+ color: var(--foreground-light);
37
+ }
@@ -0,0 +1,7 @@
1
+ import type { ComponentPropsWithRef } from "react";
2
+ type ButtonProps = ComponentPropsWithRef<"button"> & {
3
+ variant?: "default" | "outline" | "ghost";
4
+ size?: "default" | "sm" | "icon";
5
+ };
6
+ export declare function Button({ className, variant, size, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "./cn.js";
3
+ import styles from "./button.module.css";
4
+ const variants = {
5
+ default: styles.default,
6
+ outline: styles.outline,
7
+ ghost: styles.ghost,
8
+ };
9
+ const sizes = {
10
+ default: styles.defaultSize,
11
+ sm: styles.small,
12
+ icon: styles.icon,
13
+ };
14
+ export function Button({ className, variant = "default", size = "default", ...props }) {
15
+ return (_jsx("button", { "data-slot": "button", className: cn(styles.button, variants[variant], sizes[size], className), ...props }));
16
+ }