@yatoday/astro-ui 0.13.2 → 0.14.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.
Files changed (45) hide show
  1. package/components/Analytics/Analytics.astro +9 -0
  2. package/components/Analytics/AnalyticsGTM.astro +15 -0
  3. package/components/Analytics/AnalyticsGTMBody.astro +18 -0
  4. package/components/Analytics/types.ts +4 -0
  5. package/components/BackToTopButton/BackToTopButton.astro +3 -3
  6. package/components/BackToTopButton/BackToTopButton.svelte +6 -6
  7. package/components/Headline/Headline.astro +3 -1
  8. package/components/Headline/types.ts +1 -0
  9. package/components/HeroSection/HeroSection.astro +4 -2
  10. package/components/HeroSection/types.ts +1 -0
  11. package/components/ImageGalleryIkea/ImageGalleryIkea.svelte +1 -1
  12. package/components/Layout/Layout.astro +3 -0
  13. package/components/WidgetBrands/WidgetBrands.astro +3 -1
  14. package/components/WidgetBrands/types.ts +6 -2
  15. package/components/WidgetCallToAction1/WidgetCallToAction1.astro +4 -0
  16. package/components/WidgetCallToAction1/types.ts +6 -2
  17. package/components/WidgetCardSlider/WidgetCardSlider.astro +4 -0
  18. package/components/WidgetCardSlider/types.ts +6 -2
  19. package/components/WidgetContent/WidgetContent.astro +4 -0
  20. package/components/WidgetContent/types.ts +6 -2
  21. package/components/WidgetFaq1/WidgetFaq1.astro +4 -0
  22. package/components/WidgetFaq1/types.ts +6 -2
  23. package/components/WidgetFeatures0/WidgetFeatures0.astro +4 -0
  24. package/components/WidgetFeatures0/types.ts +3 -1
  25. package/components/WidgetFeaturesCard/WidgetFeaturesCard.astro +4 -0
  26. package/components/WidgetFeaturesCard/types.ts +1 -0
  27. package/components/WidgetHero0/WidgetHero0.astro +4 -0
  28. package/components/WidgetHero0/types.ts +1 -0
  29. package/components/WidgetHero1/WidgetHero1.astro +4 -1
  30. package/components/WidgetHero1/types.ts +1 -0
  31. package/components/WidgetHero2/WidgetHero2.astro +7 -3
  32. package/components/WidgetHero2/types.ts +5 -2
  33. package/components/WidgetHeroSlider/WidgetHeroSlider.svelte +4 -2
  34. package/components/WidgetStats/WidgetStats.astro +4 -0
  35. package/components/WidgetStats/types.ts +6 -2
  36. package/components/WidgetSteps1/WidgetSteps1.astro +4 -0
  37. package/components/WidgetSteps1/types.ts +6 -2
  38. package/components/WidgetStepsTimeline/WidgetStepsTimeline.astro +4 -0
  39. package/components/WidgetStepsTimeline/types.ts +6 -2
  40. package/components/WidgetSwiperPhotoSlider/WidgetSwiperPhotoSlider.astro +5 -1
  41. package/components/WidgetSwiperPhotoSlider/types.ts +5 -1
  42. package/components/WidgetTestimonials/WidgetTestimonials.astro +3 -1
  43. package/components/WidgetTestimonials/types.ts +6 -2
  44. package/components/ZoomedImage/ZoomedImage.svelte +4 -4
  45. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  //import type { AnalyticsProps as Props } from './types';
3
3
  import AnalyticsGoogleProvider from './AnalyticsGoogle.astro';
4
+ import AnalyticsGTMProvider from './AnalyticsGTM.astro';
4
5
 
5
6
  import { ANALYTICS } from 'vendor:config';
6
7
  ---
@@ -13,3 +14,11 @@ import { ANALYTICS } from 'vendor:config';
13
14
  />
14
15
  ) : null
15
16
  }
17
+
18
+ {
19
+ ANALYTICS?.vendors?.googleTagManager?.id ? (
20
+ <AnalyticsGTMProvider
21
+ id={String(ANALYTICS.vendors.googleTagManager.id)}
22
+ />
23
+ ) : null
24
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ import type { AnalyticsGTMProps as Props } from './types';
3
+
4
+ const { id = 'GTM-XXXXXXX' } = Astro.props;
5
+ ---
6
+
7
+ <!-- Google Tag Manager -->
8
+ <script is:inline define:vars={{ id }}>
9
+ (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
10
+ new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
11
+ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
12
+ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
13
+ })(window,document,'script','dataLayer',id);
14
+ </script>
15
+ <!-- End Google Tag Manager -->
@@ -0,0 +1,18 @@
1
+ ---
2
+ import { ANALYTICS } from 'vendor:config';
3
+
4
+ const gtmId = ANALYTICS?.vendors?.googleTagManager?.id;
5
+ ---
6
+
7
+ {gtmId && (
8
+ <!-- Google Tag Manager (noscript) -->
9
+ <noscript>
10
+ <iframe
11
+ src={`https://www.googletagmanager.com/ns.html?id=${gtmId}`}
12
+ height="0"
13
+ width="0"
14
+ style="display:none;visibility:hidden"
15
+ ></iframe>
16
+ </noscript>
17
+ <!-- End Google Tag Manager (noscript) -->
18
+ )}
@@ -8,4 +8,8 @@ export type AnalyticsGoogleProps = {
8
8
  partytown?: boolean;
9
9
  };
10
10
 
11
+ export type AnalyticsGTMProps = {
12
+ id: string;
13
+ };
14
+
11
15
  export type SvelteAnalyticsProps = AnalyticsProps;
@@ -56,9 +56,9 @@ const { selector = '#header', scrollOffset = 450 } = Astro.props;
56
56
  </style>
57
57
 
58
58
  <!-- Back to top button-->
59
- <a
59
+ <button
60
+ type="button"
60
61
  class="btn-scroll-top text-card-foreground"
61
- href="javascript:void(0);"
62
62
  data-yt-scroll
63
63
  data-yt-scroll-offset={scrollOffset}
64
64
  data-yt-scroll-selector={selector}
@@ -71,7 +71,7 @@ const { selector = '#header', scrollOffset = 450 } = Astro.props;
71
71
  <span class="flex items-center justify-center">
72
72
  <Icon name="tabler:arrow-up" />
73
73
  </span>
74
- </a>
74
+ </button>
75
75
 
76
76
  <script>
77
77
  import { get, attachEvent } from '../../utils';
@@ -8,7 +8,7 @@
8
8
  iconSlot,
9
9
  }: SvelteBackToTopButtonProps = $props();
10
10
 
11
- let buttonRef: HTMLAnchorElement;
11
+ let buttonRef: HTMLButtonElement;
12
12
  let progressRef: SVGCircleElement;
13
13
  let showButton = $state(false);
14
14
  let strokeDashoffset = $state(0);
@@ -34,8 +34,7 @@
34
34
  showProgress();
35
35
  };
36
36
 
37
- const handleClick = (e: MouseEvent) => {
38
- e.preventDefault();
37
+ const handleClick = () => {
39
38
  const targetEl = document.querySelector(selector);
40
39
  targetEl?.scrollIntoView({ behavior: 'smooth', block: 'end' });
41
40
  };
@@ -102,10 +101,11 @@
102
101
  }
103
102
  </style>
104
103
 
105
- <a
104
+ <button
106
105
  bind:this={buttonRef}
106
+ type="button"
107
107
  class="btn-scroll-top text-card-foreground {showButton ? 'show' : ''}"
108
- href="javascript:void(0);"
108
+ aria-label="Back to top"
109
109
  data-yt-scroll
110
110
  data-yt-scroll-offset={scrollOffset}
111
111
  data-yt-scroll-selector={selector}
@@ -132,4 +132,4 @@
132
132
  </svg>
133
133
  {/if}
134
134
  </span>
135
- </a>
135
+ </button>
@@ -9,6 +9,7 @@ const {
9
9
  position = 'center',
10
10
  classes = {},
11
11
  as = 'h2',
12
+ asSubtitle = 'p',
12
13
  } = Astro.props;
13
14
 
14
15
  const {
@@ -19,6 +20,7 @@ const {
19
20
  } = classes;
20
21
 
21
22
  const WrapperTag = as;
23
+ const SubtitleTag = asSubtitle;
22
24
  ---
23
25
 
24
26
  {
@@ -49,7 +51,7 @@ const WrapperTag = as;
49
51
  )}
50
52
 
51
53
  {subtitle && (
52
- <p class={cn('mt-1 md:mt-4 text-muted-foreground text-lg/6 md:text-xl', subtitleClass)} set:html={subtitle} />
54
+ <SubtitleTag class={cn('mt-1 md:mt-4 text-muted-foreground text-lg/6 md:text-xl', subtitleClass)} set:html={subtitle} />
53
55
  )}
54
56
  </div>
55
57
  )
@@ -9,6 +9,7 @@ export type HeadlineProps = {
9
9
  tagline?: string;
10
10
  classes?: Record<string, string>;
11
11
  ['as']?: HTMLTag;
12
+ asSubtitle?: HTMLTag;
12
13
  position?: 'center' | 'left' | 'right';
13
14
  };
14
15
 
@@ -6,7 +6,8 @@ import Button from '../Button/Button.astro';
6
6
  import { cn } from '../../utils';
7
7
 
8
8
  const {
9
- asHeader = 'h3',
9
+ asHeader = 'h1',
10
+ asDescription = 'h2',
10
11
  classes = {},
11
12
  image = await Astro.slots.render('image'),
12
13
  title = await Astro.slots.render('title'),
@@ -35,6 +36,7 @@ const {
35
36
  } = classes;
36
37
 
37
38
  const WrapperHeaderTag = asHeader;
39
+ const WrapperDescriptionTag = asDescription;
38
40
  ---
39
41
 
40
42
  <div
@@ -55,7 +57,7 @@ const WrapperHeaderTag = asHeader;
55
57
  >
56
58
  {title}
57
59
  </WrapperHeaderTag>
58
- <p class={cn('text-sm md:text-base xl:text-lg', descriptionClass)}>{description}</p>
60
+ <WrapperDescriptionTag class={cn('text-sm md:text-base xl:text-lg', descriptionClass)}>{description}</WrapperDescriptionTag>
59
61
  </div>
60
62
 
61
63
  {callToAction && (
@@ -6,6 +6,7 @@ import type { HTMLAttributes } from 'svelte/elements';
6
6
 
7
7
  export type HeroSectionProps = {
8
8
  asHeader?: HTMLTag;
9
+ asDescription?: HTMLTag;
9
10
  title?: string;
10
11
  description?: string;
11
12
  image: Image | string;
@@ -19,7 +19,7 @@
19
19
 
20
20
  onMount(async () => {
21
21
  const { register } = await import('swiper/element/bundle');
22
- const { on, get } = await import('~/utils');
22
+ const { on, get } = await import('../../utils');
23
23
 
24
24
  register();
25
25
 
@@ -2,6 +2,7 @@
2
2
  import SeoMetadata from '../Metadata/Metadata.astro';
3
3
  import SeoSiteVerification from '../SiteVerification/SiteVerification.astro';
4
4
  import SeoAnalytics from '../Analytics/Analytics.astro';
5
+ import SeoAnalyticsGTMBody from '../Analytics/AnalyticsGTMBody.astro';
5
6
  import type { LayoutProps as Props } from './types';
6
7
 
7
8
  import { I18N } from 'vendor:config';
@@ -29,6 +30,8 @@ const currentLang = Astro.currentLocale || language;
29
30
  </head>
30
31
 
31
32
  <body class="antialiased bg-background text-foreground tracking-tight">
33
+ <SeoAnalyticsGTMBody />
34
+
32
35
  <slot />
33
36
 
34
37
  <slot name="scripts" />
@@ -13,6 +13,8 @@ const {
13
13
  icons = [],
14
14
  images = [],
15
15
  position = 'center',
16
+ asHeader = 'h2',
17
+ asSubtitle = 'p',
16
18
  isAfterContent = false,
17
19
  id,
18
20
  isDark = false,
@@ -27,7 +29,7 @@ const {
27
29
  containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
28
30
  bg={bg}
29
31
  >
30
- <Headline title={title} subtitle={subtitle} tagline={tagline} position={position} />
32
+ <Headline title={title} subtitle={subtitle} tagline={tagline} position={position} as={asHeader} asSubtitle={asSubtitle} />
31
33
 
32
34
  <div class="flex flex-wrap justify-center gap-x-6 sm:gap-x-12 lg:gap-x-24">
33
35
  {
@@ -7,8 +7,10 @@ export type WidgetBrandsProps = {
7
7
  icons?: Array<string>;
8
8
  images?: Array<Image>;
9
9
  isAfterContent?: boolean;
10
+ asHeader?: HeadlineProps['as'];
11
+ asSubtitle?: HeadlineProps['asSubtitle'];
10
12
  } & WidgetWrapperProps &
11
- Omit<HeadlineProps, 'classes'>;
13
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
12
14
 
13
15
  export type SvelteWidgetBrandsProps = {
14
16
  icons?: Array<string>;
@@ -18,5 +20,7 @@ export type SvelteWidgetBrandsProps = {
18
20
  subtitle?: string | Snippet;
19
21
  tagline?: string | Snippet;
20
22
  bg?: Snippet;
23
+ asHeader?: HeadlineProps['as'];
24
+ asSubtitle?: HeadlineProps['asSubtitle'];
21
25
  } & SvelteWidgetWrapperProps &
22
- Omit<HeadlineProps, 'classes'>;
26
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -11,6 +11,8 @@ const {
11
11
  tagline = await Astro.slots.render('tagline'),
12
12
  actions = await Astro.slots.render('actions'),
13
13
  isAfterContent = false,
14
+ asHeader = 'h2',
15
+ asSubtitle = 'p',
14
16
 
15
17
  id,
16
18
  isDark = false,
@@ -30,6 +32,8 @@ const {
30
32
  title={title}
31
33
  subtitle={subtitle}
32
34
  tagline={tagline}
35
+ as={asHeader}
36
+ asSubtitle={asSubtitle}
33
37
  classes={{
34
38
  container: 'mb-0 md:mb-0 text-left',
35
39
  title: 'text-2xl md:text-4xl font-bold tracking-tighter mb-4 font-heading',
@@ -6,8 +6,10 @@ import type { Snippet } from 'svelte';
6
6
  export type WidgetCallToAction1Props = {
7
7
  actions?: ToAction[];
8
8
  isAfterContent?: boolean;
9
+ asHeader?: HeadlineProps['as'];
10
+ asSubtitle?: HeadlineProps['asSubtitle'];
9
11
  } & WidgetWrapperProps &
10
- Omit<HeadlineProps, 'classes'>;
12
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
11
13
 
12
14
  export type SvelteWidgetCallToAction1Props = {
13
15
  actions?: ToAction[] | Snippet;
@@ -16,5 +18,7 @@ export type SvelteWidgetCallToAction1Props = {
16
18
  subtitle?: string | Snippet;
17
19
  tagline?: string | Snippet;
18
20
  bg?: Snippet;
21
+ asHeader?: HeadlineProps['as'];
22
+ asSubtitle?: HeadlineProps['asSubtitle'];
19
23
  } & SvelteWidgetWrapperProps &
20
- Omit<HeadlineProps, 'classes'>;
24
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -15,6 +15,8 @@ const {
15
15
  subtitle = await Astro.slots.render('subtitle'),
16
16
  tagline = await Astro.slots.render('tagline'),
17
17
  position = 'center',
18
+ asHeader = 'h2',
19
+ asSubtitle = 'p',
18
20
  items = [] as Card1Props[] | Card2Props[] | Card3Props[],
19
21
  isAfterContent = false,
20
22
 
@@ -41,6 +43,8 @@ const Component = via;
41
43
  tagline={tagline}
42
44
  classes={classes?.headline as Record<string, string>}
43
45
  position={position}
46
+ as={asHeader}
47
+ asSubtitle={asSubtitle}
44
48
  />
45
49
 
46
50
  {
@@ -10,8 +10,10 @@ export type WidgetCardSliderProps = {
10
10
  items?: Card1Props[] | Card2Props[] | Card3Props[];
11
11
  isAfterContent?: boolean;
12
12
  withNavigation?: boolean;
13
+ asHeader?: HeadlineProps['as'];
14
+ asSubtitle?: HeadlineProps['asSubtitle'];
13
15
  } & WidgetWrapperProps &
14
- Omit<HeadlineProps, 'classes'>;
16
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
15
17
 
16
18
  export type SvelteWidgetCardSliderProps = {
17
19
  via?: any;
@@ -22,5 +24,7 @@ export type SvelteWidgetCardSliderProps = {
22
24
  subtitle?: string | Snippet;
23
25
  tagline?: string | Snippet;
24
26
  bg?: Snippet;
27
+ asHeader?: HeadlineProps['as'];
28
+ asSubtitle?: HeadlineProps['asSubtitle'];
25
29
  } & SvelteWidgetWrapperProps &
26
- Omit<HeadlineProps, 'classes'>;
30
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -24,6 +24,8 @@ const {
24
24
  isAfterContent = false,
25
25
  defaultIcon = 'tabler:check',
26
26
  position = 'center',
27
+ asHeader = 'h2',
28
+ asSubtitle = 'p',
27
29
  id,
28
30
  isDark = false,
29
31
  classes = {},
@@ -43,6 +45,8 @@ const {
43
45
  tagline={tagline}
44
46
  classes={classes?.headline as Record<string, string>}
45
47
  position={position}
48
+ as={asHeader}
49
+ asSubtitle={asSubtitle}
46
50
  />
47
51
 
48
52
  <div class={`md:flex ${isReversed ? 'md:flex-row-reverse' : ''} md:gap-16`}>
@@ -14,8 +14,10 @@ export type WidgetContentProps = {
14
14
  isReversed?: boolean;
15
15
  isAfterContent?: boolean;
16
16
  callToAction?: ToAction;
17
+ asHeader?: HeadlineProps['as'];
18
+ asSubtitle?: HeadlineProps['asSubtitle'];
17
19
  } & WidgetWrapperProps &
18
- Omit<HeadlineProps, 'classes'>;
20
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
19
21
 
20
22
  export type SvelteWidgetContentProps = {
21
23
  content?: string | Snippet;
@@ -33,5 +35,7 @@ export type SvelteWidgetContentProps = {
33
35
  tagline?: string | Snippet;
34
36
  bg?: Snippet;
35
37
  children?: Snippet;
38
+ asHeader?: HeadlineProps['as'];
39
+ asSubtitle?: HeadlineProps['asSubtitle'];
36
40
  } & SvelteWidgetWrapperProps &
37
- Omit<HeadlineProps, 'classes'>;
41
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -13,6 +13,8 @@ const {
13
13
  columns = 2,
14
14
  isAfterContent = false,
15
15
  position = 'center',
16
+ asHeader = 'h2',
17
+ asSubtitle = 'p',
16
18
  id,
17
19
  isDark = false,
18
20
  classes = {},
@@ -32,6 +34,8 @@ const {
32
34
  tagline={tagline}
33
35
  classes={classes?.headline as Record<string, string>}
34
36
  position={position}
37
+ as={asHeader}
38
+ asSubtitle={asSubtitle}
35
39
  />
36
40
 
37
41
  <ItemGrid0 columns={columns}>
@@ -7,9 +7,11 @@ import type { Snippet } from 'svelte';
7
7
  export type WidgetFaq1Props = {
8
8
  items?: Card4Props[];
9
9
  isAfterContent?: boolean;
10
+ asHeader?: HeadlineProps['as'];
11
+ asSubtitle?: HeadlineProps['asSubtitle'];
10
12
  } & WidgetWrapperProps &
11
13
  ItemGrid0Props &
12
- Omit<HeadlineProps, 'classes'>;
14
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
13
15
 
14
16
  export type SvelteWidgetFaq1Props = {
15
17
  items?: Card4Props[];
@@ -18,6 +20,8 @@ export type SvelteWidgetFaq1Props = {
18
20
  subtitle?: string | Snippet;
19
21
  tagline?: string | Snippet;
20
22
  bg?: Snippet;
23
+ asHeader?: HeadlineProps['as'];
24
+ asSubtitle?: HeadlineProps['asSubtitle'];
21
25
  } & SvelteWidgetWrapperProps &
22
26
  ItemGrid0Props &
23
- Omit<HeadlineProps, 'classes'>;
27
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -12,6 +12,8 @@ const {
12
12
  isAfterContent = false,
13
13
  callToAction = await Astro.slots.render('actions'),
14
14
  position = 'center',
15
+ asHeader = 'h2',
16
+ asSubtitle = 'p',
15
17
  id,
16
18
  isDark = false,
17
19
  classes = {},
@@ -31,6 +33,8 @@ const {
31
33
  tagline={tagline}
32
34
  classes={classes?.headline as Record<string, string>}
33
35
  position={position}
36
+ as={asHeader}
37
+ asSubtitle={asSubtitle}
34
38
  />
35
39
  <slot />
36
40
 
@@ -7,8 +7,10 @@ export type WidgetFeatures0Props = {
7
7
  isBeforeContent?: boolean;
8
8
  isAfterContent?: boolean;
9
9
  callToAction?: string | ToAction | Array<string | ToAction>;
10
+ asHeader?: HeadlineProps['as'];
11
+ asSubtitle?: HeadlineProps['asSubtitle'];
10
12
  } & WidgetWrapperProps &
11
- Omit<HeadlineProps, 'classes'>;
13
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
12
14
 
13
15
  export type SvelteWidgetFeatures0Props = WidgetFeatures0Props & {
14
16
  children?: Snippet;
@@ -18,6 +18,8 @@ const {
18
18
  columns = 4,
19
19
  image = await Astro.slots.render('image'),
20
20
  position = 'center',
21
+ asHeader = 'h2',
22
+ asSubtitle = 'p',
21
23
  isBeforeContent,
22
24
  isAfterContent,
23
25
  id,
@@ -44,6 +46,8 @@ const ComponentGrid = viaGrid;
44
46
  tagline={tagline}
45
47
  classes={classes?.headline as Record<string, string>}
46
48
  position={position}
49
+ as={asHeader}
50
+ asSubtitle={asSubtitle}
47
51
  />
48
52
 
49
53
  {
@@ -1,4 +1,5 @@
1
1
  import type { WidgetFeatures0Props, SvelteWidgetFeatures0Props } from '../WidgetFeatures0/types';
2
+ import type { HeadlineProps } from '../Headline/types';
2
3
  import type { Image } from '../../types';
3
4
  import type { Snippet } from 'svelte';
4
5
 
@@ -11,6 +11,8 @@ const {
11
11
  subtitle = await Astro.slots.render('subtitle'),
12
12
  tagline = await Astro.slots.render('tagline'),
13
13
  position = 'center',
14
+ asHeader = 'h2',
15
+ asSubtitle = 'p',
14
16
  image,
15
17
  actions = [],
16
18
  links = [],
@@ -31,6 +33,8 @@ const { container: containerClass = '', bg: bgClass = '' } = classes;
31
33
  title={title}
32
34
  subtitle={subtitle}
33
35
  tagline={tagline}
36
+ as={asHeader}
37
+ asSubtitle={asSubtitle}
34
38
  classes={{
35
39
  container: cn(
36
40
  'max-w-3xl',
@@ -1,5 +1,6 @@
1
1
  import type { WidgetFeatures0Props } from '~/components/WidgetFeatures0/types.ts';
2
2
  import type { Link, Item, ToAction, Image } from '../../types';
3
+ import type { HeadlineProps } from '../Headline/types';
3
4
  import type { Snippet } from 'svelte';
4
5
 
5
6
  export type WidgetHero0Props = {
@@ -12,6 +12,8 @@ const {
12
12
  subtitle = await Astro.slots.render('subtitle'),
13
13
  tagline = await Astro.slots.render('tagline'),
14
14
  position = 'center',
15
+ asHeader = 'h1',
16
+ asSubtitle = 'p',
15
17
  image = await Astro.slots.render('image'),
16
18
  actions = [],
17
19
  links = [],
@@ -61,10 +63,11 @@ const { container: containerClass = '', bg: bgClass = '' } = classes;
61
63
  <div class={cn('relative z-30', Astro.slots.has('default') && 'grid grid-cols-3 gap-6')}>
62
64
  <div class={cn(Astro.slots.has('default') && 'col-span-2')}>
63
65
  <Headline
64
- as="h1"
66
+ as={asHeader}
65
67
  title={title}
66
68
  subtitle={subtitle}
67
69
  tagline={tagline}
70
+ asSubtitle={asSubtitle}
68
71
  classes={{
69
72
  container: cn(
70
73
  'max-w-3xl',
@@ -1,5 +1,6 @@
1
1
  import type { WidgetFeatures0Props } from '~/components/WidgetFeatures0/types.ts';
2
2
  import type { Link, Item, ToAction, Image } from '../../types';
3
+ import type { HeadlineProps } from '../Headline/types';
3
4
  import type { Snippet } from 'svelte';
4
5
 
5
6
  export type WidgetHero1Props = {
@@ -1,11 +1,8 @@
1
1
  ---
2
2
  import type { WidgetHero2Props as Props } from './types';
3
3
  import WidgetWrapper from '../WidgetWrapper/WidgetWrapper.astro';
4
- import Headline from '../Headline/Headline.astro';
5
4
  import Image from '../Image/Image.astro';
6
- import Stats0 from '../Stats0/Stats0.astro';
7
5
  import Button from '../Button/Button.astro';
8
- import { cn } from '../../utils';
9
6
 
10
7
  const {
11
8
  title = await Astro.slots.render('title'),
@@ -14,7 +11,14 @@ const {
14
11
  content = await Astro.slots.render('content'),
15
12
  actions = await Astro.slots.render('actions'),
16
13
  image = await Astro.slots.render('image'),
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
17
15
  position = 'center',
16
+ // Note: asHeader is kept for API consistency but not used since this component has custom heading implementation
17
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
+ asHeader = 'h1',
19
+ // Note: asSubtitle is kept for API consistency but not used since this component has custom heading implementation
20
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
21
+ asSubtitle = 'p',
18
22
 
19
23
  id,
20
24
  isDark = false,
@@ -8,12 +8,15 @@ export type WidgetHero2Props = {
8
8
  content?: string;
9
9
  actions?: string | ToAction[];
10
10
  image?: string | Image;
11
+ asHeader?: HeadlineProps['as'];
12
+ asSubtitle?: HeadlineProps['asSubtitle'];
11
13
  } & WidgetWrapperProps &
12
- Omit<HeadlineProps, 'classes'>;
14
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
13
15
 
14
- export type SvelteWidgetHero2Props = WidgetHero2Props & {
16
+ export type SvelteWidgetHero2Props = Omit<WidgetHero2Props, 'asSubtitle'> & {
15
17
  contentSlot?: Snippet;
16
18
  actionsSlot?: Snippet;
17
19
  imageSlot?: Snippet;
18
20
  bgSlot?: Snippet;
21
+ asSubtitle?: HeadlineProps['asSubtitle'];
19
22
  };
@@ -158,13 +158,15 @@
158
158
  <button
159
159
  type="button"
160
160
  id={`btn-prev-${id}`}
161
+ aria-label="Previous slide"
161
162
  class="btn-navigation btn-prev hidden lg:block cursor-pointer absolute z-10 w-10 h-10 bg-transparent border-2 border-white rounded-full shadow-sm transition-opacity opacity-20 hover:opacity-100 group-hover:opacity-100"
162
- />
163
+ ></button>
163
164
  <button
164
165
  type="button"
165
166
  id={`btn-next-${id}`}
167
+ aria-label="Next slide"
166
168
  class="btn-navigation btn-next hidden lg:block cursor-pointer absolute z-10 w-10 h-10 bg-transparent border-2 border-white rounded-full shadow-sm transition-opacity opacity-20 hover:opacity-100 group-hover:opacity-100"
167
- />
169
+ ></button>
168
170
  {/if}
169
171
 
170
172
  <!-- Loading indicator -->
@@ -12,6 +12,8 @@ const {
12
12
  items = [],
13
13
  callToAction,
14
14
  position = 'center',
15
+ asHeader = 'h2',
16
+ asSubtitle = 'p',
15
17
  id,
16
18
  isDark = false,
17
19
  classes = {},
@@ -33,6 +35,8 @@ const {
33
35
  tagline={tagline}
34
36
  classes={classes?.headline as Record<string, string>}
35
37
  position={position}
38
+ as={asHeader}
39
+ asSubtitle={asSubtitle}
36
40
  />
37
41
 
38
42
  <Stats0 items={items} classes={classes?.items as Record<string, string>} />
@@ -8,8 +8,10 @@ export type WidgetStatsProps = {
8
8
  items?: Item[];
9
9
  callToAction?: ToAction;
10
10
  isAfterContent?: boolean;
11
+ asHeader?: HeadlineProps['as'];
12
+ asSubtitle?: HeadlineProps['asSubtitle'];
11
13
  } & WidgetWrapperProps &
12
- Omit<HeadlineProps, 'classes'>;
14
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
13
15
 
14
16
  export type SvelteWidgetStatsProps = {
15
17
  via?: any;
@@ -20,5 +22,7 @@ export type SvelteWidgetStatsProps = {
20
22
  subtitle?: string | Snippet;
21
23
  tagline?: string | Snippet;
22
24
  bg?: Snippet;
25
+ asHeader?: HeadlineProps['as'];
26
+ asSubtitle?: HeadlineProps['asSubtitle'];
23
27
  } & SvelteWidgetWrapperProps &
24
- Omit<HeadlineProps, 'classes'>;
28
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -14,6 +14,8 @@ const {
14
14
  items = [],
15
15
  isReversed = false,
16
16
  isAfterContent = false,
17
+ asHeader = 'h2',
18
+ asSubtitle = 'p',
17
19
 
18
20
  id,
19
21
  isDark = false,
@@ -34,6 +36,8 @@ const {
34
36
  title={title}
35
37
  subtitle={subtitle}
36
38
  tagline={tagline}
39
+ as={asHeader}
40
+ asSubtitle={asSubtitle}
37
41
  classes={{
38
42
  container: 'text-left rtl:text-right',
39
43
  title: 'text-3xl lg:text-4xl',
@@ -8,8 +8,10 @@ export type WidgetSteps1Props = {
8
8
  isReversed?: boolean;
9
9
  isAfterContent?: boolean;
10
10
  items?: Item[];
11
+ asHeader?: HeadlineProps['as'];
12
+ asSubtitle?: HeadlineProps['asSubtitle'];
11
13
  } & WidgetFeatures0Props &
12
- HeadlineProps;
14
+ Omit<HeadlineProps, 'as' | 'asSubtitle'>;
13
15
 
14
16
  export type SvelteWidgetSteps1Props = {
15
17
  callToAction?: ToAction | Snippet;
@@ -20,5 +22,7 @@ export type SvelteWidgetSteps1Props = {
20
22
  subtitle?: string | Snippet;
21
23
  tagline?: string | Snippet;
22
24
  bg?: Snippet;
25
+ asHeader?: HeadlineProps['as'];
26
+ asSubtitle?: HeadlineProps['asSubtitle'];
23
27
  } & SvelteWidgetFeatures0Props &
24
- HeadlineProps;
28
+ Omit<HeadlineProps, 'as' | 'asSubtitle'>;
@@ -14,6 +14,8 @@ const {
14
14
  isReversed = false,
15
15
  isAfterContent = false,
16
16
  defaultIcon,
17
+ asHeader = 'h2',
18
+ asSubtitle = 'p',
17
19
 
18
20
  id,
19
21
  isDark = false,
@@ -34,6 +36,8 @@ const {
34
36
  title={title}
35
37
  subtitle={subtitle}
36
38
  tagline={tagline}
39
+ as={asHeader}
40
+ asSubtitle={asSubtitle}
37
41
  classes={{
38
42
  container: 'text-left rtl:text-right',
39
43
  title: 'text-3xl lg:text-4xl',
@@ -9,8 +9,10 @@ export type WidgetStepsTimelineProps = {
9
9
  image?: string | Image;
10
10
  defaultIcon?: string;
11
11
  isAfterContent?: boolean;
12
+ asHeader?: HeadlineProps['as'];
13
+ asSubtitle?: HeadlineProps['asSubtitle'];
12
14
  } & WidgetFeatures0Props &
13
- HeadlineProps;
15
+ Omit<HeadlineProps, 'as' | 'asSubtitle'>;
14
16
 
15
17
  export type SvelteWidgetStepsTimelineProps = {
16
18
  isReversed?: boolean;
@@ -22,5 +24,7 @@ export type SvelteWidgetStepsTimelineProps = {
22
24
  subtitle?: string | Snippet;
23
25
  tagline?: string | Snippet;
24
26
  bg?: Snippet;
27
+ asHeader?: HeadlineProps['as'];
28
+ asSubtitle?: HeadlineProps['asSubtitle'];
25
29
  } & SvelteWidgetFeatures0Props &
26
- HeadlineProps;
30
+ Omit<HeadlineProps, 'as' | 'asSubtitle'>;
@@ -13,9 +13,11 @@ const {
13
13
  tagline = await Astro.slots.render('tagline'),
14
14
  imagesFolder,
15
15
  position = 'center',
16
+ asHeader = 'h2',
17
+ asSubtitle = 'p',
16
18
  isAfterContent = false,
17
19
  callToAction,
18
-
20
+
19
21
  id = (Math.random() + 1).toString(36).substring(7),
20
22
  withNavigation = true,
21
23
  isDark = false,
@@ -42,6 +44,8 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
42
44
  tagline={tagline}
43
45
  classes={classes?.headline as Record<string, string>}
44
46
  position={position}
47
+ as={asHeader}
48
+ asSubtitle={asSubtitle}
45
49
  />
46
50
 
47
51
  {
@@ -12,8 +12,10 @@ export type WidgetSwiperPhotoSliderProps = {
12
12
  headline?: Record<string, string>;
13
13
  };
14
14
  callToAction?: ToAction;
15
+ asHeader?: HeadlineProps['as'];
16
+ asSubtitle?: HeadlineProps['asSubtitle'];
15
17
  } & WidgetWrapperProps &
16
- Omit<HeadlineProps, 'classes'>;
18
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
17
19
 
18
20
  export type SvelteWidgetSwiperPhotoSliderProps = {
19
21
  isAfterContent?: boolean;
@@ -25,4 +27,6 @@ export type SvelteWidgetSwiperPhotoSliderProps = {
25
27
  subtitle?: string | Snippet;
26
28
  tagline?: string | Snippet;
27
29
  position?: 'center' | 'left' | 'right';
30
+ asHeader?: HeadlineProps['as'];
31
+ asSubtitle?: HeadlineProps['asSubtitle'];
28
32
  } & SvelteWidgetWrapperProps;
@@ -15,6 +15,8 @@ const {
15
15
  columns = 3,
16
16
  isAfterContent = false,
17
17
  position = 'center',
18
+ asHeader = 'h2',
19
+ asSubtitle = 'p',
18
20
  id,
19
21
  isDark = false,
20
22
  classes = {},
@@ -28,7 +30,7 @@ const {
28
30
  containerClass={`max-w-6xl mx-auto ${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
29
31
  bg={bg}
30
32
  >
31
- <Headline title={title} subtitle={subtitle} tagline={tagline} position={position} />
33
+ <Headline title={title} subtitle={subtitle} tagline={tagline} position={position} as={asHeader} asSubtitle={asSubtitle} />
32
34
 
33
35
  <ItemGrid0 columns={columns}>
34
36
  {
@@ -8,9 +8,11 @@ export type WidgetTestimonialsProps = {
8
8
  items?: Testimonial[];
9
9
  callToAction?: ToAction;
10
10
  isAfterContent?: boolean;
11
+ asHeader?: HeadlineProps['as'];
12
+ asSubtitle?: HeadlineProps['asSubtitle'];
11
13
  } & WidgetWrapperProps &
12
14
  ItemGrid0Props &
13
- Omit<HeadlineProps, 'classes'>;
15
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
14
16
 
15
17
  export type SvelteWidgetTestimonialsProps = {
16
18
  items?: Testimonial[];
@@ -20,6 +22,8 @@ export type SvelteWidgetTestimonialsProps = {
20
22
  subtitle?: string | Snippet;
21
23
  tagline?: string | Snippet;
22
24
  bg?: Snippet;
25
+ asHeader?: HeadlineProps['as'];
26
+ asSubtitle?: HeadlineProps['asSubtitle'];
23
27
  } & SvelteWidgetWrapperProps &
24
28
  ItemGrid0Props &
25
- Omit<HeadlineProps, 'classes'>;
29
+ Omit<HeadlineProps, 'classes' | 'as' | 'asSubtitle'>;
@@ -15,10 +15,10 @@
15
15
  ...restProps
16
16
  }: SvelteZoomedImageProps = $props();
17
17
 
18
- let containerRef: HTMLDivElement;
19
- let zoomButtonRef: HTMLButtonElement;
20
- let imageRef: HTMLImageElement;
21
- let spanRef: HTMLElement;
18
+ let containerRef = $state<HTMLDivElement | null>(null);
19
+ let zoomButtonRef = $state<HTMLButtonElement | null>(null);
20
+ let imageRef = $state<HTMLImageElement | null>(null);
21
+ let spanRef = $state<HTMLElement | null>(null);
22
22
 
23
23
  let zoomed = $state(false);
24
24
  let mousePosition = $state({ percentX: 0, percentY: 0 });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@yatoday/astro-ui",
3
3
  "type": "module",
4
- "version": "0.13.2",
4
+ "version": "0.14.0",
5
5
  "scripts": {
6
6
  "prepare": "husky",
7
7
  "pre-commit": "lint-staged",