@yatoday/astro-ui 0.18.2 → 0.18.4
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/components/Analytics/AnalyticsGTM.astro +3 -3
- package/components/Analytics/AnalyticsGTMBody.astro +16 -12
- package/components/Analytics/AnalyticsGoogle.astro +3 -1
- package/components/BreadcrumbsItem/BreadcrumbsItem.astro +8 -1
- package/components/Button/types.ts +2 -1
- package/components/CallToAction/CallToAction.astro +1 -1
- package/components/Card0/Card0.astro +20 -32
- package/components/Card1/Card1.astro +11 -19
- package/components/Card2/Card2.astro +10 -14
- package/components/Card3/Card3.astro +15 -20
- package/components/Card4/Card4.astro +6 -2
- package/components/Card5/Card5.astro +8 -1
- package/components/Card6/Card6.astro +76 -59
- package/components/Card7/Card7.astro +27 -18
- package/components/CookieConsent/CookieConsent.astro +323 -308
- package/components/CopyToClipboard/CopyToClipboard.astro +6 -14
- package/components/CopyToClipboard/copy.ts +1 -1
- package/components/DarkMode/__tests__/DarkMode.test.ts +8 -8
- package/components/Headline/Headline.astro +4 -1
- package/components/HeroSection/HeroSection.astro +13 -16
- package/components/Image/Image.astro +1 -7
- package/components/ImageGallery/ImageGallery.astro +85 -90
- package/components/ImageGalleryIkea/ImageGalleryIkea.astro +3 -2
- package/components/ImagePreload/ImagePreload.astro +22 -20
- package/components/ItemGrid1/ItemGrid1.astro +34 -24
- package/components/Metadata/Metadata.astro +1 -5
- package/components/PointMap/PointMap.astro +62 -48
- package/components/PointMap/types.ts +3 -3
- package/components/SEO/SEO.astro +34 -33
- package/components/WidgetBrands/WidgetBrands.astro +8 -1
- package/components/WidgetContent/WidgetContent.astro +22 -9
- package/components/WidgetContent/types.ts +1 -1
- package/components/WidgetFeaturesCard/WidgetFeaturesCard.astro +10 -2
- package/components/WidgetHeroSlider/WidgetHeroSlider.astro +6 -1
- package/components/WidgetNavbarFlyout/WidgetNavbarFlyout.astro +16 -7
- package/components/WidgetSwiperPhotoSlider/WidgetSwiperPhotoSlider.astro +18 -7
- package/components/WidgetTestimonials/WidgetTestimonials.astro +8 -1
- package/components/WidgetWrapper/WidgetWrapper.astro +11 -2
- package/index.d.ts +20 -20
- package/package.json +11 -9
- package/styles/styles.css +303 -160
- package/utils/i18n.ts +2 -2
- package/utils/images.ts +0 -1
- package/utils/slugify.ts +3 -0
- package/vendor-config/config.example.yaml +0 -1
- package/vendor-config/index.ts +1 -1
- package/vendor-config/utils/loadConfig.ts +15 -18
|
@@ -1,56 +1,60 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type {PointMapProps as Props} from './types';
|
|
3
|
-
import {cn, id} from
|
|
2
|
+
import type { PointMapProps as Props } from './types';
|
|
3
|
+
import { cn, id } from '../../utils';
|
|
4
4
|
import Card7 from '../Card7/Card7.astro';
|
|
5
5
|
|
|
6
6
|
const {
|
|
7
7
|
via = Card7,
|
|
8
8
|
items = [],
|
|
9
9
|
pointsDisplayMode = 'always', // default to always visible
|
|
10
|
-
classes = {}
|
|
10
|
+
classes = {},
|
|
11
11
|
} = Astro.props;
|
|
12
12
|
|
|
13
13
|
const mapId = `map-${id()}`;
|
|
14
14
|
|
|
15
|
-
const {
|
|
16
|
-
container: containerClass = '',
|
|
17
|
-
popup: popupClass = '',
|
|
18
|
-
} = classes;
|
|
15
|
+
const { container: containerClass = '', popup: popupClass = '' } = classes;
|
|
19
16
|
|
|
20
17
|
const Component = via;
|
|
21
18
|
---
|
|
22
19
|
|
|
23
20
|
<div id={mapId} class={cn(`map-picker relative h-full w-full points-${pointsDisplayMode}`, containerClass)}>
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
</button>
|
|
36
|
-
|
|
37
|
-
<!-- Popup content (hidden by default) -->
|
|
38
|
-
<div
|
|
39
|
-
class={cn("popup-content absolute rounded-md shadow-lg z-10 max-w-xs hidden", popupClass)}
|
|
40
|
-
style={`left: ${point.x}%; top: ${point.y}%; transform: translate(${point.x > 50 ? '-100%' : '0'}, ${point.y > 50 ? '-100%' : '0'});`}
|
|
41
|
-
data-popup={i}
|
|
42
|
-
data-map-id={mapId}
|
|
43
|
-
>
|
|
44
|
-
<Component
|
|
45
|
-
{...point}
|
|
46
|
-
classes={Object.assign({container: 'border-transparent dark:border-input'}, classes?.card || {}, point?.classes || {}) as Record<string, string>}
|
|
21
|
+
{
|
|
22
|
+
items.map((point, i) => (
|
|
23
|
+
<>
|
|
24
|
+
{/* Hotspot point */}
|
|
25
|
+
<button
|
|
26
|
+
class="hotspot-point cursor-pointer"
|
|
27
|
+
style={`left: ${point.x}%; top: ${point.y}%; width: 24px; height: 24px; transform: translate(-50%, -50%);`}
|
|
28
|
+
data-index={i}
|
|
29
|
+
data-map-id={mapId}
|
|
30
|
+
aria-label={point.title}
|
|
31
|
+
{...(point.isPopupOpen ? { 'data-initially-open': '' } : {})}
|
|
47
32
|
/>
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
33
|
+
|
|
34
|
+
{/* Popup content (hidden by default) */}
|
|
35
|
+
<div
|
|
36
|
+
class={cn('popup-content absolute rounded-md shadow-lg z-10 max-w-xs hidden', popupClass)}
|
|
37
|
+
style={`left: ${point.x}%; top: ${point.y}%; transform: translate(${point.x > 50 ? '-100%' : '0'}, ${point.y > 50 ? '-100%' : '0'});`}
|
|
38
|
+
data-popup={i}
|
|
39
|
+
data-map-id={mapId}
|
|
40
|
+
>
|
|
41
|
+
<Component
|
|
42
|
+
{...point}
|
|
43
|
+
classes={
|
|
44
|
+
Object.assign(
|
|
45
|
+
{ container: 'border-transparent dark:border-input' },
|
|
46
|
+
classes?.card || {},
|
|
47
|
+
point?.classes || {}
|
|
48
|
+
) as Record<string, string>
|
|
49
|
+
}
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
</>
|
|
53
|
+
))
|
|
54
|
+
}
|
|
51
55
|
|
|
52
56
|
<div class="w-full h-full">
|
|
53
|
-
<slot/>
|
|
57
|
+
<slot />
|
|
54
58
|
</div>
|
|
55
59
|
</div>
|
|
56
60
|
|
|
@@ -70,7 +74,9 @@ const Component = via;
|
|
|
70
74
|
.points-hover .hotspot-point {
|
|
71
75
|
opacity: 0;
|
|
72
76
|
visibility: hidden;
|
|
73
|
-
transition:
|
|
77
|
+
transition:
|
|
78
|
+
opacity 250ms ease-in-out,
|
|
79
|
+
visibility 250ms ease-in-out;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
.points-hover:hover .hotspot-point,
|
|
@@ -81,7 +87,10 @@ const Component = via;
|
|
|
81
87
|
|
|
82
88
|
.hotspot-point {
|
|
83
89
|
box-sizing: border-box;
|
|
84
|
-
transition:
|
|
90
|
+
transition:
|
|
91
|
+
border-color 250ms ease-in-out,
|
|
92
|
+
opacity 250ms ease-in-out,
|
|
93
|
+
visibility 250ms ease-in-out;
|
|
85
94
|
transform: translateX(-1rem) translateY(-1rem) scale(0.999);
|
|
86
95
|
padding: 0;
|
|
87
96
|
width: 2rem;
|
|
@@ -91,14 +100,14 @@ const Component = via;
|
|
|
91
100
|
position: absolute;
|
|
92
101
|
background-color: rgba(17, 17, 17, 0.75);
|
|
93
102
|
border-radius: 64px;
|
|
94
|
-
line-height: .5;
|
|
103
|
+
line-height: 0.5;
|
|
95
104
|
display: flex;
|
|
96
105
|
align-items: center;
|
|
97
106
|
justify-content: center;
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
.hotspot-point::before {
|
|
101
|
-
content:
|
|
110
|
+
content: '';
|
|
102
111
|
position: absolute;
|
|
103
112
|
top: -0.5rem;
|
|
104
113
|
left: -0.5rem;
|
|
@@ -108,18 +117,19 @@ const Component = via;
|
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
.hotspot-point::after {
|
|
111
|
-
content:
|
|
120
|
+
content: '';
|
|
112
121
|
position: relative;
|
|
113
122
|
display: block;
|
|
114
123
|
background: rgb(255, 255, 255);
|
|
115
124
|
box-shadow: 0 1px 4px rgba(17, 17, 17, 0.55);
|
|
116
|
-
width: .75rem;
|
|
117
|
-
height: .75rem;
|
|
125
|
+
width: 0.75rem;
|
|
126
|
+
height: 0.75rem;
|
|
118
127
|
border-radius: 64px;
|
|
119
128
|
transition: transform 250ms ease-in-out;
|
|
120
129
|
}
|
|
121
130
|
|
|
122
|
-
.hotspot-point:active,
|
|
131
|
+
.hotspot-point:active,
|
|
132
|
+
.hotspot-point:hover {
|
|
123
133
|
background-color: rgba(17, 17, 17, 0.9);
|
|
124
134
|
}
|
|
125
135
|
|
|
@@ -139,13 +149,15 @@ const Component = via;
|
|
|
139
149
|
const MAP_ID_ATTRIBUTE = 'data-map-id';
|
|
140
150
|
|
|
141
151
|
// Initialize each map component separately
|
|
142
|
-
document.querySelectorAll('.map-picker').forEach(mapContainer => {
|
|
152
|
+
document.querySelectorAll('.map-picker').forEach((mapContainer) => {
|
|
143
153
|
const mapId = mapContainer.id;
|
|
144
154
|
if (!mapId) return;
|
|
145
155
|
|
|
146
156
|
// Get all hotspot points and popups for this specific map
|
|
147
157
|
const hotspotPoints = document.querySelectorAll(`.hotspot-point[${MAP_ID_ATTRIBUTE}="${mapId}"]`);
|
|
148
|
-
const popups = document.querySelectorAll(
|
|
158
|
+
const popups = document.querySelectorAll(
|
|
159
|
+
`.popup-content[${MAP_ID_ATTRIBUTE}="${mapId}"]`
|
|
160
|
+
) as NodeListOf<HTMLElement>;
|
|
149
161
|
|
|
150
162
|
if (!hotspotPoints.length || !popups.length) return;
|
|
151
163
|
|
|
@@ -196,7 +208,9 @@ const Component = via;
|
|
|
196
208
|
return;
|
|
197
209
|
}
|
|
198
210
|
|
|
199
|
-
const point = document.querySelector(
|
|
211
|
+
const point = document.querySelector(
|
|
212
|
+
`.hotspot-point[data-index="${popupIndex}"][${MAP_ID_ATTRIBUTE}="${mapId}"]`
|
|
213
|
+
) as HTMLElement;
|
|
200
214
|
if (!point) return;
|
|
201
215
|
const coordinates = getPointCoordinates(point);
|
|
202
216
|
const translateX = coordinates.x > 50 ? '-100%' : '0';
|
|
@@ -214,7 +228,7 @@ const Component = via;
|
|
|
214
228
|
function getPointCoordinates(pointElement: HTMLElement): PointCoordinates {
|
|
215
229
|
return {
|
|
216
230
|
x: parseFloat(pointElement.style.left) || 0,
|
|
217
|
-
y: parseFloat(pointElement.style.top) || 0
|
|
231
|
+
y: parseFloat(pointElement.style.top) || 0,
|
|
218
232
|
};
|
|
219
233
|
}
|
|
220
234
|
|
|
@@ -258,13 +272,13 @@ const Component = via;
|
|
|
258
272
|
|
|
259
273
|
// Hide all popups (including initially open ones)
|
|
260
274
|
function hideAllPopups() {
|
|
261
|
-
popups.forEach(popup => {
|
|
275
|
+
popups.forEach((popup) => {
|
|
262
276
|
popup.classList.add('hidden');
|
|
263
277
|
});
|
|
264
278
|
}
|
|
265
279
|
|
|
266
280
|
// Add event listeners to hotspot points
|
|
267
|
-
hotspotPoints.forEach(point => {
|
|
281
|
+
hotspotPoints.forEach((point) => {
|
|
268
282
|
const index = getPointIndex(point);
|
|
269
283
|
if (index === null) return;
|
|
270
284
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {HotspotPoint} from
|
|
1
|
+
import type { HotspotPoint } from '../../types';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
|
|
4
4
|
export type PointMapProps = {
|
|
@@ -6,7 +6,7 @@ export type PointMapProps = {
|
|
|
6
6
|
items: HotspotPoint[];
|
|
7
7
|
pointsDisplayMode?: 'always' | 'hover' | undefined; // controls visibility of hotspot points
|
|
8
8
|
classes?: Record<string, string>;
|
|
9
|
-
}
|
|
9
|
+
};
|
|
10
10
|
|
|
11
11
|
export type SveltePointMapProps = {
|
|
12
12
|
via?: any;
|
|
@@ -14,4 +14,4 @@ export type SveltePointMapProps = {
|
|
|
14
14
|
pointsDisplayMode?: 'always' | 'hover' | undefined;
|
|
15
15
|
classes?: Record<string, string>;
|
|
16
16
|
children?: Snippet;
|
|
17
|
-
}
|
|
17
|
+
};
|
package/components/SEO/SEO.astro
CHANGED
|
@@ -65,45 +65,46 @@ const getOGLocale = (loc: string): string => {
|
|
|
65
65
|
};
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
-
<!-- Primary Meta Tags -->
|
|
69
|
-
{title && <title>{title}</title>}
|
|
68
|
+
<!-- Primary Meta Tags -->{title && <title>{title}</title>}
|
|
70
69
|
{description && <meta name="description" content={description} />}
|
|
71
70
|
{canonical && <link rel="canonical" href={canonical} />}
|
|
72
71
|
<meta name="robots" content={robotsContent} />
|
|
73
72
|
|
|
74
73
|
<!-- Open Graph / Facebook -->
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
74
|
+
{
|
|
75
|
+
openGraph && (
|
|
76
|
+
<>
|
|
77
|
+
{openGraph.title && <meta property="og:title" content={openGraph.title} />}
|
|
78
|
+
{openGraph.description && <meta property="og:description" content={openGraph.description} />}
|
|
79
|
+
{openGraph.url && <meta property="og:url" content={openGraph.url} />}
|
|
80
|
+
{openGraph.type && <meta property="og:type" content={openGraph.type} />}
|
|
81
|
+
{openGraph.image && (
|
|
82
|
+
<>
|
|
83
|
+
<meta property="og:image" content={openGraph.image.url} />
|
|
84
|
+
{openGraph.image.width && <meta property="og:image:width" content={openGraph.image.width.toString()} />}
|
|
85
|
+
{openGraph.image.height && <meta property="og:image:height" content={openGraph.image.height.toString()} />}
|
|
86
|
+
{openGraph.image.alt && <meta property="og:image:alt" content={openGraph.image.alt} />}
|
|
87
|
+
</>
|
|
88
|
+
)}
|
|
89
|
+
<meta property="og:locale" content={getOGLocale(locale)} />
|
|
90
|
+
{openGraph.siteName && <meta property="og:site_name" content={openGraph.siteName} />}
|
|
91
|
+
</>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
93
94
|
|
|
94
95
|
<!-- Alternate Language Links (hreflang) -->
|
|
95
|
-
{alternateLocales.map(({ locale: altLocale, url }) =>
|
|
96
|
-
<link rel="alternate" hreflang={altLocale} href={url} />
|
|
97
|
-
))}
|
|
96
|
+
{alternateLocales.map(({ locale: altLocale, url }) => <link rel="alternate" hreflang={altLocale} href={url} />)}
|
|
98
97
|
|
|
99
98
|
<!-- Twitter Card -->
|
|
100
|
-
{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
{
|
|
100
|
+
twitter && (
|
|
101
|
+
<>
|
|
102
|
+
<meta name="twitter:card" content={twitter.card || 'summary_large_image'} />
|
|
103
|
+
{twitter.site && <meta name="twitter:site" content={twitter.site} />}
|
|
104
|
+
{twitter.creator && <meta name="twitter:creator" content={twitter.creator} />}
|
|
105
|
+
{twitter.title && <meta name="twitter:title" content={twitter.title} />}
|
|
106
|
+
{twitter.description && <meta name="twitter:description" content={twitter.description} />}
|
|
107
|
+
{twitter.image && <meta name="twitter:image" content={twitter.image} />}
|
|
108
|
+
</>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
@@ -29,7 +29,14 @@ const {
|
|
|
29
29
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
30
30
|
bg={bg}
|
|
31
31
|
>
|
|
32
|
-
<Headline
|
|
32
|
+
<Headline
|
|
33
|
+
title={title}
|
|
34
|
+
subtitle={subtitle}
|
|
35
|
+
tagline={tagline}
|
|
36
|
+
position={position}
|
|
37
|
+
as={asHeader}
|
|
38
|
+
asSubtitle={asSubtitle}
|
|
39
|
+
/>
|
|
33
40
|
|
|
34
41
|
<div class="flex flex-wrap justify-center gap-x-6 sm:gap-x-12 lg:gap-x-24">
|
|
35
42
|
{
|
|
@@ -50,7 +50,7 @@ const {
|
|
|
50
50
|
/>
|
|
51
51
|
|
|
52
52
|
<div class={`md:flex ${isReversed ? 'md:flex-row-reverse' : ''} md:gap-16`}>
|
|
53
|
-
<div class={cn(
|
|
53
|
+
<div class={cn('md:basis-1/2 self-center', classes?.start ?? '')}>
|
|
54
54
|
<slot />
|
|
55
55
|
{content && <div class={cn('mb-12 text-lg', classes?.content ?? '')} set:html={content} />}
|
|
56
56
|
|
|
@@ -70,21 +70,34 @@ const {
|
|
|
70
70
|
icon={defaultIcon}
|
|
71
71
|
{...item}
|
|
72
72
|
classes={{
|
|
73
|
-
container: cn(
|
|
74
|
-
|
|
73
|
+
container: cn(
|
|
74
|
+
'gap-0 border-0 py-0 justify-start',
|
|
75
|
+
(classes?.items as Record<string, string>)?.container
|
|
76
|
+
),
|
|
77
|
+
title: cn(
|
|
78
|
+
'text-lg font-medium leading-6 dark:text-white ml-2 rtl:ml-0 rtl:mr-2',
|
|
79
|
+
(classes?.items as Record<string, string>)?.title
|
|
80
|
+
),
|
|
75
81
|
description: cn('ml-2 rtl:ml-0 rtl:mr-2', (classes?.items as Record<string, string>)?.description),
|
|
76
|
-
icon: cn(
|
|
82
|
+
icon: cn(
|
|
83
|
+
'flex h-7 w-7 items-center justify-center rounded-full bg-green-600 dark:bg-green-700 text-gray-50 p-1',
|
|
84
|
+
(classes?.items as Record<string, string>)?.icon
|
|
85
|
+
),
|
|
77
86
|
}}
|
|
78
87
|
/>
|
|
79
88
|
))
|
|
80
89
|
}
|
|
81
90
|
</ItemGrid0>
|
|
82
91
|
</div>
|
|
83
|
-
<div aria-hidden="true" class={cn(
|
|
92
|
+
<div aria-hidden="true" class={cn('mt-10 md:mt-0 md:basis-1/2', classes?.end ?? '')}>
|
|
84
93
|
{
|
|
85
94
|
image && (
|
|
86
|
-
|
|
87
|
-
|
|
95
|
+
<div class={cn('relative m-auto max-w-4xl', classes?.image ?? '')}>
|
|
96
|
+
<PointMap
|
|
97
|
+
items={points}
|
|
98
|
+
pointsDisplayMode={pointsDisplayMode}
|
|
99
|
+
classes={{ ...((classes?.points as object) ?? {}) }}
|
|
100
|
+
>
|
|
88
101
|
{typeof image === 'string' ? (
|
|
89
102
|
<Fragment set:html={image} />
|
|
90
103
|
) : (
|
|
@@ -97,8 +110,8 @@ const {
|
|
|
97
110
|
{...image}
|
|
98
111
|
/>
|
|
99
112
|
)}
|
|
100
|
-
|
|
101
|
-
|
|
113
|
+
</PointMap>
|
|
114
|
+
</div>
|
|
102
115
|
)
|
|
103
116
|
}
|
|
104
117
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {Item, HotspotPoint, ToAction} from '../../types';
|
|
1
|
+
import type { Item, HotspotPoint, ToAction } from '../../types';
|
|
2
2
|
import type { WidgetWrapperProps, SvelteWidgetWrapperProps } from '../WidgetWrapper/types';
|
|
3
3
|
import type { HeadlineProps } from '../Headline/types.ts';
|
|
4
4
|
import type { Snippet } from 'svelte';
|
|
@@ -49,7 +49,7 @@ const ComponentGrid = viaGrid;
|
|
|
49
49
|
as={asHeader}
|
|
50
50
|
asSubtitle={asSubtitle}
|
|
51
51
|
/>
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
{
|
|
54
54
|
image && (
|
|
55
55
|
<div aria-hidden="true" class={cn('aspect-w-16 aspect-h-7 mb-6')}>
|
|
@@ -79,6 +79,14 @@ const ComponentGrid = viaGrid;
|
|
|
79
79
|
<slot />
|
|
80
80
|
|
|
81
81
|
<ComponentGrid columns={columns} class={classes?.grid && ''}>
|
|
82
|
-
{
|
|
82
|
+
{
|
|
83
|
+
items &&
|
|
84
|
+
items.map((item) => (
|
|
85
|
+
<Component
|
|
86
|
+
{...item}
|
|
87
|
+
classes={Object.assign({}, classes?.card || {}, item?.classes || {}) as Record<string, string>}
|
|
88
|
+
/>
|
|
89
|
+
))
|
|
90
|
+
}
|
|
83
91
|
</ComponentGrid>
|
|
84
92
|
</WidgetWrapper>
|
|
@@ -197,7 +197,12 @@ const {
|
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
<!-- Loading indicator -->
|
|
200
|
-
<div
|
|
200
|
+
<div
|
|
201
|
+
class={cn(
|
|
202
|
+
'absolute top-0 left-0 w-full h-full flex items-center justify-center pointer-events-none',
|
|
203
|
+
`${classes?.loading}`
|
|
204
|
+
)}
|
|
205
|
+
>
|
|
201
206
|
<svg class="animate-spin h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
|
202
207
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
|
203
208
|
<path
|
|
@@ -118,8 +118,7 @@ const panelItems = links.map((link, index) => ({ link, index })).filter(({ link
|
|
|
118
118
|
aria-expanded="false"
|
|
119
119
|
class={cn('hidden md:flex px-4 py-3 items-center whitespace-nowrap cursor-pointer', linksClass)}
|
|
120
120
|
>
|
|
121
|
-
{item.text}
|
|
122
|
-
<Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 rtl:ml-0 rtl:mr-0.5" />
|
|
121
|
+
{item.text} <Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 rtl:ml-0 rtl:mr-0.5" />
|
|
123
122
|
</button>
|
|
124
123
|
) : (
|
|
125
124
|
<a
|
|
@@ -140,7 +139,9 @@ const panelItems = links.map((link, index) => ({ link, index })).filter(({ link
|
|
|
140
139
|
<div class="md:hidden">
|
|
141
140
|
{hasPanel ? (
|
|
142
141
|
<>
|
|
143
|
-
<span
|
|
142
|
+
<span
|
|
143
|
+
class={cn('block px-4 py-3 text-base font-semibold uppercase tracking-wider', megaHeadingClass)}
|
|
144
|
+
>
|
|
144
145
|
{item.text}
|
|
145
146
|
</span>
|
|
146
147
|
<ul class="flex flex-col pb-2">
|
|
@@ -202,7 +203,10 @@ const panelItems = links.map((link, index) => ({ link, index })).filter(({ link
|
|
|
202
203
|
role="region"
|
|
203
204
|
aria-label="Menu details"
|
|
204
205
|
>
|
|
205
|
-
<div
|
|
206
|
+
<div
|
|
207
|
+
class={cn('flyout-bg relative overflow-hidden rounded-xl border border-border', megaMenuClass)}
|
|
208
|
+
data-flyout-bg
|
|
209
|
+
>
|
|
206
210
|
{panelItems.map(({ link, index }) => (
|
|
207
211
|
<div class="flyout-panel absolute top-0 left-0" data-flyout-panel data-flyout-key={index}>
|
|
208
212
|
{link.mega ? (
|
|
@@ -297,9 +301,14 @@ const panelItems = links.map((link, index) => ({ link, index })).filter(({ link
|
|
|
297
301
|
>
|
|
298
302
|
<div class="items-center flex justify-between w-full md:w-auto">
|
|
299
303
|
<div class="flex">
|
|
300
|
-
{
|
|
301
|
-
|
|
302
|
-
|
|
304
|
+
{
|
|
305
|
+
showToggleTheme && (
|
|
306
|
+
<DarkMode
|
|
307
|
+
initialMode={initialMode}
|
|
308
|
+
iconClass={cn('w-6 h-6 md:w-5 md:h-5 md:inline-block', darkModeIconClass)}
|
|
309
|
+
/>
|
|
310
|
+
)
|
|
311
|
+
}
|
|
303
312
|
</div>
|
|
304
313
|
|
|
305
314
|
<!-- Actions Buttons -->
|
|
@@ -6,7 +6,7 @@ import SwiperSlider from '../SwiperSlider/SwiperSlider.astro';
|
|
|
6
6
|
import { Image as AstroImage, getImage } from 'astro:assets';
|
|
7
7
|
import { fetchLocalImages } from '../../utils/images';
|
|
8
8
|
import { cn } from '../../utils';
|
|
9
|
-
import Button from
|
|
9
|
+
import Button from '../Button/Button.astro';
|
|
10
10
|
|
|
11
11
|
const {
|
|
12
12
|
title = await Astro.slots.render('title'),
|
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
...rest
|
|
29
29
|
} = Astro.props;
|
|
30
30
|
|
|
31
|
-
const images = await fetchLocalImages() as Record<string, () => any>;
|
|
31
|
+
const images = (await fetchLocalImages()) as Record<string, () => any>;
|
|
32
32
|
const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
33
33
|
return imagePath.startsWith(`/src/assets/images/${imagesFolder}/`);
|
|
34
34
|
});
|
|
@@ -62,11 +62,19 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
|
62
62
|
|
|
63
63
|
// Generate alt text: alt prop > title-based > numbered fallback
|
|
64
64
|
// Detect UUID filenames (8-4-4-4-12 hex pattern) and treat as meaningless
|
|
65
|
-
const filename =
|
|
65
|
+
const filename =
|
|
66
|
+
imagePath
|
|
67
|
+
.split('/')
|
|
68
|
+
.pop()
|
|
69
|
+
?.replace(/\.[^/.]+$/, '') || '';
|
|
66
70
|
const isUuidFilename = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(filename);
|
|
67
71
|
const imageNumber = index + 1;
|
|
68
|
-
const imageName =
|
|
69
|
-
const baseTitle = title
|
|
72
|
+
const imageName = filename && !isUuidFilename ? filename : String(imageNumber);
|
|
73
|
+
const baseTitle = title
|
|
74
|
+
? String(title)
|
|
75
|
+
.replace(/<[^>]*>/g, '')
|
|
76
|
+
.trim()
|
|
77
|
+
: '';
|
|
70
78
|
const altText = alt
|
|
71
79
|
? alt + ' - ' + imageName
|
|
72
80
|
: baseTitle
|
|
@@ -90,7 +98,10 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
|
90
98
|
widths={[400, 900]}
|
|
91
99
|
width={400}
|
|
92
100
|
sizes="(max-width: 900px) 400px, 900px"
|
|
93
|
-
class={cn(
|
|
101
|
+
class={cn(
|
|
102
|
+
'object-cover object-top w-full md:h-full group-hover:scale-105 transition duration-300',
|
|
103
|
+
classes?.image
|
|
104
|
+
)}
|
|
94
105
|
/>
|
|
95
106
|
</a>
|
|
96
107
|
</swiper-slide>
|
|
@@ -107,7 +118,7 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
|
107
118
|
</div>
|
|
108
119
|
)
|
|
109
120
|
}
|
|
110
|
-
|
|
121
|
+
|
|
111
122
|
<slot />
|
|
112
123
|
</WidgetWrapper>
|
|
113
124
|
|
|
@@ -30,7 +30,14 @@ const {
|
|
|
30
30
|
containerClass={`max-w-6xl mx-auto ${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
31
31
|
bg={bg}
|
|
32
32
|
>
|
|
33
|
-
<Headline
|
|
33
|
+
<Headline
|
|
34
|
+
title={title}
|
|
35
|
+
subtitle={subtitle}
|
|
36
|
+
tagline={tagline}
|
|
37
|
+
position={position}
|
|
38
|
+
as={asHeader}
|
|
39
|
+
asSubtitle={asSubtitle}
|
|
40
|
+
/>
|
|
34
41
|
|
|
35
42
|
<ItemGrid0 columns={columns}>
|
|
36
43
|
{
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { WidgetWrapperProps as Props } from './types';
|
|
3
3
|
import Background from '../Background/Background.astro';
|
|
4
|
-
import {cn} from
|
|
4
|
+
import { cn } from '../../utils';
|
|
5
5
|
|
|
6
|
-
const {
|
|
6
|
+
const {
|
|
7
|
+
id,
|
|
8
|
+
isDark = false,
|
|
9
|
+
class: className = '',
|
|
10
|
+
containerClass = '',
|
|
11
|
+
bg,
|
|
12
|
+
as = 'section',
|
|
13
|
+
isAfterContent = false,
|
|
14
|
+
...rest
|
|
15
|
+
} = Astro.props;
|
|
7
16
|
|
|
8
17
|
const WrapperTag = as;
|
|
9
18
|
---
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Utility Types
|
|
2
|
-
import type {HTMLAttributes} from
|
|
3
|
-
import type {ImageMetadata} from
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types';
|
|
3
|
+
import type { ImageMetadata } from 'astro';
|
|
4
4
|
|
|
5
5
|
export type ClassValue = ClassArray | ClassDictionary | string | number | bigint | null | boolean | undefined;
|
|
6
6
|
export type ClassDictionary = Record<string, any>;
|
|
@@ -33,7 +33,7 @@ export type HotspotPoint = {
|
|
|
33
33
|
isPopupOpen?: boolean; // whether the popup is open on initialization
|
|
34
34
|
classes?: Record<string, string>;
|
|
35
35
|
callToAction?: CallToAction;
|
|
36
|
-
}
|
|
36
|
+
};
|
|
37
37
|
|
|
38
38
|
export type Item = {
|
|
39
39
|
title?: string;
|
|
@@ -51,23 +51,23 @@ export type Image = {
|
|
|
51
51
|
aspectRatio?: string;
|
|
52
52
|
class?: string;
|
|
53
53
|
} & Omit<HTMLAttributes<'img'>, 'src'> & {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
};
|
|
54
|
+
src?: string | ImageMetadata | null;
|
|
55
|
+
width?: string | number | null;
|
|
56
|
+
height?: string | number | null;
|
|
57
|
+
alt?: string | null;
|
|
58
|
+
loading?: 'eager' | 'lazy' | null;
|
|
59
|
+
decoding?: 'sync' | 'async' | 'auto' | null;
|
|
60
|
+
class?: string;
|
|
61
|
+
style?: string;
|
|
62
|
+
srcset?: string | null;
|
|
63
|
+
sizes?: string | null;
|
|
64
|
+
fetchpriority?: 'high' | 'low' | 'auto' | null;
|
|
65
|
+
layout?: Layout;
|
|
66
|
+
widths?: number[] | null;
|
|
67
|
+
aspectRatio?: string | number | null;
|
|
68
|
+
objectPosition?: string;
|
|
69
|
+
format?: string;
|
|
70
|
+
};
|
|
71
71
|
|
|
72
72
|
export type Testimonial = {
|
|
73
73
|
title?: string;
|