@notionhive/menus 0.1.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.
Files changed (61) hide show
  1. package/bin/menus.js +16 -0
  2. package/category.config.json +7 -0
  3. package/package.json +24 -0
  4. package/registry/index.json +74 -0
  5. package/registry/menu-01.json +14 -0
  6. package/registry/menu-02.json +12 -0
  7. package/registry/menu-03.json +12 -0
  8. package/registry/menu-04.json +10 -0
  9. package/registry/menu-05.json +10 -0
  10. package/registry/menu-06.json +10 -0
  11. package/templates/components/atoms/SafeImage/SafeImage.jsx +101 -0
  12. package/templates/components/atoms/SafeImage/index.js +1 -0
  13. package/templates/components/hooks/useCarousel.js +73 -0
  14. package/templates/components/molecules/CorporateHeader/CorporateHeader.jsx +174 -0
  15. package/templates/components/molecules/CorporateHeader/CorporateHeader.propTypes.js +22 -0
  16. package/templates/components/molecules/CorporateHeader/index.js +1 -0
  17. package/templates/components/molecules/EquipmentMegaMenu/EquipmentMegaMenu.jsx +202 -0
  18. package/templates/components/molecules/EquipmentMegaMenu/EquipmentMegaMenu.propTypes.js +104 -0
  19. package/templates/components/molecules/EquipmentMegaMenu/index.js +5 -0
  20. package/templates/components/molecules/FullScreenNavOverlay/FullScreenNavOverlay.jsx +117 -0
  21. package/templates/components/molecules/FullScreenNavOverlay/FullScreenNavOverlay.propTypes.js +34 -0
  22. package/templates/components/molecules/FullScreenNavOverlay/index.js +2 -0
  23. package/templates/components/molecules/MobileNavDrawer/MobileNavDrawer.jsx +139 -0
  24. package/templates/components/molecules/MobileNavDrawer/index.js +2 -0
  25. package/templates/components/molecules/SiteHeader/SiteHeader.jsx +177 -0
  26. package/templates/components/molecules/SiteHeader/SiteHeader.propTypes.js +20 -0
  27. package/templates/components/molecules/SiteHeader/index.js +1 -0
  28. package/templates/components/molecules/SlideIndicators/SlideIndicators.jsx +75 -0
  29. package/templates/components/molecules/SlideIndicators/SlideIndicators.propTypes.js +10 -0
  30. package/templates/components/molecules/SlideIndicators/index.js +1 -0
  31. package/templates/components/organisms/Menu01/Menu01.jsx +211 -0
  32. package/templates/components/organisms/Menu01/Menu01.propTypes.js +63 -0
  33. package/templates/components/organisms/Menu01/index.js +1 -0
  34. package/templates/components/organisms/Menu02/Menu02.jsx +133 -0
  35. package/templates/components/organisms/Menu02/Menu02.propTypes.js +71 -0
  36. package/templates/components/organisms/Menu02/index.js +1 -0
  37. package/templates/components/organisms/Menu03/Menu03.jsx +411 -0
  38. package/templates/components/organisms/Menu03/Menu03.propTypes.js +113 -0
  39. package/templates/components/organisms/Menu03/index.js +1 -0
  40. package/templates/components/organisms/Menu04/Menu04.jsx +232 -0
  41. package/templates/components/organisms/Menu04/Menu04.propTypes.js +53 -0
  42. package/templates/components/organisms/Menu04/index.js +2 -0
  43. package/templates/components/organisms/Menu05/Menu05.jsx +318 -0
  44. package/templates/components/organisms/Menu05/Menu05.propTypes.js +79 -0
  45. package/templates/components/organisms/Menu05/index.js +2 -0
  46. package/templates/components/organisms/Menu06/Menu06.jsx +241 -0
  47. package/templates/components/organisms/Menu06/Menu06.propTypes.js +55 -0
  48. package/templates/components/organisms/Menu06/index.js +2 -0
  49. package/templates/public/menus/menu01/agriculture.png +0 -0
  50. package/templates/public/menus/menu01/banner.jpg +0 -0
  51. package/templates/public/menus/menu01/build-your-own.png +0 -0
  52. package/templates/public/menus/menu01/construction.png +0 -0
  53. package/templates/public/menus/menu01/lawn-care.png +0 -0
  54. package/templates/public/menus/menu01/logo.png +0 -0
  55. package/templates/public/menus/menu01/promotions.png +0 -0
  56. package/templates/public/menus/menu03/logo.png +46 -0
  57. package/templates/public/menus/menu04/featured.jpg +0 -0
  58. package/templates/public/menus/menu04/logo.png +0 -0
  59. package/templates/public/menus/menu05/hero-bg.jpg +0 -0
  60. package/templates/public/menus/menu05/logo.png +0 -0
  61. package/templates/public/menus/menu06/pool.jpg +0 -0
@@ -0,0 +1,113 @@
1
+ import PropTypes from "prop-types";
2
+
3
+ const navItemShape = PropTypes.shape({
4
+ label: PropTypes.string.isRequired,
5
+ href: PropTypes.string,
6
+ onClick: PropTypes.func,
7
+ hasDropdown: PropTypes.bool,
8
+ active: PropTypes.bool,
9
+ });
10
+
11
+ const utilityLinkShape = PropTypes.shape({
12
+ label: PropTypes.string.isRequired,
13
+ href: PropTypes.string,
14
+ onClick: PropTypes.func,
15
+ highlighted: PropTypes.bool,
16
+ hasDropdown: PropTypes.bool,
17
+ });
18
+
19
+ const aboutLinkShape = PropTypes.shape({
20
+ label: PropTypes.string.isRequired,
21
+ href: PropTypes.string,
22
+ onClick: PropTypes.func,
23
+ variant: PropTypes.oneOf(["primary", "secondary"]),
24
+ });
25
+
26
+ export const menu03PropTypes = {
27
+ logoSrc: PropTypes.string,
28
+ logoAlt: PropTypes.string,
29
+ utilityLinks: PropTypes.arrayOf(utilityLinkShape),
30
+ navItems: PropTypes.arrayOf(navItemShape),
31
+ onSearchClick: PropTypes.func,
32
+ onMenuClick: PropTypes.func,
33
+ aboutMenuOpen: PropTypes.bool,
34
+ defaultAboutMenuOpen: PropTypes.bool,
35
+ onAboutMenuChange: PropTypes.func,
36
+ aboutPrimaryLinks: PropTypes.arrayOf(aboutLinkShape),
37
+ aboutSecondaryHeading: PropTypes.string,
38
+ aboutSecondaryLinks: PropTypes.arrayOf(aboutLinkShape),
39
+ slides: PropTypes.arrayOf(
40
+ PropTypes.shape({
41
+ backgroundImage: PropTypes.string,
42
+ backgroundAlt: PropTypes.string,
43
+ headline: PropTypes.string,
44
+ })
45
+ ),
46
+ slideCount: PropTypes.number,
47
+ activeSlide: PropTypes.number,
48
+ defaultPlaying: PropTypes.bool,
49
+ onPlayPauseClick: PropTypes.func,
50
+ onSlideChange: PropTypes.func,
51
+ className: PropTypes.string,
52
+ };
53
+
54
+ export const menu03DefaultProps = {
55
+ logoSrc: "/menus/menu03/logo.png",
56
+ logoAlt: "BRAC University",
57
+ utilityLinks: [
58
+ { label: "Apply Now", href: "#" },
59
+ { label: "Make a Donation", href: "#" },
60
+ { label: "Academic Dates", href: "#" },
61
+ { label: "Faculty and Staff", href: "#" },
62
+ { label: "Alumni", href: "#", highlighted: true, hasDropdown: true },
63
+ { label: "Students", href: "#" },
64
+ ],
65
+ navItems: [
66
+ { label: "About", hasDropdown: true, active: true },
67
+ { label: "Academics", href: "#", hasDropdown: true },
68
+ { label: "Admission", href: "#", hasDropdown: true },
69
+ { label: "Research", href: "#" },
70
+ { label: "Campus Life", href: "#", hasDropdown: true },
71
+ { label: "News", href: "#" },
72
+ { label: "Events", href: "#" },
73
+ { label: "More", href: "#", hasDropdown: true },
74
+ ],
75
+ defaultAboutMenuOpen: false,
76
+ aboutPrimaryLinks: [
77
+ { label: "About BRAC University", href: "#", variant: "primary" },
78
+ { label: "Mission and Vision", href: "#", variant: "primary" },
79
+ { label: "Affiliations", href: "#", variant: "primary" },
80
+ { label: "HR & Administrative Policies", href: "#", variant: "primary" },
81
+ ],
82
+ aboutSecondaryHeading: "Leadership and Management",
83
+ aboutSecondaryLinks: [
84
+ { label: "The Vice Chancellor", href: "#", variant: "secondary" },
85
+ { label: "Board of Trustees", href: "#", variant: "secondary" },
86
+ { label: "Syndicate", href: "#", variant: "secondary" },
87
+ { label: "Academic Council", href: "#", variant: "secondary" },
88
+ { label: "Administration", href: "#", variant: "secondary" },
89
+ { label: "Senior Management and Advisors", href: "#", variant: "secondary" },
90
+ { label: "Faculty", href: "#", variant: "secondary" },
91
+ { label: "Staffs", href: "#", variant: "secondary" },
92
+ ],
93
+ slides: [
94
+ {
95
+ backgroundImage: "/heroes/hero14/background.jpg",
96
+ backgroundAlt: "Aerial view of BRAC University campus",
97
+ headline: "From Bangladesh to the World",
98
+ },
99
+ {
100
+ backgroundImage: "/heroes/hero14/background.jpg",
101
+ backgroundAlt: "BRAC University campus",
102
+ headline: "Inspiring Excellence",
103
+ },
104
+ {
105
+ backgroundImage: "/heroes/hero14/background.jpg",
106
+ backgroundAlt: "BRAC University students",
107
+ headline: "Leading Through Innovation",
108
+ },
109
+ ],
110
+ slideCount: 3,
111
+ activeSlide: 0,
112
+ defaultPlaying: true,
113
+ };
@@ -0,0 +1 @@
1
+ export { Menu03, default } from "./Menu03";
@@ -0,0 +1,232 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import SafeImage from "../../atoms/SafeImage";
5
+ import { FullScreenNavOverlay } from "../../molecules/FullScreenNavOverlay";
6
+ import { menu04DefaultProps, menu04PropTypes } from "./Menu04.propTypes";
7
+
8
+ function CloseIcon() {
9
+ return (
10
+ <span className="relative flex h-5 w-8 items-center justify-center" aria-hidden="true">
11
+ <span className="absolute h-0.5 w-9 rotate-[30deg] bg-white" />
12
+ <span className="absolute h-0.5 w-9 -rotate-[30deg] bg-white" />
13
+ </span>
14
+ );
15
+ }
16
+
17
+ function ExternalLinkIcon() {
18
+ return (
19
+ <svg
20
+ width="11"
21
+ height="11"
22
+ viewBox="0 0 11 11"
23
+ fill="none"
24
+ aria-hidden="true"
25
+ className="shrink-0"
26
+ >
27
+ <path
28
+ d="M2 9L9 2M9 2H4M9 2V7"
29
+ stroke="currentColor"
30
+ strokeWidth="1.2"
31
+ strokeLinecap="round"
32
+ strokeLinejoin="round"
33
+ />
34
+ </svg>
35
+ );
36
+ }
37
+
38
+ /**
39
+ * Menu04 — Verona full-screen dark navigation overlay with featured image,
40
+ * serif nav links, contact info, and social pills.
41
+ *
42
+ * @param {object} props - See Menu04.propTypes.js
43
+ */
44
+ export function Menu04({
45
+ defaultOpen = menu04DefaultProps.defaultOpen,
46
+ logoSrc = menu04DefaultProps.logoSrc,
47
+ logoAlt = menu04DefaultProps.logoAlt,
48
+ featuredImage = menu04DefaultProps.featuredImage,
49
+ featuredImageAlt = menu04DefaultProps.featuredImageAlt,
50
+ navItems = menu04DefaultProps.navItems,
51
+ email = menu04DefaultProps.email,
52
+ phone = menu04DefaultProps.phone,
53
+ socialLinks = menu04DefaultProps.socialLinks,
54
+ closeLabel = menu04DefaultProps.closeLabel,
55
+ onClose,
56
+ className = "",
57
+ }) {
58
+ const [isOpen, setIsOpen] = useState(defaultOpen);
59
+
60
+ const handleClose = () => {
61
+ setIsOpen(false);
62
+ onClose?.();
63
+ };
64
+
65
+ return (
66
+ <section
67
+ className={["relative min-h-[600px] w-full bg-[#1f1f1f] md:min-h-[700px]", className]
68
+ .filter(Boolean)
69
+ .join(" ")}
70
+ data-menu="menu04"
71
+ >
72
+ {!isOpen ? (
73
+ <div className="flex min-h-[600px] items-center justify-center px-4 md:min-h-[700px]">
74
+ <button
75
+ type="button"
76
+ onClick={() => setIsOpen(true)}
77
+ className="rounded-xl border border-white/20 px-8 py-4 font-medium text-white transition-colors duration-200 ease-out hover:bg-white/10 focus-visible:outline-2 focus-visible:outline-offset-2"
78
+ >
79
+ Open Menu
80
+ </button>
81
+ </div>
82
+ ) : null}
83
+
84
+ <FullScreenNavOverlay
85
+ isOpen={isOpen}
86
+ onClose={handleClose}
87
+ slideFrom="right"
88
+ ariaLabel="Verona navigation"
89
+ panelClassName="bg-[#1f1f1f]"
90
+ >
91
+ <div className="relative flex min-h-full w-full flex-col overflow-y-auto">
92
+ {/* Vertical grid lines */}
93
+ <div
94
+ className="pointer-events-none absolute inset-0 hidden lg:block"
95
+ aria-hidden="true"
96
+ >
97
+ <div className="absolute bottom-0 left-[4%] top-0 w-px bg-white/10" />
98
+ <div className="absolute bottom-0 left-1/3 top-0 w-px bg-white/10" />
99
+ <div className="absolute bottom-0 left-2/3 top-0 w-px bg-white/10" />
100
+ <div className="absolute bottom-0 right-[4%] top-0 w-px bg-white/10" />
101
+ </div>
102
+
103
+ {/* Header */}
104
+ <div className="relative z-10 flex items-start justify-between px-4 pt-6 sm:px-6 md:px-10 lg:px-[60px] lg:pt-8">
105
+ <div className="relative h-8 w-[100px] sm:h-10 sm:w-[130px]">
106
+ <SafeImage
107
+ src={logoSrc}
108
+ alt={logoAlt}
109
+ fill
110
+ className="object-contain object-left"
111
+ sizes="130px"
112
+ />
113
+ </div>
114
+
115
+ <button
116
+ type="button"
117
+ onClick={handleClose}
118
+ className="flex items-center gap-3 rounded-xl px-4 py-3 text-white transition-opacity duration-200 ease-out hover:opacity-80 focus-visible:outline-2 focus-visible:outline-offset-2 sm:gap-[18px] sm:px-[30px] sm:py-3"
119
+ >
120
+ <span className="text-base tracking-wide sm:text-[21px]">{closeLabel}</span>
121
+ <CloseIcon />
122
+ </button>
123
+ </div>
124
+
125
+ {/* Three-column content */}
126
+ <div className="relative z-10 mx-auto flex w-full max-w-[1800px] flex-1 flex-col gap-12 px-4 pb-12 pt-10 sm:px-6 md:px-10 lg:grid lg:grid-cols-3 lg:gap-0 lg:px-[60px] lg:pb-16 lg:pt-16">
127
+ {/* Featured image */}
128
+ <div className="relative aspect-[535/768] w-full overflow-hidden lg:aspect-auto lg:min-h-[500px] lg:max-w-[535px]">
129
+ <SafeImage
130
+ src={featuredImage}
131
+ alt={featuredImageAlt}
132
+ fill
133
+ className="object-cover object-center"
134
+ sizes="(max-width: 1024px) 100vw, 535px"
135
+ priority
136
+ />
137
+ </div>
138
+
139
+ {/* Nav links */}
140
+ <nav className="flex flex-col gap-6 sm:gap-8 lg:items-start lg:justify-center lg:px-8 xl:px-12">
141
+ {navItems.map((item) => {
142
+ const linkClass = [
143
+ "font-serif text-4xl leading-none tracking-[-0.03em] transition-opacity duration-200 ease-out sm:text-5xl md:text-6xl lg:text-[72px] lg:tracking-[-2.16px]",
144
+ item.isActive ? "text-white" : "text-white/60 hover:text-white/80",
145
+ ].join(" ");
146
+
147
+ if (item.href) {
148
+ return (
149
+ <a
150
+ key={item.label}
151
+ href={item.href}
152
+ className={linkClass}
153
+ aria-current={item.isActive ? "page" : undefined}
154
+ >
155
+ {item.label}
156
+ </a>
157
+ );
158
+ }
159
+
160
+ return (
161
+ <button
162
+ key={item.label}
163
+ type="button"
164
+ onClick={item.onClick}
165
+ className={`${linkClass} text-left focus-visible:outline-2 focus-visible:outline-offset-2`}
166
+ aria-current={item.isActive ? "page" : undefined}
167
+ >
168
+ {item.label}
169
+ </button>
170
+ );
171
+ })}
172
+ </nav>
173
+
174
+ {/* Contact + social */}
175
+ <div className="flex flex-col justify-end gap-10 lg:gap-12 lg:pb-4 lg:pl-8 xl:pl-12">
176
+ <div className="flex flex-col gap-4 sm:gap-6">
177
+ {email ? (
178
+ <a
179
+ href={`mailto:${email}`}
180
+ className="font-serif text-3xl leading-tight tracking-[-0.03em] text-white transition-opacity duration-200 ease-out hover:opacity-80 sm:text-4xl md:text-5xl lg:text-[56px] lg:tracking-[-1.68px]"
181
+ >
182
+ {email}
183
+ </a>
184
+ ) : null}
185
+ {phone ? (
186
+ <a
187
+ href={`tel:${phone.replace(/\s/g, "")}`}
188
+ className="text-base text-white/80 transition-opacity duration-200 ease-out hover:opacity-100"
189
+ >
190
+ {phone}
191
+ </a>
192
+ ) : null}
193
+ </div>
194
+
195
+ <div className="flex flex-wrap gap-2">
196
+ {socialLinks.map((link) => {
197
+ const pillClass =
198
+ "inline-flex h-11 items-center gap-2.5 rounded-[88px] bg-white/[0.04] px-6 text-sm text-white transition-colors duration-200 ease-out hover:bg-white/10 focus-visible:outline-2 focus-visible:outline-offset-2";
199
+
200
+ if (link.href) {
201
+ return (
202
+ <a key={link.label} href={link.href} className={pillClass}>
203
+ {link.label}
204
+ <ExternalLinkIcon />
205
+ </a>
206
+ );
207
+ }
208
+
209
+ return (
210
+ <button
211
+ key={link.label}
212
+ type="button"
213
+ onClick={link.onClick}
214
+ className={pillClass}
215
+ >
216
+ {link.label}
217
+ <ExternalLinkIcon />
218
+ </button>
219
+ );
220
+ })}
221
+ </div>
222
+ </div>
223
+ </div>
224
+ </div>
225
+ </FullScreenNavOverlay>
226
+ </section>
227
+ );
228
+ }
229
+
230
+ Menu04.propTypes = menu04PropTypes;
231
+
232
+ export default Menu04;
@@ -0,0 +1,53 @@
1
+ import PropTypes from "prop-types";
2
+
3
+ export const menu04PropTypes = {
4
+ /** Whether the overlay starts open (uncontrolled). */
5
+ defaultOpen: PropTypes.bool,
6
+ logoSrc: PropTypes.string,
7
+ logoAlt: PropTypes.string,
8
+ featuredImage: PropTypes.string,
9
+ featuredImageAlt: PropTypes.string,
10
+ navItems: PropTypes.arrayOf(
11
+ PropTypes.shape({
12
+ label: PropTypes.string.isRequired,
13
+ href: PropTypes.string,
14
+ onClick: PropTypes.func,
15
+ isActive: PropTypes.bool,
16
+ }),
17
+ ),
18
+ email: PropTypes.string,
19
+ phone: PropTypes.string,
20
+ socialLinks: PropTypes.arrayOf(
21
+ PropTypes.shape({
22
+ label: PropTypes.string.isRequired,
23
+ href: PropTypes.string,
24
+ onClick: PropTypes.func,
25
+ }),
26
+ ),
27
+ closeLabel: PropTypes.string,
28
+ onClose: PropTypes.func,
29
+ className: PropTypes.string,
30
+ };
31
+
32
+ export const menu04DefaultProps = {
33
+ defaultOpen: false,
34
+ logoSrc: "/menus/menu04/logo.png",
35
+ logoAlt: "Verona",
36
+ featuredImage: "/menus/menu04/featured.jpg",
37
+ featuredImageAlt: "Modern red architecture against a blue sky",
38
+ navItems: [
39
+ { label: "Home", href: "#", isActive: true },
40
+ { label: "Properties", href: "#" },
41
+ { label: "Projects", href: "#" },
42
+ { label: "About Us", href: "#" },
43
+ { label: "Contact Us", href: "#" },
44
+ ],
45
+ email: "hello@verona.com",
46
+ phone: "+31 (0)6 51897629",
47
+ socialLinks: [
48
+ { label: "Linkedin", href: "#" },
49
+ { label: "Instagram", href: "#" },
50
+ { label: "Dribbble", href: "#" },
51
+ ],
52
+ closeLabel: "CLOSE",
53
+ };
@@ -0,0 +1,2 @@
1
+ export { Menu04 } from "./Menu04";
2
+ export { default } from "./Menu04";