@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.
@@ -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-icon
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
- <iconify-icon
86
+ <ChevronIcon
89
87
  class="iconify-arrow"
90
- icon="codicon:triangle-down"
91
- width="15"
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
- .mobile-header__menu {
152
- display: none;
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
- @media (width < 768px) {
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
- width: 104vw;
158
- height: 100dvh;
159
- position: fixed;
160
- top: -11px;
161
- left: 0;
162
- background: var(--bg-color-opaque, #151515);
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
- color: color-mix(
174
- in srgb,
175
- var(--accent-color, #00ffff) 30%,
176
- var(--text-color, #ffffff) 70%
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
- .active {
181
- color: var(--accent-color, #00ffff) !important;
213
+ .mobile-details {
214
+ width: 100%;
215
+ interpolate-size: allow-keywords;
182
216
  }
183
- }
184
217
 
185
- .mobile-menu {
186
- display: flex;
187
- flex-direction: column;
188
- gap: 1rem;
189
- max-height: 76dvh;
190
- overflow-y: auto;
191
- list-style: none;
192
- padding: 0;
193
- margin: 0;
194
- }
195
-
196
- .mobile-menu li a {
197
- border: solid 1px
198
- color-mix(in srgb, var(--accent-color, #00ffff) 15%, transparent);
199
- border-radius: 4px;
200
- width: 100%;
201
- height: 4rem;
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
- .mobile-details::details-content {
234
- transition:
235
- height 0.5s ease,
236
- opacity 0.5s ease,
237
- content-visibility 0.5s allow-discrete;
238
- opacity: 0;
239
- height: 0;
240
- overflow: clip;
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
- .mobile-details:open iconify-icon {
244
- transform: rotate(180deg);
245
- }
246
+ .mobile-details:open svg.iconify-arrow {
247
+ transform: rotate(180deg);
248
+ }
246
249
 
247
- .mobile-details:open::details-content {
248
- height: auto;
249
- opacity: 1;
250
- }
250
+ .mobile-details:open::details-content {
251
+ height: auto;
252
+ opacity: 1;
253
+ }
251
254
 
252
- .mobile-submenu,
253
- .mobile-subsubmenu {
254
- border-left: dashed 1px var(--accent-color, #00ffff);
255
- padding-left: 2rem;
256
- margin-left: 1rem;
257
- margin-top: 1rem;
258
- list-style: none;
259
- gap: 1rem;
260
- display: flex;
261
- flex-direction: column;
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
- .mobile-header__menu.is-active {
265
- transform: translateX(-7%);
266
- }
267
+ .mobile-header__menu.is-active {
268
+ transform: translateX(-7%);
269
+ }
267
270
 
268
- /* Adjust transform for fullscreen header */
269
- .mobile-header__menu--fullscreen.is-active {
270
- transform: translate(0%);
271
- }
271
+ /* Adjust transform for fullscreen header */
272
+ .mobile-header__menu--fullscreen.is-active {
273
+ transform: translate(0%);
274
+ }
272
275
 
273
- .menu__summary {
274
- width: 100%;
275
- font-size: 1.7rem;
276
- height: 5rem;
277
- color: inherit;
278
- display: flex;
279
- align-items: center;
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>