@hubpav/hwio-ui 0.5.0 → 0.6.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/package.json +4 -4
- package/src/components/HWioContactSection.astro +1 -1
- package/src/components/HWioHeader.astro +48 -12
- package/src/components/HWioHubSpotForm.astro +3 -1
- package/src/components/HWioIcon.astro +1 -0
- package/src/integration.d.mts +2 -0
- package/src/integration.mjs +9 -3
- package/src/styles/themes/er3o.css +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubpav/hwio-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "HARDWARIO web design system for Astro: DaisyUI 5 themes generated from the brand tokens, the Tailwind entry stylesheet and the HWio* components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"build": "node scripts/build-themes.mjs"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@hubpav/hwio-brand": "0.
|
|
35
|
-
"@hubpav/hwio-web-runtime": "0.
|
|
36
|
-
"@hubpav/hwio-web-worker": "0.
|
|
34
|
+
"@hubpav/hwio-brand": "0.6.0",
|
|
35
|
+
"@hubpav/hwio-web-runtime": "0.6.0",
|
|
36
|
+
"@hubpav/hwio-web-worker": "0.6.0",
|
|
37
37
|
"daisyui": "5.7.28"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -26,7 +26,7 @@ const { id = 'contact', eyebrow, title, lead, person, tone = 'alt', class: class
|
|
|
26
26
|
<p class="font-semibold">{person.name}</p>
|
|
27
27
|
{person.role && <p class="opacity-80">{person.role}</p>}
|
|
28
28
|
{person.email && <a href={`mailto:${person.email}`} class="link link-hover inline-flex items-center gap-1"><HWioIcon name="mail" size="sm" />{person.email}</a>}
|
|
29
|
-
{person.phone && <a href={person.phoneHref ?? `tel:${person.phone.replace(/\s+/g, '')}`} class="link link-hover ml-3 inline-flex items-center gap-1"><HWioIcon name="phone" size="sm" />{person.phone}</a>}
|
|
29
|
+
{person.phone && <a href={person.phoneHref ?? `tel:${person.phone.replace(/\s+/g, '')}`} class="link link-hover ml-3 inline-flex items-center gap-1 whitespace-nowrap"><HWioIcon name="phone" size="sm" />{person.phone}</a>}
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
32
|
)}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
/**
|
|
3
|
-
* Sticky site header: logo slot, primary nav (flat links
|
|
4
|
-
* CTAs, language switcher, theme toggle, and a DaisyUI drawer for small
|
|
3
|
+
* Sticky site header: logo slot, primary nav (flat links, or mega items whose `mega:<key>` slot opens as a
|
|
4
|
+
* full-width panel under the bar), CTAs, language switcher, theme toggle, and a DaisyUI drawer for small
|
|
5
|
+
* screens, where a mega item lists its `children` as a collapsible group instead.
|
|
5
6
|
*/
|
|
6
7
|
import type { HWioCta, HWioLinkItem } from '../types';
|
|
7
8
|
import HWioButton from './HWioButton.astro';
|
|
@@ -9,7 +10,12 @@ import HWioIcon from './HWioIcon.astro';
|
|
|
9
10
|
import HWioLanguageSwitcher from './HWioLanguageSwitcher.astro';
|
|
10
11
|
import HWioThemeToggle from './HWioThemeToggle.astro';
|
|
11
12
|
|
|
12
|
-
interface NavItem extends HWioLinkItem {
|
|
13
|
+
interface NavItem extends HWioLinkItem {
|
|
14
|
+
/** Key of the `mega:<key>` slot; the item becomes a button that opens the panel (hover, click, keyboard). */
|
|
15
|
+
mega?: string;
|
|
16
|
+
/** Links listed under the item in the drawer (the panel is desktop-only); a description renders as a second, muted line. */
|
|
17
|
+
children?: (HWioLinkItem & { description?: string })[];
|
|
18
|
+
}
|
|
13
19
|
interface Props {
|
|
14
20
|
nav: NavItem[];
|
|
15
21
|
ctas?: HWioCta[];
|
|
@@ -24,11 +30,13 @@ interface Props {
|
|
|
24
30
|
}
|
|
25
31
|
const { nav, ctas = [], languages = [], showThemeToggle = true, scrollspy = false, labels, desktopFrom = 'lg', id = 'hwio-nav-drawer', class: className = '' } = Astro.props;
|
|
26
32
|
const BREAK = {
|
|
27
|
-
lg: { nav: 'hidden flex-1 justify-center lg:flex', ctas: 'hidden items-center gap-2 lg:flex', drawer: 'drawer drawer-end w-auto lg:hidden' },
|
|
28
|
-
xl: { nav: 'hidden flex-1 justify-center xl:flex', ctas: 'hidden items-center gap-2 xl:flex', drawer: 'drawer drawer-end w-auto xl:hidden' },
|
|
33
|
+
lg: { nav: 'hidden flex-1 justify-center lg:flex', ctas: 'hidden items-center gap-2 lg:flex', drawer: 'drawer drawer-end w-auto lg:hidden', panels: 'hidden lg:block' },
|
|
34
|
+
xl: { nav: 'hidden flex-1 justify-center xl:flex', ctas: 'hidden items-center gap-2 xl:flex', drawer: 'drawer drawer-end w-auto xl:hidden', panels: 'hidden xl:block' },
|
|
29
35
|
} as const;
|
|
30
36
|
const bp = BREAK[desktopFrom];
|
|
31
37
|
const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost' } as const;
|
|
38
|
+
const megaItems = nav.filter((item) => item.mega);
|
|
39
|
+
const linkAttrs = (item: HWioLinkItem) => (item.external ? { target: '_blank', rel: 'noopener noreferrer' } : {});
|
|
32
40
|
---
|
|
33
41
|
<header class:list={['sticky top-0 z-50 border-b border-base-300 bg-base-100/90 backdrop-blur supports-[backdrop-filter]:bg-base-100/80', className]} data-hwio-font-exempt>
|
|
34
42
|
<div class="container flex h-16 items-center gap-4 lg:h-[72px]">
|
|
@@ -41,12 +49,10 @@ const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost'
|
|
|
41
49
|
{nav.map((item) => (
|
|
42
50
|
<li>
|
|
43
51
|
{item.mega ? (
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
</div>
|
|
49
|
-
</details>
|
|
52
|
+
<button type="button" class="px-3 text-[15px] font-medium text-base-content/80 hover:text-accent" data-hwio-mega-trigger={item.mega} aria-expanded="false" aria-haspopup="true" aria-controls={`${id}-mega-${item.mega}`}>
|
|
53
|
+
{item.label}
|
|
54
|
+
<HWioIcon name="chevron-down" size="sm" class="opacity-50 transition-transform duration-200" />
|
|
55
|
+
</button>
|
|
50
56
|
) : (
|
|
51
57
|
<a href={item.href} class="px-3 text-[15px] font-medium text-base-content/80 hover:text-accent" aria-current={item.current ? 'page' : undefined} data-track={item.track?.id} data-track-location={item.track?.location ?? 'header'}>{item.label}</a>
|
|
52
58
|
)}
|
|
@@ -81,7 +87,28 @@ const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost'
|
|
|
81
87
|
</div>
|
|
82
88
|
<ul class="menu w-full text-base">
|
|
83
89
|
{nav.map((item) => (
|
|
84
|
-
<li
|
|
90
|
+
<li>
|
|
91
|
+
{item.children?.length ? (
|
|
92
|
+
<details>
|
|
93
|
+
<summary>{item.label}</summary>
|
|
94
|
+
<ul>
|
|
95
|
+
{item.children.map((child) => (
|
|
96
|
+
<li>
|
|
97
|
+
<a href={child.href} {...linkAttrs(child)} data-track={child.track?.id} data-track-location="mobile-menu">
|
|
98
|
+
{/* One grid cell: DaisyUI lays menu items out as a column-flow grid, so the two lines nest in one span. */}
|
|
99
|
+
<span class="flex flex-col items-start gap-0.5">
|
|
100
|
+
<span class="inline-flex items-center gap-1">{child.label}{child.external && <HWioIcon name="external" size="sm" class="opacity-50" />}</span>
|
|
101
|
+
{child.description && <span class="text-xs font-normal leading-snug opacity-70">{child.description}</span>}
|
|
102
|
+
</span>
|
|
103
|
+
</a>
|
|
104
|
+
</li>
|
|
105
|
+
))}
|
|
106
|
+
</ul>
|
|
107
|
+
</details>
|
|
108
|
+
) : (
|
|
109
|
+
<a href={item.href} {...linkAttrs(item)} aria-current={item.current ? 'page' : undefined} data-track={item.track?.id} data-track-location="mobile-menu">{item.label}</a>
|
|
110
|
+
)}
|
|
111
|
+
</li>
|
|
85
112
|
))}
|
|
86
113
|
</ul>
|
|
87
114
|
<div class="mt-4 flex flex-col gap-2">
|
|
@@ -95,6 +122,15 @@ const CTA_VARIANT = { primary: 'primary', secondary: 'secondary', ghost: 'ghost'
|
|
|
95
122
|
</div>
|
|
96
123
|
</div>
|
|
97
124
|
</div>
|
|
125
|
+
{megaItems.length > 0 && (
|
|
126
|
+
<div class={bp.panels}>
|
|
127
|
+
{megaItems.map((item) => (
|
|
128
|
+
<div id={`${id}-mega-${item.mega}`} class="absolute inset-x-0 top-full border-t border-base-300 bg-base-100 shadow-xl" data-hwio-mega-panel={item.mega} hidden>
|
|
129
|
+
<div class="container py-8"><slot name={`mega:${item.mega}`} /></div>
|
|
130
|
+
</div>
|
|
131
|
+
))}
|
|
132
|
+
</div>
|
|
133
|
+
)}
|
|
98
134
|
</header>
|
|
99
135
|
<script>
|
|
100
136
|
import { hwioNavRuntime } from '@hubpav/hwio-web-runtime/nav';
|
|
@@ -9,7 +9,8 @@ import HWioTurnstile from './HWioTurnstile.astro';
|
|
|
9
9
|
interface Props {
|
|
10
10
|
form: { key: string; guid: string; endpoint: string; event?: 'generate_lead' | 'newsletter_signup'; enrich?: boolean; kind?: string; source?: string };
|
|
11
11
|
fields: HWioFieldDef[];
|
|
12
|
-
|
|
12
|
+
/** turnstile: shown when the anti-spam widget produced no token (falls back to `error`). */
|
|
13
|
+
labels: { submit: string; sending: string; success: string; error: string; turnstile?: string };
|
|
13
14
|
locale: string;
|
|
14
15
|
turnstileSiteKey?: string;
|
|
15
16
|
layout?: 'grid' | 'inline';
|
|
@@ -33,6 +34,7 @@ const LAYOUT = { grid: 'grid gap-4 md:grid-cols-2', inline: 'flex flex-col gap-3
|
|
|
33
34
|
data-hs-sending-msg={labels.sending}
|
|
34
35
|
data-hs-success-msg={labels.success}
|
|
35
36
|
data-hs-error-msg={labels.error}
|
|
37
|
+
data-hs-turnstile-msg={labels.turnstile}
|
|
36
38
|
>
|
|
37
39
|
<div class={LAYOUT[layout]}>
|
|
38
40
|
{fields.map((field) => <HWioFormField field={field} />)}
|
|
@@ -29,6 +29,7 @@ const FILL = {
|
|
|
29
29
|
x: 'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z',
|
|
30
30
|
instagram: 'M7.8 2h8.4C19.4 2 22 4.6 22 7.8v8.4a5.8 5.8 0 0 1-5.8 5.8H7.8C4.6 22 2 19.4 2 16.2V7.8A5.8 5.8 0 0 1 7.8 2m-.2 2A3.6 3.6 0 0 0 4 7.6v8.8C4 18.39 5.61 20 7.6 20h8.8a3.6 3.6 0 0 0 3.6-3.6V7.6C20 5.61 18.39 4 16.4 4H7.6m9.65 1.5a1.25 1.25 0 0 1 1.25 1.25A1.25 1.25 0 0 1 17.25 8 1.25 1.25 0 0 1 16 6.75a1.25 1.25 0 0 1 1.25-1.25M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3Z',
|
|
31
31
|
youtube: 'M10 15l5.19-3L10 9v6m11.56-7.83c.13.47.22 1.1.28 1.9.07.8.1 1.49.1 2.09L22 12c0 2.19-.16 3.8-.44 4.83-.25.9-.83 1.48-1.73 1.73-.47.13-1.33.22-2.65.28-1.3.07-2.49.1-3.59.1L12 19c-4.19 0-6.8-.16-7.83-.44-.9-.25-1.48-.83-1.73-1.73-.13-.47-.22-1.1-.28-1.9-.07-.8-.1-1.49-.1-2.09L2 12c0-2.19.16-3.8.44-4.83.25-.9.83-1.48 1.73-1.73.47-.13 1.33-.22 2.65-.28 1.3-.07 2.49-.1 3.59-.1L12 5c4.19 0 6.8.16 7.83.44.9.25 1.48.83 1.73 1.73Z',
|
|
32
|
+
facebook: 'M22 12c0-5.52-4.48-10-10-10S2 6.48 2 12c0 4.84 3.44 8.87 8 9.8V15H8v-3h2V9.5C10 7.57 11.57 6 13.5 6H16v3h-2c-.55 0-1 .45-1 1v2h3v3h-3v6.95c5.05-.5 9-4.76 9-9.95Z',
|
|
32
33
|
github: 'M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34-.46-1.16-1.11-1.47-1.11-1.47-.91-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.87 1.52 2.34 1.07 2.91.83.09-.65.35-1.09.63-1.34-2.22-.25-4.55-1.11-4.55-4.92 0-1.11.38-2 1.03-2.71-.1-.25-.45-1.29.1-2.64 0 0 .84-.27 2.75 1.02.79-.22 1.65-.33 2.5-.33.85 0 1.71.11 2.5.33 1.91-1.29 2.75-1.02 2.75-1.02.55 1.35.2 2.39.1 2.64.65.71 1.03 1.6 1.03 2.71 0 3.82-2.34 4.66-4.57 4.91.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2Z',
|
|
33
34
|
forum: 'M12 3C6.5 3 2 6.58 2 11a7.218 7.218 0 0 0 2.75 5.5c0 .6-.42 2.17-2.75 4.5 2.37-.11 4.64-1 6.47-2.5H12c5.5 0 10-3.58 10-8s-4.5-8-10-8Z',
|
|
34
35
|
} as const;
|
package/src/integration.d.mts
CHANGED
|
@@ -5,5 +5,7 @@ export interface HWioUiOptions {
|
|
|
5
5
|
headers?: HWioHeadersOptions | false;
|
|
6
6
|
/** Serve the brand fonts and logos in dev and copy them into the build output. */
|
|
7
7
|
assets?: boolean;
|
|
8
|
+
/** Font families copied into /fonts (file-name prefixes in @hubpav/hwio-brand/dist/fonts). Default ['inter']. */
|
|
9
|
+
fonts?: string[];
|
|
8
10
|
}
|
|
9
11
|
export function hwioUi(options?: HWioUiOptions): AstroIntegration;
|
package/src/integration.mjs
CHANGED
|
@@ -19,11 +19,12 @@ function brandDir() {
|
|
|
19
19
|
const MIME = { '.woff2': 'font/woff2', '.svg': 'image/svg+xml', '.png': 'image/png', '.ico': 'image/x-icon' };
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
* @param {{ headers?: import('@hubpav/hwio-web-worker/headers').HWioHeadersOptions | false, assets?: boolean }} [options]
|
|
22
|
+
* @param {{ headers?: import('@hubpav/hwio-web-worker/headers').HWioHeadersOptions | false, assets?: boolean, fonts?: string[] }} [options]
|
|
23
|
+
* fonts: font families (file-name prefixes in @hubpav/hwio-brand/dist/fonts) copied to /fonts; default ['inter'].
|
|
23
24
|
* @returns {import('astro').AstroIntegration}
|
|
24
25
|
*/
|
|
25
26
|
export function hwioUi(options = {}) {
|
|
26
|
-
const { headers = false, assets = true } = options;
|
|
27
|
+
const { headers = false, assets = true, fonts = ['inter'] } = options;
|
|
27
28
|
const brand = brandDir();
|
|
28
29
|
const fontsDir = join(brand, 'dist/fonts');
|
|
29
30
|
const logosDir = join(brand, 'logos');
|
|
@@ -51,7 +52,12 @@ export function hwioUi(options = {}) {
|
|
|
51
52
|
for (const [src, dest] of [[fontsDir, 'fonts'], [logosDir, 'brand']]) {
|
|
52
53
|
if (!existsSync(src)) continue;
|
|
53
54
|
mkdirSync(join(out, dest), { recursive: true });
|
|
54
|
-
for (const f of readdirSync(src))
|
|
55
|
+
for (const f of readdirSync(src)) {
|
|
56
|
+
if (extname(f) === '.css') continue;
|
|
57
|
+
// Only the families the site's themes use (a HARDWARIO site never serves Poppins, enerooo never Inter).
|
|
58
|
+
if (dest === 'fonts' && !fonts.some((family) => f.startsWith(`${family}-`))) continue;
|
|
59
|
+
copyFileSync(join(src, f), join(out, dest, f));
|
|
60
|
+
}
|
|
55
61
|
}
|
|
56
62
|
}
|
|
57
63
|
if (headers) writeFileSync(join(out, '_headers'), hwioRenderHeadersFile(headers));
|