@sofidevo/astro-dynamic-header 2.0.2 → 3.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.
@@ -1,18 +1,11 @@
1
1
  ---
2
- export interface Props {
3
- /** Override the default color of the hamburger lines */
4
- color?: string;
5
- }
6
-
7
- const { color = "var(--text-color, var(--color-hamburger-lines, #fff))" } =
8
- Astro.props;
2
+ export interface Props {}
9
3
  ---
10
4
 
11
5
  <button
12
6
  class="hamburger hamburger--collapse"
13
7
  type="button"
14
8
  id="hamburger-btn"
15
- style={`--hamburger-color: ${color};`}
16
9
  >
17
10
  <span class="hamburger-box">
18
11
  <span class="hamburger-inner"></span>
@@ -65,10 +58,7 @@ const { color = "var(--text-color, var(--color-hamburger-lines, #fff))" } =
65
58
  .hamburger-inner,
66
59
  .hamburger-inner::before,
67
60
  .hamburger-inner::after {
68
- background-color: var(
69
- --hamburger-color,
70
- var(--color-hamburger-lines, #fff)
71
- );
61
+ background-color: var(--text-color, inherit);
72
62
  position: absolute;
73
63
  width: 40px;
74
64
  height: 4px;
package/src/Header.astro CHANGED
@@ -4,21 +4,20 @@ import NavMenu from "./NavMenu.astro";
4
4
  import MobileNav from "./MobileNav.astro";
5
5
 
6
6
  import type {
7
- LogoConfig,
8
7
  NavConfig,
9
8
  DualThemeConfig,
10
- CustomClassNames,
9
+ HeaderClassNames,
11
10
  } from "./index.js";
12
11
 
13
12
  export interface Props {
14
- /**
13
+ /**
15
14
  * Layout style.
16
15
  * - "floating": Centered with max-width and rounded corners.
17
16
  * - "fullscreen": Full width with no border radius.
18
17
  * @default "floating"
19
18
  */
20
19
  headerType?: "floating" | "fullscreen";
21
- /**
20
+ /**
22
21
  * Theme behavior.
23
22
  * - "light": Force light mode.
24
23
  * - "dark": Force dark mode.
@@ -26,35 +25,31 @@ export interface Props {
26
25
  * @default "auto"
27
26
  */
28
27
  preset?: "light" | "dark" | "auto";
29
- /** Logo configuration object (src, alt, text, etc.) */
30
- logo?: LogoConfig;
28
+
31
29
  /** Navigation links and structure. */
32
30
  navigation?: NavConfig;
33
31
  /** Custom theme overrides for light and dark modes. */
34
32
  theme?: DualThemeConfig;
35
- /**
36
- * Custom CSS classes for specific internal elements.
37
- * @example { header: "shadow-lg", nav: "ml-auto" }
33
+ /**
34
+ * High-level CSS class overrides for structural wrapper elements.
35
+ * For fine-grained nav/logo element classes, use the nested `xxx__class`
36
+ * props inside `navigation` or `logo` instead.
37
+ * @example { header: "shadow-lg", container: "top-4" }
38
38
  */
39
- classNames?: CustomClassNames;
39
+ classNames?: HeaderClassNames;
40
40
  }
41
41
 
42
42
  const {
43
43
  headerType = "floating",
44
44
  preset = "auto",
45
- logo = {},
45
+
46
46
  navigation = {},
47
47
  theme = {},
48
48
  classNames = {},
49
49
  } = Astro.props;
50
50
 
51
51
  if (import.meta.env.DEV) {
52
- // Check if logo is being passed as a string (legacy)
53
- if (typeof logo === "string") {
54
- console.warn(
55
- "[@sofidevo/astro-dynamic-header] BREAKING CHANGE: The 'logo' prop now expects an object. Please use logo={{ src: '...' }} instead.",
56
- );
57
- }
52
+
58
53
  if (Array.isArray(navigation)) {
59
54
  console.warn(
60
55
  "[@sofidevo/astro-dynamic-header] BREAKING CHANGE: The 'navigation' prop now expects an object with 'menuItems'. Please use navigation={{ menuItems: [...] }} instead.",
@@ -62,42 +57,36 @@ if (import.meta.env.DEV) {
62
57
  }
63
58
  }
64
59
 
65
- // Default theme configuration
66
- const defaultThemes = {
67
- light: {
68
- backgroundColor: "rgba(255, 255, 255, 0.9)",
69
- backgroundColorOpaque: "rgb(255, 255, 255)",
70
- backdropBlur: "blur(20px)",
71
- zIndex: 10,
72
- textColor: "#1a1a1a",
73
- accentColor: "#3e1c71",
74
- },
75
- dark: {
76
- backgroundColor: "#0d0d0dcc",
77
- backgroundColorOpaque: "#0d0d0d",
78
- backdropBlur: "blur(20px)",
79
- zIndex: 10,
80
- textColor: "#ffffff",
81
- accentColor: "#00ffff",
82
- },
83
- };
84
-
85
- // Merge with user overrides
86
- const lightTheme = { ...defaultThemes.light, ...theme.light };
87
- const darkTheme = { ...defaultThemes.dark, ...theme.dark };
60
+ // Map user theme overrides to CSS custom properties
61
+ const inlineStyles: Record<string, string> = {};
88
62
 
89
- // Navigation configuration
90
- const { homeUrl = "/", menuItems = [] } = navigation;
63
+ if (theme.light) {
64
+ if (theme.light.backgroundColor) inlineStyles["--l-bg"] = theme.light.backgroundColor;
65
+ if (theme.light.backgroundColorOpaque) inlineStyles["--l-bg-opaque"] = theme.light.backgroundColorOpaque;
66
+ if (theme.light.textColor) inlineStyles["--l-text"] = theme.light.textColor;
67
+ if (theme.light.accentColor) inlineStyles["--l-accent"] = theme.light.accentColor;
68
+ if (theme.light.backdropBlur) inlineStyles["--l-blur"] = theme.light.backdropBlur;
69
+ }
70
+ if (theme.dark) {
71
+ if (theme.dark.backgroundColor) inlineStyles["--d-bg"] = theme.dark.backgroundColor;
72
+ if (theme.dark.backgroundColorOpaque) inlineStyles["--d-bg-opaque"] = theme.dark.backgroundColorOpaque;
73
+ if (theme.dark.textColor) inlineStyles["--d-text"] = theme.dark.textColor;
74
+ if (theme.dark.accentColor) inlineStyles["--d-accent"] = theme.dark.accentColor;
75
+ if (theme.dark.backdropBlur) inlineStyles["--d-blur"] = theme.dark.backdropBlur;
76
+ }
91
77
 
92
- // Logo configuration
78
+ const zIndex = theme.light?.zIndex ?? 10;
79
+
80
+ // Navigation configuration
93
81
  const {
94
- src: logoSrc = "/logo.png",
95
- alt: logoAlt = "Logo",
96
- width: logoWidth = "55px",
97
- text: logoText = "",
98
- textSize: logoTextSize = "1em",
99
- textColor: logoTextColor = "inherit", // Will inherit from theme text-color
100
- } = logo;
82
+ homeUrl = "/",
83
+ menuItems = [],
84
+ header__menu__class,
85
+ header__item__class,
86
+ menu__link__class,
87
+ } = navigation;
88
+
89
+
101
90
 
102
91
  const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
103
92
  ---
@@ -150,7 +139,7 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
150
139
  `header__container--${headerType}`,
151
140
  classNames.container,
152
141
  ]}
153
- style={{ zIndex: lightTheme.zIndex }}
142
+ style={{ zIndex }}
154
143
  >
155
144
  <header
156
145
  class:list={[
@@ -159,40 +148,18 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
159
148
  forcedClass,
160
149
  classNames.header,
161
150
  ]}
162
- style={{
163
- "--l-bg": lightTheme.backgroundColor,
164
- "--l-bg-opaque": lightTheme.backgroundColorOpaque,
165
- "--l-text": lightTheme.textColor,
166
- "--l-accent": lightTheme.accentColor,
167
- "--l-blur": lightTheme.backdropBlur,
168
- "--d-bg": darkTheme.backgroundColor,
169
- "--d-bg-opaque": darkTheme.backgroundColorOpaque,
170
- "--d-text": darkTheme.textColor,
171
- "--d-accent": darkTheme.accentColor,
172
- "--d-blur": darkTheme.backdropBlur,
173
- }}
151
+ style={Object.keys(inlineStyles).length > 0 ? inlineStyles : undefined}
174
152
  >
175
- <a class:list={["logo__container", classNames.logo]} href={homeUrl}>
176
- <img
177
- class="header__logo"
178
- src={logoSrc}
179
- alt={logoAlt}
180
- style={{ width: logoWidth }}
181
- />
182
- {
183
- logoText && (
184
- <span
185
- class:list={["header__logo-text", classNames.logoText]}
186
- style={{ color: logoTextColor, fontSize: logoTextSize }}
187
- >
188
- {logoText}
189
- </span>
190
- )
191
- }
192
- </a>
153
+ <slot name="logo" />
193
154
 
194
155
  <div class:list={["nav-menu-wrapper", classNames.nav]}>
195
- <NavMenu menuItems={menuItems} />
156
+ <NavMenu
157
+ menuItems={menuItems}
158
+ homeUrl={homeUrl}
159
+ header__menu__class={header__menu__class}
160
+ header__item__class={header__item__class}
161
+ menu__link__class={menu__link__class}
162
+ />
196
163
  </div>
197
164
 
198
165
  {
@@ -205,7 +172,12 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
205
172
 
206
173
  <HamburgerButton />
207
174
 
208
- <MobileNav menuItems={menuItems} type={headerType}>
175
+ <MobileNav
176
+ menuItems={menuItems}
177
+ homeUrl={homeUrl}
178
+ type={headerType}
179
+ mobileNav__class={classNames.mobileNav}
180
+ >
209
181
  {
210
182
  Astro.slots.has("actions") && (
211
183
  <div class="actions-mobile" slot="slot-panel">
@@ -219,11 +191,11 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
219
191
 
220
192
  <style is:inline>
221
193
  .header {
222
- --bg-color: var(--l-bg);
223
- --bg-color-opaque: var(--l-bg-opaque);
224
- --text-color: var(--l-text);
225
- --accent-color: var(--l-accent);
226
- --backdrop-blur: var(--l-blur);
194
+ --bg-color: var(--l-bg, rgba(255, 255, 255, 0.9));
195
+ --bg-color-opaque: var(--l-bg-opaque, rgb(255, 255, 255));
196
+ --text-color: var(--l-text, #1a1a1a);
197
+ --accent-color: var(--l-accent, #3e1c71);
198
+ --backdrop-blur: var(--l-blur, blur(20px));
227
199
 
228
200
  display: flex;
229
201
  align-items: center;
@@ -247,28 +219,28 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
247
219
 
248
220
  /* Automatic dark mode detection via root class */
249
221
  :root.dark .header:not(.header--force-light) {
250
- --bg-color: var(--d-bg);
251
- --bg-color-opaque: var(--d-bg-opaque);
252
- --text-color: var(--d-text);
253
- --accent-color: var(--d-accent);
254
- --backdrop-blur: var(--d-blur);
222
+ --bg-color: var(--d-bg, #0d0d0dcc);
223
+ --bg-color-opaque: var(--d-bg-opaque, #0d0d0d);
224
+ --text-color: var(--d-text, #ffffff);
225
+ --accent-color: var(--d-accent, #00ffff);
226
+ --backdrop-blur: var(--d-blur, blur(20px));
255
227
  }
256
228
 
257
229
  /* Forced themes */
258
230
  .header--force-dark {
259
- --bg-color: var(--d-bg) !important;
260
- --bg-color-opaque: var(--d-bg-opaque) !important;
261
- --text-color: var(--d-text) !important;
262
- --accent-color: var(--d-accent) !important;
263
- --backdrop-blur: var(--d-blur) !important;
231
+ --bg-color: var(--d-bg, #0d0d0dcc) !important;
232
+ --bg-color-opaque: var(--d-bg-opaque, #0d0d0d) !important;
233
+ --text-color: var(--d-text, #ffffff) !important;
234
+ --accent-color: var(--d-accent, #00ffff) !important;
235
+ --backdrop-blur: var(--d-blur, blur(20px)) !important;
264
236
  }
265
237
 
266
238
  .header--force-light {
267
- --bg-color: var(--l-bg) !important;
268
- --bg-color-opaque: var(--l-bg-opaque) !important;
269
- --text-color: var(--l-text) !important;
270
- --accent-color: var(--l-accent) !important;
271
- --backdrop-blur: var(--l-blur) !important;
239
+ --bg-color: var(--l-bg, rgba(255, 255, 255, 0.9)) !important;
240
+ --bg-color-opaque: var(--l-bg-opaque, rgb(255, 255, 255)) !important;
241
+ --text-color: var(--l-text, #1a1a1a) !important;
242
+ --accent-color: var(--l-accent, #3e1c71) !important;
243
+ --backdrop-blur: var(--l-blur, blur(20px)) !important;
272
244
  }
273
245
 
274
246
  .header__container {
@@ -313,20 +285,7 @@ const forcedClass = preset !== "auto" ? `header--force-${preset}` : "";
313
285
  }
314
286
  }
315
287
 
316
- .logo__container {
317
- display: flex;
318
- align-items: center;
319
- text-decoration: none;
320
- color: inherit;
321
- & span {
322
- font-weight: 600;
323
- }
324
- }
325
288
 
326
- .header__logo {
327
- margin-right: 1em;
328
- object-fit: contain;
329
- }
330
289
 
331
290
  .actions-desktop {
332
291
  @media (width < 768px) {
@@ -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,30 +11,38 @@ 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;
16
+ /** Extra CSS class(es) for the root mobile `<nav>` panel. */
17
+ mobileNav__class?: string;
13
18
  }
14
19
 
15
- const { type } = Astro.props;
16
-
17
20
  const {
21
+ type,
22
+ mobileNav__class,
18
23
  menuItems = [],
19
24
  showHomeLink = true,
20
25
  homeText = "Home",
26
+ homeUrl = "/",
21
27
  } = Astro.props;
22
28
 
23
29
  const pagePathname = Astro.url.pathname;
24
30
  ---
25
31
 
26
32
  <nav
27
- class={`mobile-header__menu mobile-header__menu--${type}`}
33
+ class:list={[
34
+ `mobile-header__menu mobile-header__menu--${type}`,
35
+ mobileNav__class,
36
+ ]}
28
37
  id="mobile-header-menu"
29
38
  >
30
39
  <ol class="mobile-menu">
31
40
  {
32
- showHomeLink && pagePathname !== "/" && (
41
+ showHomeLink && pagePathname !== homeUrl && (
33
42
  <li class="header__item mobile-header__item">
34
43
  <a
35
44
  class="menu__link mobile-menu__link"
36
- href="/"
45
+ href={homeUrl}
37
46
  data-astro-prefetch="hover"
38
47
  >
39
48
  {homeText}
@@ -47,16 +56,13 @@ const pagePathname = Astro.url.pathname;
47
56
  return (
48
57
  <li>
49
58
  {item.submenu ? (
50
- <details class="mobile-details" open={item.submenu.some(sub => pagePathname === sub.link)}>
59
+ <details
60
+ class="mobile-details"
61
+ open={item.submenu.some((sub) => pagePathname === sub.link)}
62
+ >
51
63
  <summary class:list={["menu__summary", { active: isActive }]}>
52
64
  {item.text}
53
- <iconify-icon
54
- class="iconify-arrow"
55
- icon="codicon:triangle-down"
56
- width="15"
57
- height="15"
58
- style="color: var(--accent-color);"
59
- />
65
+ <ChevronIcon class="iconify-arrow" width={15} height={15} />
60
66
  </summary>
61
67
  <ol class="mobile-submenu">
62
68
  {item?.submenu?.map((sub: SecondaryMenuItem) => {
@@ -64,24 +70,37 @@ const pagePathname = Astro.url.pathname;
64
70
  return (
65
71
  <li>
66
72
  {sub.submenu && sub.submenu.length > 0 ? (
67
- <details class="mobile-details" open={sub.submenu.some(subsub => pagePathname === subsub.link)}>
68
- <summary class:list={["menu__summary", { active: isSubActive }]}>
73
+ <details
74
+ class="mobile-details"
75
+ open={sub.submenu.some(
76
+ (subsub) => pagePathname === subsub.link,
77
+ )}
78
+ >
79
+ <summary
80
+ class:list={[
81
+ "menu__summary",
82
+ { active: isSubActive },
83
+ ]}
84
+ >
69
85
  {sub.text}
70
- <iconify-icon
86
+ <ChevronIcon
71
87
  class="iconify-arrow"
72
- icon="codicon:triangle-down"
73
- width="15"
74
- height="15"
75
- style="color: var(--accent-color);"
88
+ width={15}
89
+ height={15}
76
90
  />
77
91
  </summary>
78
92
  <ol class="mobile-subsubmenu">
79
93
  {sub.submenu.map((subsub: TertiaryMenuItem) => {
80
- const isSubSubActive = pagePathname === subsub.link;
94
+ const isSubSubActive =
95
+ pagePathname === subsub.link;
81
96
  return (
82
97
  <li class="mobile-submenu__item secondary">
83
98
  <a
84
- class:list={["menu__link", "mobile-menu__link", { active: isSubSubActive }]}
99
+ class:list={[
100
+ "menu__link",
101
+ "mobile-menu__link",
102
+ { active: isSubSubActive },
103
+ ]}
85
104
  href={subsub.link}
86
105
  >
87
106
  {subsub.text}
@@ -92,7 +111,14 @@ const pagePathname = Astro.url.pathname;
92
111
  </ol>
93
112
  </details>
94
113
  ) : (
95
- <a class:list={["menu__link", "mobile-menu__link", { active: isSubActive }]} href={sub.link}>
114
+ <a
115
+ class:list={[
116
+ "menu__link",
117
+ "mobile-menu__link",
118
+ { active: isSubActive },
119
+ ]}
120
+ href={sub.link}
121
+ >
96
122
  {sub.text}
97
123
  </a>
98
124
  )}
@@ -102,7 +128,10 @@ const pagePathname = Astro.url.pathname;
102
128
  </ol>
103
129
  </details>
104
130
  ) : (
105
- <a class:list={["mobile-menu__link", { active: isActive }]} href={item.link}>
131
+ <a
132
+ class:list={["mobile-menu__link", { active: isActive }]}
133
+ href={item.link}
134
+ >
106
135
  {item.text}
107
136
  </a>
108
137
  )}
@@ -128,7 +157,9 @@ const pagePathname = Astro.url.pathname;
128
157
  left: 0;
129
158
  background: var(--bg-color-opaque, #151515);
130
159
  z-index: 20;
131
- transition: transform 0.3s ease-in-out, background-color 0.3s ease;
160
+ transition:
161
+ transform 0.3s ease-in-out,
162
+ background-color 0.3s ease;
132
163
  transform: translateX(100%);
133
164
  padding: 10rem 2rem 2rem;
134
165
  color: var(--text-color, #fff);
@@ -205,7 +236,7 @@ const pagePathname = Astro.url.pathname;
205
236
  overflow: clip;
206
237
  }
207
238
 
208
- .mobile-details:open iconify-icon {
239
+ .mobile-details:open svg.iconify-arrow {
209
240
  transform: rotate(180deg);
210
241
  }
211
242
 
@@ -0,0 +1,106 @@
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
+ .n1mjuz {
50
+ fill: var(--svg-color--fff, #fff);
51
+ }
52
+ .smogax {
53
+ fill: none;
54
+ stroke: white;
55
+ stroke-linecap: round;
56
+ stroke-linejoin: round;
57
+ stroke-width: var(--svg-stroke-width--2px, 2px);
58
+ d: path(
59
+ "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"
60
+ );
61
+ }
62
+ .t_ev7s {
63
+ d: path("M0 0h24v24H0z");
64
+ }
65
+ .izfmla {
66
+ stroke: white;
67
+ stroke-linecap: round;
68
+ stroke-linejoin: round;
69
+ stroke-width: var(--svg-stroke-width--2px, 2px);
70
+ d: path(
71
+ "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"
72
+ );
73
+ }
74
+ .abf34n {
75
+ fill: none;
76
+ stroke: white;
77
+ stroke-dasharray: 4;
78
+ stroke-linecap: round;
79
+ stroke-linejoin: round;
80
+ }
81
+ .k7_l3l {
82
+ d: path("M12 5h1.5M12 5h-1.5M12 5v1.5M12 5v-1.5");
83
+ }
84
+ .hhuniw {
85
+ d: path("M17 11h1.5M17 11h-1.5M17 11v1.5M17 11v-1.5");
86
+ }
87
+
88
+ .z8cgtd {
89
+ d: path("M20 5h1.5M20 5h-1.5M20 5v1.5M20 5v-1.5");
90
+ }
91
+ .drcfta {
92
+ d: path("M12 4h1.5M12 4h-1.5M12 4v1.5M12 4v-1.5");
93
+ }
94
+ .yij7vx {
95
+ d: path("M18 12h1.5M18 12h-1.5M18 12v1.5M18 12v-1.5");
96
+ }
97
+ .emoajy {
98
+ d: path("M19 4h1.5M19 4h-1.5M19 4v1.5M19 4v-1.5");
99
+ }
100
+ .f1to6s {
101
+ d: path("M13 4h1.5M13 4h-1.5M13 4v1.5M13 4v-1.5");
102
+ }
103
+ .niixso {
104
+ d: path("M19 11h1.5M19 11h-1.5M19 11v1.5M19 11v-1.5");
105
+ }
106
+ </style>