@sofidevo/astro-dynamic-header 3.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +543 -337
- package/package.json +20 -16
- package/src/ChevronIcon.astro +33 -0
- package/src/HamburgerButton.astro +100 -92
- package/src/Header.astro +105 -156
- package/src/MobileNav.astro +133 -129
- package/src/MoonIcon.astro +114 -0
- package/src/NavMenu.astro +175 -281
- package/src/SunIcon.astro +42 -0
- package/src/index.ts +15 -8
- package/src/scripts/hamburger.ts +55 -0
- package/src/scripts/nav-menu.ts +119 -0
package/src/MobileNav.astro
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { MenuItem, SecondaryMenuItem, TertiaryMenuItem } from "./index.js";
|
|
3
|
+
import ChevronIcon from "./ChevronIcon.astro";
|
|
3
4
|
|
|
4
5
|
export interface Props {
|
|
5
6
|
/** Header type for styling: "floating" or "fullscreen" */
|
|
@@ -10,16 +11,19 @@ export interface Props {
|
|
|
10
11
|
showHomeLink?: boolean;
|
|
11
12
|
/** Text for the home link (defaults to "Home") */
|
|
12
13
|
homeText?: string;
|
|
14
|
+
/** The destination URL for the home link. @default "/" */
|
|
15
|
+
homeUrl?: string;
|
|
13
16
|
/** Extra CSS class(es) for the root mobile `<nav>` panel. */
|
|
14
17
|
mobileNav__class?: string;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
const {
|
|
18
|
-
type,
|
|
21
|
+
type = "floating",
|
|
19
22
|
mobileNav__class,
|
|
20
23
|
menuItems = [],
|
|
21
24
|
showHomeLink = true,
|
|
22
|
-
homeText = "Home"
|
|
25
|
+
homeText = "Home",
|
|
26
|
+
homeUrl = "/",
|
|
23
27
|
} = Astro.props;
|
|
24
28
|
|
|
25
29
|
const pagePathname = Astro.url.pathname;
|
|
@@ -34,11 +38,11 @@ const pagePathname = Astro.url.pathname;
|
|
|
34
38
|
>
|
|
35
39
|
<ol class="mobile-menu">
|
|
36
40
|
{
|
|
37
|
-
showHomeLink && pagePathname !==
|
|
41
|
+
showHomeLink && pagePathname !== homeUrl && (
|
|
38
42
|
<li class="header__item mobile-header__item">
|
|
39
43
|
<a
|
|
40
44
|
class="menu__link mobile-menu__link"
|
|
41
|
-
href=
|
|
45
|
+
href={homeUrl}
|
|
42
46
|
data-astro-prefetch="hover"
|
|
43
47
|
>
|
|
44
48
|
{homeText}
|
|
@@ -58,13 +62,7 @@ const pagePathname = Astro.url.pathname;
|
|
|
58
62
|
>
|
|
59
63
|
<summary class:list={["menu__summary", { active: isActive }]}>
|
|
60
64
|
{item.text}
|
|
61
|
-
<iconify-
|
|
62
|
-
class="iconify-arrow"
|
|
63
|
-
icon="codicon:triangle-down"
|
|
64
|
-
width="15"
|
|
65
|
-
height="15"
|
|
66
|
-
style="color: var(--accent-color);"
|
|
67
|
-
/>
|
|
65
|
+
<ChevronIcon class="iconify-arrow" width={15} height={15} />
|
|
68
66
|
</summary>
|
|
69
67
|
<ol class="mobile-submenu">
|
|
70
68
|
{item?.submenu?.map((sub: SecondaryMenuItem) => {
|
|
@@ -85,12 +83,10 @@ const pagePathname = Astro.url.pathname;
|
|
|
85
83
|
]}
|
|
86
84
|
>
|
|
87
85
|
{sub.text}
|
|
88
|
-
<
|
|
86
|
+
<ChevronIcon
|
|
89
87
|
class="iconify-arrow"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
height="15"
|
|
93
|
-
style="color: var(--accent-color);"
|
|
88
|
+
width={15}
|
|
89
|
+
height={15}
|
|
94
90
|
/>
|
|
95
91
|
</summary>
|
|
96
92
|
<ol class="mobile-subsubmenu">
|
|
@@ -148,134 +144,142 @@ const pagePathname = Astro.url.pathname;
|
|
|
148
144
|
</nav>
|
|
149
145
|
|
|
150
146
|
<style>
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
/*
|
|
148
|
+
* base (resets) < components (ours) < utilities (consumer classNames).
|
|
149
|
+
* Order statement keeps it deterministic regardless of bundling order.
|
|
150
|
+
*/
|
|
151
|
+
@layer theme, base, components, utilities;
|
|
153
152
|
|
|
154
|
-
|
|
153
|
+
@layer components {
|
|
154
|
+
.mobile-header__menu {
|
|
155
|
+
display: none;
|
|
156
|
+
|
|
157
|
+
@media (width < 768px) {
|
|
158
|
+
display: flex;
|
|
159
|
+
flex-direction: column;
|
|
160
|
+
width: 104vw;
|
|
161
|
+
height: 100dvh;
|
|
162
|
+
position: fixed;
|
|
163
|
+
top: -11px;
|
|
164
|
+
left: 0;
|
|
165
|
+
background: var(--bg-color-opaque, #151515);
|
|
166
|
+
z-index: 20;
|
|
167
|
+
transition:
|
|
168
|
+
transform 0.3s ease-in-out,
|
|
169
|
+
background-color 0.3s ease;
|
|
170
|
+
transform: translateX(100%);
|
|
171
|
+
padding: 10rem 2rem 2rem;
|
|
172
|
+
color: var(--text-color, #fff);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
a {
|
|
176
|
+
color: color-mix(
|
|
177
|
+
in srgb,
|
|
178
|
+
var(--accent-color, #00ffff) 30%,
|
|
179
|
+
var(--text-color, #ffffff) 70%
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.active {
|
|
184
|
+
color: var(--accent-color, #00ffff);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.mobile-menu {
|
|
155
189
|
display: flex;
|
|
156
190
|
flex-direction: column;
|
|
157
|
-
|
|
158
|
-
height:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
z-index: 20;
|
|
164
|
-
transition:
|
|
165
|
-
transform 0.3s ease-in-out,
|
|
166
|
-
background-color 0.3s ease;
|
|
167
|
-
transform: translateX(100%);
|
|
168
|
-
padding: 10rem 2rem 2rem;
|
|
169
|
-
color: var(--text-color, #fff);
|
|
191
|
+
gap: 1rem;
|
|
192
|
+
max-height: 76dvh;
|
|
193
|
+
overflow-y: auto;
|
|
194
|
+
list-style: none;
|
|
195
|
+
padding: 0;
|
|
196
|
+
margin: 0;
|
|
170
197
|
}
|
|
171
198
|
|
|
172
|
-
a {
|
|
173
|
-
|
|
174
|
-
in srgb,
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
199
|
+
.mobile-menu li a {
|
|
200
|
+
border: solid 1px
|
|
201
|
+
color-mix(in srgb, var(--accent-color, #00ffff) 15%, transparent);
|
|
202
|
+
border-radius: 4px;
|
|
203
|
+
width: 100%;
|
|
204
|
+
height: 4rem;
|
|
205
|
+
font-size: 1.5rem;
|
|
206
|
+
display: flex;
|
|
207
|
+
align-items: center;
|
|
208
|
+
justify-content: space-between;
|
|
209
|
+
padding: 0 1rem;
|
|
210
|
+
text-decoration: none;
|
|
178
211
|
}
|
|
179
212
|
|
|
180
|
-
.
|
|
181
|
-
|
|
213
|
+
.mobile-details {
|
|
214
|
+
width: 100%;
|
|
215
|
+
interpolate-size: allow-keywords;
|
|
182
216
|
}
|
|
183
|
-
}
|
|
184
217
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
font-size: 1.5rem;
|
|
203
|
-
display: flex;
|
|
204
|
-
align-items: center;
|
|
205
|
-
justify-content: space-between;
|
|
206
|
-
padding: 0 1rem;
|
|
207
|
-
text-decoration: none;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
.mobile-details {
|
|
211
|
-
width: 100%;
|
|
212
|
-
interpolate-size: allow-keywords;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
.mobile-details summary {
|
|
216
|
-
background: linear-gradient(
|
|
217
|
-
to right,
|
|
218
|
-
color-mix(in srgb, var(--accent-color, #00ffff) 20%, transparent),
|
|
219
|
-
transparent
|
|
220
|
-
);
|
|
221
|
-
border-radius: 4px;
|
|
222
|
-
width: 100%;
|
|
223
|
-
height: 4rem;
|
|
224
|
-
font-size: 1.5rem;
|
|
225
|
-
display: flex;
|
|
226
|
-
align-items: center;
|
|
227
|
-
justify-content: space-between;
|
|
228
|
-
padding: 0 1rem;
|
|
229
|
-
cursor: pointer;
|
|
230
|
-
list-style: none;
|
|
231
|
-
}
|
|
218
|
+
.mobile-details summary {
|
|
219
|
+
background: linear-gradient(
|
|
220
|
+
to right,
|
|
221
|
+
color-mix(in srgb, var(--accent-color, #00ffff) 20%, transparent),
|
|
222
|
+
transparent
|
|
223
|
+
);
|
|
224
|
+
border-radius: 4px;
|
|
225
|
+
width: 100%;
|
|
226
|
+
height: 4rem;
|
|
227
|
+
font-size: 1.5rem;
|
|
228
|
+
display: flex;
|
|
229
|
+
align-items: center;
|
|
230
|
+
justify-content: space-between;
|
|
231
|
+
padding: 0 1rem;
|
|
232
|
+
cursor: pointer;
|
|
233
|
+
list-style: none;
|
|
234
|
+
}
|
|
232
235
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
236
|
+
.mobile-details::details-content {
|
|
237
|
+
transition:
|
|
238
|
+
height 0.5s ease,
|
|
239
|
+
opacity 0.5s ease,
|
|
240
|
+
content-visibility 0.5s allow-discrete;
|
|
241
|
+
opacity: 0;
|
|
242
|
+
height: 0;
|
|
243
|
+
overflow: clip;
|
|
244
|
+
}
|
|
242
245
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
+
.mobile-details:open svg.iconify-arrow {
|
|
247
|
+
transform: rotate(180deg);
|
|
248
|
+
}
|
|
246
249
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
250
|
+
.mobile-details:open::details-content {
|
|
251
|
+
height: auto;
|
|
252
|
+
opacity: 1;
|
|
253
|
+
}
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
255
|
+
.mobile-submenu,
|
|
256
|
+
.mobile-subsubmenu {
|
|
257
|
+
border-left: dashed 1px var(--accent-color, #00ffff);
|
|
258
|
+
padding-left: 2rem;
|
|
259
|
+
margin-left: 1rem;
|
|
260
|
+
margin-top: 1rem;
|
|
261
|
+
list-style: none;
|
|
262
|
+
gap: 1rem;
|
|
263
|
+
display: flex;
|
|
264
|
+
flex-direction: column;
|
|
265
|
+
}
|
|
263
266
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
.mobile-header__menu.is-active {
|
|
268
|
+
transform: translateX(-7%);
|
|
269
|
+
}
|
|
267
270
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
271
|
+
/* Adjust transform for fullscreen header */
|
|
272
|
+
.mobile-header__menu--fullscreen.is-active {
|
|
273
|
+
transform: translate(0%);
|
|
274
|
+
}
|
|
272
275
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
276
|
+
.menu__summary {
|
|
277
|
+
width: 100%;
|
|
278
|
+
font-size: 1.7rem;
|
|
279
|
+
height: 5rem;
|
|
280
|
+
color: inherit;
|
|
281
|
+
display: flex;
|
|
282
|
+
align-items: center;
|
|
283
|
+
}
|
|
280
284
|
}
|
|
281
285
|
</style>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
const props = Astro.props;
|
|
3
|
+
|
|
4
|
+
const regex = /\sid="(\S+)"/g;
|
|
5
|
+
const counters = new Map<string, number>();
|
|
6
|
+
|
|
7
|
+
function nextID(id: string) {
|
|
8
|
+
id = id.replace(/[0-9]+$/, "") || "a";
|
|
9
|
+
const count = counters.get(id) || 0;
|
|
10
|
+
counters.set(id, count + 1);
|
|
11
|
+
return count ? `${id}${count}` : id;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function replaceIDs(body: string) {
|
|
15
|
+
const ids: string[] = [];
|
|
16
|
+
let match;
|
|
17
|
+
while ((match = regex.exec(body))) ids.push(match[1]);
|
|
18
|
+
if (!ids.length) return body;
|
|
19
|
+
const suffix =
|
|
20
|
+
"suffix" + ((Math.random() * 16777216) | Date.now()).toString(16);
|
|
21
|
+
ids.forEach((id) => {
|
|
22
|
+
const newID = nextID(id);
|
|
23
|
+
const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24
|
+
body = body.replace(
|
|
25
|
+
new RegExp('([#;"])(' + escapedID + ')([")]|\\.[a-z])', "g"),
|
|
26
|
+
"$1" + newID + suffix + "$3",
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
body = body.replace(new RegExp(suffix, "g"), "");
|
|
30
|
+
return body;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const viewBox = "0 0 24 24";
|
|
34
|
+
const content = replaceIDs(
|
|
35
|
+
`<defs><mask id="SVGnw0mAdjE"><path d="M12 2c5.52 0 10 4.48 10 10c0 5.52 -4.48 10 -10 10c-5.52 0 -10 -4.48 -10 -10c0 -5.52 4.48 -10 10 -10Z" class="n1mjuz"><animate fill="freeze" attributeName="d" dur="0.4s" values="M12 6c3.31 0 6 2.69 6 6c0 3.31 -2.69 6 -6 6c-3.31 0 -6 -2.69 -6 -6c0 -3.31 2.69 -6 6 -6Z;M12 2c5.52 0 10 4.48 10 10c0 5.52 -4.48 10 -10 10c-5.52 0 -10 -4.48 -10 -10c0 -5.52 4.48 -10 10 -10Z"/><set fill="freeze" attributeName="opacity" begin="0.4s" to="0"/></path><path d="M18 -4c5.52 0 10 4.48 10 10c0 5.52 -4.48 10 -10 10c-5.52 0 -10 -4.48 -10 -10c0 -5.52 4.48 -10 10 -10Z"><animate fill="freeze" attributeName="d" dur="0.4s" values="M22 -4c3.31 0 6 2.69 6 6c0 3.31 -2.69 6 -6 6c-3.31 0 -6 -2.69 -6 -6c0 -3.31 2.69 -6 6 -6Z;M18 -4c5.52 0 10 4.48 10 10c0 5.52 -4.48 10 -10 10c-5.52 0 -10 -4.48 -10 -10c0 -5.52 4.48 -10 10 -10Z"/><set fill="freeze" attributeName="opacity" begin="0.4s" to="0"/></path></mask></defs><path class="smogax"><animate fill="freeze" attributeName="opacity" dur="0.4s" values="1;0"/></path><g class="cuyn6t"><path mask="url(#SVGnw0mAdjE)" class="t_ev7s"/><path opacity="0" class="izfmla"><set fill="freeze" attributeName="opacity" begin="0.4s" to="1"/></path></g><g stroke-dashoffset="4" class="abf34n"><path class="k7_l3l"><animate attributeName="stroke-dashoffset" begin="0.4s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="hhuniw"><animate attributeName="stroke-dashoffset" begin="1.07s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="z8cgtd"><animate attributeName="stroke-dashoffset" begin="1.74s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="drcfta"><animate attributeName="stroke-dashoffset" begin="2.41s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="yij7vx"><animate attributeName="stroke-dashoffset" begin="3.08s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="emoajy"><animate attributeName="stroke-dashoffset" begin="3.75s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="f1to6s"><animate attributeName="stroke-dashoffset" begin="4.42s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="niixso"><animate attributeName="stroke-dashoffset" begin="5.09s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path><path class="z8cgtd"><animate attributeName="stroke-dashoffset" begin="5.76s" dur="6s" keyTimes="0;0.08;0.22;0.3;1" repeatCount="indefinite" values="4;0;0;4;4"/></path></g>`,
|
|
36
|
+
);
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
<svg
|
|
40
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
41
|
+
width="25px"
|
|
42
|
+
height="25px"
|
|
43
|
+
viewBox={viewBox}
|
|
44
|
+
{...props}
|
|
45
|
+
set:html={content}
|
|
46
|
+
/>
|
|
47
|
+
|
|
48
|
+
<style is:inline>
|
|
49
|
+
/*
|
|
50
|
+
* base (resets) < components (ours) < utilities (consumer classNames).
|
|
51
|
+
* Order statement keeps it deterministic regardless of bundling order.
|
|
52
|
+
*/
|
|
53
|
+
@layer theme, base, components, utilities;
|
|
54
|
+
|
|
55
|
+
@layer components {
|
|
56
|
+
.n1mjuz {
|
|
57
|
+
fill: var(--svg-color--fff, #fff);
|
|
58
|
+
}
|
|
59
|
+
.smogax {
|
|
60
|
+
fill: none;
|
|
61
|
+
stroke: white;
|
|
62
|
+
stroke-linecap: round;
|
|
63
|
+
stroke-linejoin: round;
|
|
64
|
+
stroke-width: var(--svg-stroke-width--2px, 2px);
|
|
65
|
+
d: path(
|
|
66
|
+
"M12 21v1M21 12h1M12 3v-1M3 12h-1M18.5 18.5l0.5 0.5M18.5 5.5l0.5 -0.5M5.5 5.5l-0.5 -0.5M5.5 18.5l-0.5 0.5"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
.t_ev7s {
|
|
70
|
+
d: path("M0 0h24v24H0z");
|
|
71
|
+
}
|
|
72
|
+
.izfmla {
|
|
73
|
+
stroke: white;
|
|
74
|
+
stroke-linecap: round;
|
|
75
|
+
stroke-linejoin: round;
|
|
76
|
+
stroke-width: var(--svg-stroke-width--2px, 2px);
|
|
77
|
+
d: path(
|
|
78
|
+
"M7 6c0 6.08 4.92 11 11 11c0.53 0 1.05 -0.04 1.56 -0.11c-1.61 2.47 -4.39 4.11 -7.56 4.11c-4.97 0 -9 -4.03 -9 -9c0 -3.17 1.64 -5.95 4.11 -7.56c-0.07 0.51 -0.11 1.03 -0.11 1.56Z"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
.abf34n {
|
|
82
|
+
fill: none;
|
|
83
|
+
stroke: white;
|
|
84
|
+
stroke-dasharray: 4;
|
|
85
|
+
stroke-linecap: round;
|
|
86
|
+
stroke-linejoin: round;
|
|
87
|
+
}
|
|
88
|
+
.k7_l3l {
|
|
89
|
+
d: path("M12 5h1.5M12 5h-1.5M12 5v1.5M12 5v-1.5");
|
|
90
|
+
}
|
|
91
|
+
.hhuniw {
|
|
92
|
+
d: path("M17 11h1.5M17 11h-1.5M17 11v1.5M17 11v-1.5");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.z8cgtd {
|
|
96
|
+
d: path("M20 5h1.5M20 5h-1.5M20 5v1.5M20 5v-1.5");
|
|
97
|
+
}
|
|
98
|
+
.drcfta {
|
|
99
|
+
d: path("M12 4h1.5M12 4h-1.5M12 4v1.5M12 4v-1.5");
|
|
100
|
+
}
|
|
101
|
+
.yij7vx {
|
|
102
|
+
d: path("M18 12h1.5M18 12h-1.5M18 12v1.5M18 12v-1.5");
|
|
103
|
+
}
|
|
104
|
+
.emoajy {
|
|
105
|
+
d: path("M19 4h1.5M19 4h-1.5M19 4v1.5M19 4v-1.5");
|
|
106
|
+
}
|
|
107
|
+
.f1to6s {
|
|
108
|
+
d: path("M13 4h1.5M13 4h-1.5M13 4v1.5M13 4v-1.5");
|
|
109
|
+
}
|
|
110
|
+
.niixso {
|
|
111
|
+
d: path("M19 11h1.5M19 11h-1.5M19 11v1.5M19 11v-1.5");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
</style>
|