@yatoday/astro-ui 0.7.2 → 0.8.3
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/astro.d.ts +3 -0
- package/astro.js +2 -0
- package/components/Button/__tests__/Button.test.ts +28 -0
- package/components/Card0/Card0.astro +2 -1
- package/components/Card0/Card0.svelte +26 -3
- package/components/Card4/Card4.astro +2 -0
- package/components/CopyToClipboard/CopyToClipboard.astro +76 -0
- package/components/CopyToClipboard/CopyToClipboard.svelte +50 -0
- package/components/CopyToClipboard/copy.ts +26 -0
- package/components/CopyToClipboard/types.ts +10 -0
- package/components/DarkMode/DarkMode.svelte +69 -3
- package/components/Headline/Headline.astro +1 -1
- package/components/ImageGalleryIkea/ImageGalleryIkea.astro +2 -6
- package/components/Layout/Layout.astro +2 -2
- package/components/Layout/types.ts +1 -0
- package/components/WidgetBrands/WidgetBrands.astro +5 -4
- package/components/WidgetCardSlider/WidgetCardSlider.astro +8 -2
- package/components/WidgetContent/WidgetContent.astro +8 -2
- package/components/WidgetFaq1/WidgetFaq1.astro +9 -2
- package/components/WidgetFeatures0/WidgetFeatures0.astro +8 -2
- package/components/WidgetFeaturesCard/WidgetFeaturesCard.astro +8 -2
- package/components/WidgetStats/WidgetStats.astro +8 -1
- package/components/WidgetSwiperPhotoSlider/WidgetSwiperPhotoSlider.astro +9 -3
- package/components/WidgetTestimonials/WidgetTestimonials.astro +5 -5
- package/package.json +15 -8
- package/styles/styles.css +3 -0
- package/svelte.d.ts +3 -0
- package/svelte.js +2 -0
package/astro.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { Card3Props as YtCard3Props } from './components/Card3/types'
|
|
|
12
12
|
import type { Card4Props as YtCard4Props } from './components/Card4/types'
|
|
13
13
|
import type { Card5Props as YtCard5Props } from './components/Card5/types'
|
|
14
14
|
import type { ConditionalWrapperProps as YtConditionalWrapperProps } from './components/ConditionalWrapper/types'
|
|
15
|
+
import type { CopyToClipboardProps as YtCopyToClipboardProps } from './components/CopyToClipboard/types'
|
|
15
16
|
import type { DarkModeProps as YtDarkModeProps } from './components/DarkMode/types'
|
|
16
17
|
import type { HeadlineProps as YtHeadlineProps } from './components/Headline/types'
|
|
17
18
|
import type { HeroSectionProps as YtHeroSectionProps } from './components/HeroSection/types'
|
|
@@ -61,6 +62,7 @@ declare module '@yatoday/astro-ui/astro' {
|
|
|
61
62
|
export function Card4(_props: YtCard4Props): any
|
|
62
63
|
export function Card5(_props: YtCard5Props): any
|
|
63
64
|
export function ConditionalWrapper(_props: YtConditionalWrapperProps): any
|
|
65
|
+
export function CopyToClipboard(_props: YtCopyToClipboardProps): any
|
|
64
66
|
export function DarkMode(_props: YtDarkModeProps): any
|
|
65
67
|
export function Headline(_props: YtHeadlineProps): any
|
|
66
68
|
export function HeroSection(_props: YtHeroSectionProps): any
|
|
@@ -109,6 +111,7 @@ declare module '@yatoday/astro-ui/astro' {
|
|
|
109
111
|
export type Card4Props = YtCard4Props
|
|
110
112
|
export type Card5Props = YtCard5Props
|
|
111
113
|
export type ConditionalWrapperProps = YtConditionalWrapperProps
|
|
114
|
+
export type CopyToClipboardProps = YtCopyToClipboardProps
|
|
112
115
|
export type DarkModeProps = YtDarkModeProps
|
|
113
116
|
export type HeadlineProps = YtHeadlineProps
|
|
114
117
|
export type HeroSectionProps = YtHeroSectionProps
|
package/astro.js
CHANGED
|
@@ -12,6 +12,7 @@ import Card3Component from './components/Card3/Card3.astro'
|
|
|
12
12
|
import Card4Component from './components/Card4/Card4.astro'
|
|
13
13
|
import Card5Component from './components/Card5/Card5.astro'
|
|
14
14
|
import ConditionalWrapperComponent from './components/ConditionalWrapper/ConditionalWrapper.astro'
|
|
15
|
+
import CopyToClipboardComponent from './components/CopyToClipboard/CopyToClipboard.astro'
|
|
15
16
|
import DarkModeComponent from './components/DarkMode/DarkMode.astro'
|
|
16
17
|
import HeadlineComponent from './components/Headline/Headline.astro'
|
|
17
18
|
import HeroSectionComponent from './components/HeroSection/HeroSection.astro'
|
|
@@ -60,6 +61,7 @@ export const Card3 = Card3Component
|
|
|
60
61
|
export const Card4 = Card4Component
|
|
61
62
|
export const Card5 = Card5Component
|
|
62
63
|
export const ConditionalWrapper = ConditionalWrapperComponent
|
|
64
|
+
export const CopyToClipboard = CopyToClipboardComponent
|
|
63
65
|
export const DarkMode = DarkModeComponent
|
|
64
66
|
export const Headline = HeadlineComponent
|
|
65
67
|
export const HeroSection = HeroSectionComponent
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { themeVariants } from '../theme-variants';
|
|
3
|
+
|
|
4
|
+
describe('Button Theme Variants', () => {
|
|
5
|
+
it('has the correct default variant', () => {
|
|
6
|
+
const classes = themeVariants({ variant: 'default' });
|
|
7
|
+
expect(classes).toContain('bg-secondary');
|
|
8
|
+
expect(classes).toContain('text-secondary-foreground');
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('has the correct primary variant', () => {
|
|
12
|
+
const classes = themeVariants({ variant: 'primary' });
|
|
13
|
+
expect(classes).toContain('bg-primary');
|
|
14
|
+
expect(classes).toContain('text-primary-foreground');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('has the correct size classes for default size', () => {
|
|
18
|
+
const classes = themeVariants({ size: 'default' });
|
|
19
|
+
expect(classes).toContain('px-6');
|
|
20
|
+
expect(classes).toContain('h-10');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('has the correct size classes for small size', () => {
|
|
24
|
+
const classes = themeVariants({ size: 'sm' });
|
|
25
|
+
expect(classes).toContain('h-8');
|
|
26
|
+
expect(classes).toContain('px-4');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { Card0Props as Props } from './types';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { Fragment } from 'astro/components';
|
|
4
5
|
|
|
5
6
|
const { badge, as = 'article', classes = {} } = Astro.props;
|
|
6
7
|
|
|
@@ -17,7 +18,7 @@ const { container: containerClass = '', badge: badgeClass = 'top-2 left-2' } = c
|
|
|
17
18
|
>
|
|
18
19
|
<div class={twMerge('absolute z-10', badgeClass)}>
|
|
19
20
|
<slot name="badge">
|
|
20
|
-
{badge && <
|
|
21
|
+
{badge && <span set:html={badge} />}
|
|
21
22
|
</slot>
|
|
22
23
|
</div>
|
|
23
24
|
|
|
@@ -1,7 +1,30 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
import type { Card0Props } from './types';
|
|
2
4
|
|
|
5
|
+
export let badge: Card0Props['badge'] = undefined;
|
|
6
|
+
export let as: Card0Props['as'] = 'article';
|
|
7
|
+
export let classes: Card0Props['classes'] = {};
|
|
8
|
+
|
|
9
|
+
const { container: containerClass = '', badge: badgeClass = 'top-2 left-2' } = classes;
|
|
3
10
|
</script>
|
|
4
11
|
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
12
|
+
<svelte:element
|
|
13
|
+
this={as}
|
|
14
|
+
class={twMerge(
|
|
15
|
+
'relative flex flex-col justify-between gap-6 overflow-hidden rounded-lg border border-input bg-card text-card-foreground py-6 group',
|
|
16
|
+
containerClass
|
|
17
|
+
)}
|
|
18
|
+
>
|
|
19
|
+
<div class={twMerge('absolute z-10', badgeClass)}>
|
|
20
|
+
<slot name="badge">
|
|
21
|
+
{#if badge}
|
|
22
|
+
{@html badge}
|
|
23
|
+
{/if}
|
|
24
|
+
</slot>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<slot name="image" />
|
|
28
|
+
|
|
29
|
+
<slot />
|
|
30
|
+
</svelte:element>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { CopyToClipboardProps as Props } from './types';
|
|
3
|
+
import Button from "../Button/Button.astro";
|
|
4
|
+
import { Icon } from 'astro-icon/components';
|
|
5
|
+
|
|
6
|
+
const {
|
|
7
|
+
variant = 'outline',
|
|
8
|
+
size = 'icon',
|
|
9
|
+
text = '',
|
|
10
|
+
class: className = '',
|
|
11
|
+
type = 'button',
|
|
12
|
+
...rest
|
|
13
|
+
} = Astro.props;
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<Button
|
|
17
|
+
data-yt-copy-to-clipboard={text}
|
|
18
|
+
type={type}
|
|
19
|
+
class={className}
|
|
20
|
+
variant={variant}
|
|
21
|
+
size={size}
|
|
22
|
+
{...rest}
|
|
23
|
+
>
|
|
24
|
+
<span class="copy-icon">
|
|
25
|
+
<Icon name="tabler:copy" />
|
|
26
|
+
</span>
|
|
27
|
+
<span class="check-icon" style="display: none;">
|
|
28
|
+
<Icon name="tabler:check" />
|
|
29
|
+
</span>
|
|
30
|
+
</Button>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
import { on, get } from '../../utils';
|
|
34
|
+
import copyToClipboard from "./copy";
|
|
35
|
+
|
|
36
|
+
const init = () => {
|
|
37
|
+
// Only run once
|
|
38
|
+
if (!window.copyToClipboardInitialized) {
|
|
39
|
+
window.copyToClipboardInitialized = true;
|
|
40
|
+
|
|
41
|
+
const btn = get('[data-yt-copy-to-clipboard]', true) as NodeListOf<HTMLElement>;
|
|
42
|
+
if (btn && btn.length === 0) return;
|
|
43
|
+
|
|
44
|
+
btn.forEach(addCopyListeners);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const addCopyListeners = (btn: HTMLElement) => {
|
|
49
|
+
btn.addEventListener('click', (e) => {
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
|
|
52
|
+
if(btn.dataset.ytCopyToClipboard) {
|
|
53
|
+
copyToClipboard(btn.dataset.ytCopyToClipboard);
|
|
54
|
+
|
|
55
|
+
// Show check icon
|
|
56
|
+
const copyIcon = btn.querySelector('.copy-icon') as HTMLElement;
|
|
57
|
+
const checkIcon = btn.querySelector('.check-icon') as HTMLElement;
|
|
58
|
+
|
|
59
|
+
if (copyIcon && checkIcon) {
|
|
60
|
+
copyIcon.style.display = 'none';
|
|
61
|
+
checkIcon.style.display = 'block';
|
|
62
|
+
|
|
63
|
+
// Reset back to copy icon after 3 seconds
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
copyIcon.style.display = 'block';
|
|
66
|
+
checkIcon.style.display = 'none';
|
|
67
|
+
}, 3000);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
on(document, 'astro:after-swap', init);
|
|
75
|
+
init();
|
|
76
|
+
</script>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type {CopyToClipboardProps} from './types';
|
|
3
|
+
import Button from '../Button/Button.svelte';
|
|
4
|
+
import Copy from "lucide-svelte/icons/copy";
|
|
5
|
+
import Check from "lucide-svelte/icons/check";
|
|
6
|
+
import copyToClipboard from "./copy.ts";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
class: className = '',
|
|
10
|
+
variant = 'outline',
|
|
11
|
+
size = 'icon',
|
|
12
|
+
ref = $bindable(null),
|
|
13
|
+
text = undefined,
|
|
14
|
+
type = 'button',
|
|
15
|
+
children,
|
|
16
|
+
...restProps
|
|
17
|
+
}: CopyToClipboardProps = $props();
|
|
18
|
+
|
|
19
|
+
let showCheck = $state(false);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Copies the text passed as param to the system clipboard
|
|
23
|
+
* Check if using HTTPS and navigator.clipboard is available
|
|
24
|
+
* Then uses standard clipboard API, otherwise uses fallback
|
|
25
|
+
*/
|
|
26
|
+
const copy = async (value: string) => {
|
|
27
|
+
await copyToClipboard(value);
|
|
28
|
+
|
|
29
|
+
showCheck = true;
|
|
30
|
+
setTimeout(() => {
|
|
31
|
+
showCheck = false;
|
|
32
|
+
}, 3000);
|
|
33
|
+
}
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<Button
|
|
37
|
+
type={type}
|
|
38
|
+
class={className}
|
|
39
|
+
variant={variant}
|
|
40
|
+
size={size}
|
|
41
|
+
onclick={() => copy(text)}
|
|
42
|
+
{...restProps}
|
|
43
|
+
>
|
|
44
|
+
{#if showCheck}
|
|
45
|
+
<Check />
|
|
46
|
+
{:else}
|
|
47
|
+
<Copy />
|
|
48
|
+
{/if}
|
|
49
|
+
|
|
50
|
+
</Button>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function unsecuredCopyToClipboard(text: string) {
|
|
2
|
+
const textArea = document.createElement('textarea');
|
|
3
|
+
textArea.value = text;
|
|
4
|
+
document.body.appendChild(textArea);
|
|
5
|
+
textArea.focus();
|
|
6
|
+
textArea.select();
|
|
7
|
+
try {
|
|
8
|
+
document.execCommand('copy');
|
|
9
|
+
} catch (err) {
|
|
10
|
+
console.error('Unable to copy to clipboard', err);
|
|
11
|
+
}
|
|
12
|
+
document.body.removeChild(textArea);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Copies the text passed as param to the system clipboard
|
|
17
|
+
* Check if using HTTPS and navigator.clipboard is available
|
|
18
|
+
* Then uses standard clipboard API, otherwise uses fallback
|
|
19
|
+
*/
|
|
20
|
+
export default async function copyToClipboard (value: string) {
|
|
21
|
+
if (window.isSecureContext && navigator.clipboard) {
|
|
22
|
+
await navigator.clipboard.writeText(value);
|
|
23
|
+
} else {
|
|
24
|
+
unsecuredCopyToClipboard(value);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WithElementRef } from 'bits-ui';
|
|
2
|
+
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
|
+
import type { ButtonSize, ButtonVariant } from '../Button/theme-variants.ts';
|
|
4
|
+
|
|
5
|
+
export type CopyToClipboardProps = WithElementRef<HTMLButtonAttributes> & {
|
|
6
|
+
variant?: ButtonVariant;
|
|
7
|
+
size?: ButtonSize;
|
|
8
|
+
text?: string;
|
|
9
|
+
class?: string;
|
|
10
|
+
};
|
|
@@ -1,7 +1,73 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import Icon from '@iconify/svelte';
|
|
5
|
+
import type { DarkModeProps } from './types';
|
|
2
6
|
|
|
7
|
+
export let label: DarkModeProps['label'] = 'Toggle between Dark and Light mode';
|
|
8
|
+
export let class: DarkModeProps['class'] = 'dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-hidden focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5';
|
|
9
|
+
export let iconClass: DarkModeProps['iconClass'] = 'w-6 h-6';
|
|
10
|
+
export let iconName: DarkModeProps['iconName'] = 'tabler:sun';
|
|
11
|
+
export let initialMode: DarkModeProps['initialMode'] = 'system';
|
|
12
|
+
|
|
13
|
+
let root: HTMLElement;
|
|
14
|
+
|
|
15
|
+
function applyTheme(theme: string) {
|
|
16
|
+
if (theme === 'dark') {
|
|
17
|
+
root.classList.add('dark');
|
|
18
|
+
} else {
|
|
19
|
+
root.classList.remove('dark');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function initialize() {
|
|
24
|
+
if ((initialMode && initialMode.endsWith(':only')) || (!localStorage.theme && initialMode !== 'system')) {
|
|
25
|
+
applyTheme(initialMode.replace(':only', ''));
|
|
26
|
+
} else if (
|
|
27
|
+
localStorage.theme === 'dark' ||
|
|
28
|
+
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
29
|
+
) {
|
|
30
|
+
applyTheme('dark');
|
|
31
|
+
} else {
|
|
32
|
+
applyTheme('light');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function toggleDarkMode() {
|
|
37
|
+
if (initialMode.endsWith(':only')) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
root.classList.toggle('dark');
|
|
41
|
+
localStorage.theme = root.classList.contains('dark') ? 'dark' : 'light';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
onMount(() => {
|
|
45
|
+
// Only run once
|
|
46
|
+
if (!window.darkModeInitialized) {
|
|
47
|
+
window.darkModeInitialized = true;
|
|
48
|
+
|
|
49
|
+
root = document.documentElement;
|
|
50
|
+
|
|
51
|
+
// Listen for view transitions (if using Astro)
|
|
52
|
+
document.addEventListener('astro:after-swap', () => {
|
|
53
|
+
initialize();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
initialize();
|
|
57
|
+
}
|
|
58
|
+
});
|
|
3
59
|
</script>
|
|
4
60
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
61
|
+
{#if !initialMode.endsWith(':only')}
|
|
62
|
+
<button
|
|
63
|
+
type="button"
|
|
64
|
+
class={twMerge('cursor-pointer inline-flex items-center', class)}
|
|
65
|
+
aria-label={label}
|
|
66
|
+
data-yt-toggle-color-scheme
|
|
67
|
+
on:click={toggleDarkMode}
|
|
68
|
+
>
|
|
69
|
+
<slot>
|
|
70
|
+
<Icon icon={iconName} class={iconClass} />
|
|
71
|
+
</slot>
|
|
72
|
+
</button>
|
|
73
|
+
{/if}
|
|
@@ -14,11 +14,7 @@ const {
|
|
|
14
14
|
...rest
|
|
15
15
|
} = Astro.props;
|
|
16
16
|
|
|
17
|
-
const {
|
|
18
|
-
container: containerClass = '',
|
|
19
|
-
swiper: swiperClass = '',
|
|
20
|
-
swiperThumb: swiperThumbClass = '',
|
|
21
|
-
} = classes;
|
|
17
|
+
const { container: containerClass = '', swiper: swiperClass = '', swiperThumb: swiperThumbClass = '' } = classes;
|
|
22
18
|
---
|
|
23
19
|
|
|
24
20
|
<style>
|
|
@@ -28,7 +24,7 @@ const {
|
|
|
28
24
|
}
|
|
29
25
|
</style>
|
|
30
26
|
|
|
31
|
-
<div class={cn(
|
|
27
|
+
<div class={cn('@container relative', containerClass)} data-image-gallery-ikea={id}>
|
|
32
28
|
<div class="absolute left-0 top-0 z-20 hidden md:block group w-20">
|
|
33
29
|
<!-- Thumb Slider -->
|
|
34
30
|
<button
|
|
@@ -6,12 +6,12 @@ import type { LayoutProps as Props } from './types';
|
|
|
6
6
|
|
|
7
7
|
import { I18N } from 'vendor:config';
|
|
8
8
|
|
|
9
|
-
const { metadata = {} } = Astro.props;
|
|
9
|
+
const { metadata = {}, class: className } = Astro.props;
|
|
10
10
|
const { language, textDirection } = I18N;
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
<!doctype html>
|
|
14
|
-
<html lang={language} dir={textDirection}>
|
|
14
|
+
<html lang={language} dir={textDirection} class={className}>
|
|
15
15
|
<head>
|
|
16
16
|
<meta charset="UTF-8" />
|
|
17
17
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
@@ -7,11 +7,12 @@ import { Icon } from 'astro-icon/components';
|
|
|
7
7
|
import { cn } from '../../utils';
|
|
8
8
|
|
|
9
9
|
const {
|
|
10
|
-
title = '',
|
|
11
|
-
subtitle = '',
|
|
12
|
-
tagline = '',
|
|
10
|
+
title = await Astro.slots.render('title'),
|
|
11
|
+
subtitle = await Astro.slots.render('subtitle'),
|
|
12
|
+
tagline = await Astro.slots.render('tagline'),
|
|
13
13
|
icons = [],
|
|
14
14
|
images = [],
|
|
15
|
+
position = 'center',
|
|
15
16
|
isAfterContent = false,
|
|
16
17
|
id,
|
|
17
18
|
isDark = false,
|
|
@@ -26,7 +27,7 @@ const {
|
|
|
26
27
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
27
28
|
bg={bg}
|
|
28
29
|
>
|
|
29
|
-
<Headline title={title} subtitle={subtitle} tagline={tagline} />
|
|
30
|
+
<Headline title={title} subtitle={subtitle} tagline={tagline} position={position} />
|
|
30
31
|
|
|
31
32
|
<div class="flex flex-wrap justify-center gap-x-6 sm:gap-x-12 lg:gap-x-24">
|
|
32
33
|
{
|
|
@@ -14,7 +14,7 @@ const {
|
|
|
14
14
|
title = await Astro.slots.render('title'),
|
|
15
15
|
subtitle = await Astro.slots.render('subtitle'),
|
|
16
16
|
tagline = await Astro.slots.render('tagline'),
|
|
17
|
-
|
|
17
|
+
position = 'center',
|
|
18
18
|
items = [] as Card1Props[] | Card2Props[] | Card3Props[],
|
|
19
19
|
isAfterContent = false,
|
|
20
20
|
|
|
@@ -35,7 +35,13 @@ const Component = via;
|
|
|
35
35
|
bg={bg}
|
|
36
36
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container}`}
|
|
37
37
|
>
|
|
38
|
-
<Headline
|
|
38
|
+
<Headline
|
|
39
|
+
title={title}
|
|
40
|
+
subtitle={subtitle}
|
|
41
|
+
tagline={tagline}
|
|
42
|
+
classes={classes?.headline as Record<string, string>}
|
|
43
|
+
position={position}
|
|
44
|
+
/>
|
|
39
45
|
|
|
40
46
|
{
|
|
41
47
|
items && (
|
|
@@ -20,7 +20,7 @@ const {
|
|
|
20
20
|
isReversed = false,
|
|
21
21
|
isAfterContent = false,
|
|
22
22
|
defaultIcon = 'tabler:check',
|
|
23
|
-
|
|
23
|
+
position = 'center',
|
|
24
24
|
id,
|
|
25
25
|
isDark = false,
|
|
26
26
|
classes = {},
|
|
@@ -34,7 +34,13 @@ const {
|
|
|
34
34
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
35
35
|
bg={bg}
|
|
36
36
|
>
|
|
37
|
-
<Headline
|
|
37
|
+
<Headline
|
|
38
|
+
title={title}
|
|
39
|
+
subtitle={subtitle}
|
|
40
|
+
tagline={tagline}
|
|
41
|
+
classes={classes?.headline as Record<string, string>}
|
|
42
|
+
position={position}
|
|
43
|
+
/>
|
|
38
44
|
|
|
39
45
|
<div class={`md:flex ${isReversed ? 'md:flex-row-reverse' : ''} md:gap-16`}>
|
|
40
46
|
<div class="md:basis-1/2 self-center">
|
|
@@ -12,7 +12,7 @@ const {
|
|
|
12
12
|
items = [],
|
|
13
13
|
columns = 2,
|
|
14
14
|
isAfterContent = false,
|
|
15
|
-
|
|
15
|
+
position = 'center',
|
|
16
16
|
id,
|
|
17
17
|
isDark = false,
|
|
18
18
|
classes = {},
|
|
@@ -26,7 +26,14 @@ const {
|
|
|
26
26
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
27
27
|
bg={bg}
|
|
28
28
|
>
|
|
29
|
-
<Headline
|
|
29
|
+
<Headline
|
|
30
|
+
title={title}
|
|
31
|
+
subtitle={subtitle}
|
|
32
|
+
tagline={tagline}
|
|
33
|
+
classes={classes?.headline as Record<string, string>}
|
|
34
|
+
position={position}
|
|
35
|
+
/>
|
|
36
|
+
|
|
30
37
|
<ItemGrid0 columns={columns}>
|
|
31
38
|
{
|
|
32
39
|
items &&
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
tagline = await Astro.slots.render('tagline'),
|
|
12
12
|
isAfterContent = false,
|
|
13
13
|
callToAction = await Astro.slots.render('actions'),
|
|
14
|
-
|
|
14
|
+
position = 'center',
|
|
15
15
|
id,
|
|
16
16
|
isDark = false,
|
|
17
17
|
classes = {},
|
|
@@ -25,7 +25,13 @@ const {
|
|
|
25
25
|
containerClass={`${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
26
26
|
bg={bg}
|
|
27
27
|
>
|
|
28
|
-
<Headline
|
|
28
|
+
<Headline
|
|
29
|
+
title={title}
|
|
30
|
+
subtitle={subtitle}
|
|
31
|
+
tagline={tagline}
|
|
32
|
+
classes={classes?.headline as Record<string, string>}
|
|
33
|
+
position={position}
|
|
34
|
+
/>
|
|
29
35
|
<slot />
|
|
30
36
|
|
|
31
37
|
{
|
|
@@ -16,7 +16,7 @@ const {
|
|
|
16
16
|
items = [],
|
|
17
17
|
columns = 4,
|
|
18
18
|
image = await Astro.slots.render('image'),
|
|
19
|
-
|
|
19
|
+
position = 'center',
|
|
20
20
|
isBeforeContent,
|
|
21
21
|
isAfterContent,
|
|
22
22
|
id,
|
|
@@ -36,7 +36,13 @@ const Component = via;
|
|
|
36
36
|
}`}
|
|
37
37
|
bg={bg}
|
|
38
38
|
>
|
|
39
|
-
<Headline
|
|
39
|
+
<Headline
|
|
40
|
+
title={title}
|
|
41
|
+
subtitle={subtitle}
|
|
42
|
+
tagline={tagline}
|
|
43
|
+
classes={classes?.headline as Record<string, string>}
|
|
44
|
+
position={position}
|
|
45
|
+
/>
|
|
40
46
|
|
|
41
47
|
{
|
|
42
48
|
image && (
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
tagline,
|
|
12
12
|
items = [],
|
|
13
13
|
callToAction,
|
|
14
|
+
position = 'center',
|
|
14
15
|
id,
|
|
15
16
|
isDark = false,
|
|
16
17
|
classes = {},
|
|
@@ -26,7 +27,13 @@ const {
|
|
|
26
27
|
${classes?.container ?? ''}`}
|
|
27
28
|
bg={bg}
|
|
28
29
|
>
|
|
29
|
-
<Headline
|
|
30
|
+
<Headline
|
|
31
|
+
title={title}
|
|
32
|
+
subtitle={subtitle}
|
|
33
|
+
tagline={tagline}
|
|
34
|
+
classes={classes?.headline as Record<string, string>}
|
|
35
|
+
position={position}
|
|
36
|
+
/>
|
|
30
37
|
|
|
31
38
|
<Stats0 items={items} classes={classes?.items as Record<string, string>} />
|
|
32
39
|
|
|
@@ -5,13 +5,13 @@ import WidgetWrapper from '../WidgetWrapper/WidgetWrapper.astro';
|
|
|
5
5
|
import SwiperSlider from '../SwiperSlider/SwiperSlider.astro';
|
|
6
6
|
import { Image as AstroImage, getImage } from 'astro:assets';
|
|
7
7
|
import { fetchLocalImages } from '../../utils/images';
|
|
8
|
-
import Image from '../Image/Image.astro';
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
title = await Astro.slots.render('title'),
|
|
12
11
|
subtitle = await Astro.slots.render('subtitle'),
|
|
13
12
|
tagline = await Astro.slots.render('tagline'),
|
|
14
13
|
imagesFolder,
|
|
14
|
+
position = 'center',
|
|
15
15
|
isAfterContent = false,
|
|
16
16
|
|
|
17
17
|
id = (Math.random() + 1).toString(36).substring(7),
|
|
@@ -34,7 +34,13 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
|
34
34
|
bg={bg}
|
|
35
35
|
containerClass={`gallery ${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container}`}
|
|
36
36
|
>
|
|
37
|
-
<Headline
|
|
37
|
+
<Headline
|
|
38
|
+
title={title}
|
|
39
|
+
subtitle={subtitle}
|
|
40
|
+
tagline={tagline}
|
|
41
|
+
classes={classes?.headline as Record<string, string>}
|
|
42
|
+
position={position}
|
|
43
|
+
/>
|
|
38
44
|
|
|
39
45
|
{
|
|
40
46
|
imagePaths && (
|
|
@@ -53,7 +59,7 @@ const imagePaths = Object.keys(images).filter((imagePath) => {
|
|
|
53
59
|
data-pswp-width={optimizedImage.attributes.width}
|
|
54
60
|
data-pswp-height={optimizedImage.attributes.height}
|
|
55
61
|
target="_blank"
|
|
56
|
-
class="group overflow-hidden rounded-md border-primary cursor-zoom-in block
|
|
62
|
+
class="group overflow-hidden rounded-md border-primary cursor-zoom-in block"
|
|
57
63
|
>
|
|
58
64
|
<AstroImage
|
|
59
65
|
src={image}
|
|
@@ -7,14 +7,14 @@ import Button from '../Button/Button.astro';
|
|
|
7
7
|
import Card5 from '../Card5/Card5.astro';
|
|
8
8
|
|
|
9
9
|
const {
|
|
10
|
-
title = '',
|
|
11
|
-
subtitle = '',
|
|
12
|
-
tagline = '',
|
|
10
|
+
title = await Astro.slots.render('title'),
|
|
11
|
+
subtitle = await Astro.slots.render('subtitle'),
|
|
12
|
+
tagline = await Astro.slots.render('tagline'),
|
|
13
13
|
items = [],
|
|
14
14
|
callToAction,
|
|
15
15
|
columns = 3,
|
|
16
16
|
isAfterContent = false,
|
|
17
|
-
|
|
17
|
+
position = 'center',
|
|
18
18
|
id,
|
|
19
19
|
isDark = false,
|
|
20
20
|
classes = {},
|
|
@@ -28,7 +28,7 @@ const {
|
|
|
28
28
|
containerClass={`max-w-6xl mx-auto ${isAfterContent ? 'pt-0 md:pt-0 lg:pt-0' : ''} ${classes?.container ?? ''}`}
|
|
29
29
|
bg={bg}
|
|
30
30
|
>
|
|
31
|
-
<Headline title={title} subtitle={subtitle} tagline={tagline} />
|
|
31
|
+
<Headline title={title} subtitle={subtitle} tagline={tagline} position={position} />
|
|
32
32
|
|
|
33
33
|
<ItemGrid0 columns={columns}>
|
|
34
34
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yatoday/astro-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.3",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepare": "husky",
|
|
7
7
|
"pre-commit": "lint-staged",
|
|
@@ -20,7 +20,10 @@
|
|
|
20
20
|
"fix": "npm run fix:eslint && npm run fix:prettier",
|
|
21
21
|
"fix:eslint": "eslint --fix .",
|
|
22
22
|
"fix:prettier": "prettier -w .",
|
|
23
|
-
"create-component": "node scripts/createComponent.js"
|
|
23
|
+
"create-component": "node scripts/createComponent.js",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest",
|
|
26
|
+
"test:coverage": "vitest run --coverage"
|
|
24
27
|
},
|
|
25
28
|
"dependencies": {
|
|
26
29
|
"lodash.merge": "^4.6.2",
|
|
@@ -39,6 +42,11 @@
|
|
|
39
42
|
"@astrojs/svelte": "^7.0.5",
|
|
40
43
|
"@eslint/js": "9.18.0",
|
|
41
44
|
"@iconify-json/tabler": "^1.2.10",
|
|
45
|
+
"@tailwindcss/cli": "^4.0.13",
|
|
46
|
+
"@tailwindcss/typography": "^0.5.16",
|
|
47
|
+
"@tailwindcss/vite": "^4.0.12",
|
|
48
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
49
|
+
"@testing-library/svelte": "^5.2.7",
|
|
42
50
|
"@types/html-escaper": "^3.0.4",
|
|
43
51
|
"@types/js-yaml": "^4.0.9",
|
|
44
52
|
"@types/lodash.merge": "^4.6.9",
|
|
@@ -54,21 +62,20 @@
|
|
|
54
62
|
"eslint-plugin-svelte": "2.46.1",
|
|
55
63
|
"husky": "9.1.7",
|
|
56
64
|
"js-yaml": "^4.1.0",
|
|
57
|
-
"jsdom": "26.0.0",
|
|
65
|
+
"jsdom": "^26.0.0",
|
|
58
66
|
"lint-staged": "15.4.2",
|
|
67
|
+
"lucide-svelte": "^0.469.0",
|
|
59
68
|
"prettier": "^3.4.2",
|
|
60
69
|
"prettier-plugin-astro": "^0.14.1",
|
|
61
70
|
"svelte": "5.20.1",
|
|
62
71
|
"svelte-eslint-parser": "0.43.0",
|
|
63
|
-
"tailwindcss": "^4.0.12",
|
|
64
72
|
"tailwind-merge": "^3.0.0",
|
|
65
73
|
"tailwind-variants": "^0.3.1",
|
|
66
|
-
"
|
|
67
|
-
"@tailwindcss/typography": "^0.5.16",
|
|
68
|
-
"@tailwindcss/vite": "^4.0.12",
|
|
74
|
+
"tailwindcss": "^4.0.12",
|
|
69
75
|
"typescript": "5.7.3",
|
|
70
76
|
"typescript-eslint": "8.21.0",
|
|
71
|
-
"vite-tsconfig-paths": "5.1.4"
|
|
77
|
+
"vite-tsconfig-paths": "5.1.4",
|
|
78
|
+
"vitest": "^3.1.3"
|
|
72
79
|
},
|
|
73
80
|
"exports": {
|
|
74
81
|
".": "./index.js",
|
package/styles/styles.css
CHANGED
package/svelte.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ import type { SvelteCard3Props as YtSvelteCard3Props } from './components/Card3/
|
|
|
13
13
|
import type { SvelteCard4Props as YtSvelteCard4Props } from './components/Card4/types'
|
|
14
14
|
import type { SvelteCard5Props as YtSvelteCard5Props } from './components/Card5/types'
|
|
15
15
|
import type { SvelteConditionalWrapperProps as YtSvelteConditionalWrapperProps } from './components/ConditionalWrapper/types'
|
|
16
|
+
import type { SvelteCopyToClipboardProps as YtSvelteCopyToClipboardProps } from './components/CopyToClipboard/types'
|
|
16
17
|
import type { SvelteDarkModeProps as YtSvelteDarkModeProps } from './components/DarkMode/types'
|
|
17
18
|
import type { SvelteHeadlineProps as YtSvelteHeadlineProps } from './components/Headline/types'
|
|
18
19
|
import type { SvelteHeroSectionProps as YtSvelteHeroSectionProps } from './components/HeroSection/types'
|
|
@@ -62,6 +63,7 @@ declare module '@yatoday/astro-ui/svelte' {
|
|
|
62
63
|
export const Card4: Component<YtSvelteCard4Props>
|
|
63
64
|
export const Card5: Component<YtSvelteCard5Props>
|
|
64
65
|
export const ConditionalWrapper: Component<YtSvelteConditionalWrapperProps>
|
|
66
|
+
export const CopyToClipboard: Component<YtSvelteCopyToClipboardProps>
|
|
65
67
|
export const DarkMode: Component<YtSvelteDarkModeProps>
|
|
66
68
|
export const Headline: Component<YtSvelteHeadlineProps>
|
|
67
69
|
export const HeroSection: Component<YtSvelteHeroSectionProps>
|
|
@@ -110,6 +112,7 @@ declare module '@yatoday/astro-ui/svelte' {
|
|
|
110
112
|
export type Card4Props = YtSvelteCard4Props
|
|
111
113
|
export type Card5Props = YtSvelteCard5Props
|
|
112
114
|
export type ConditionalWrapperProps = YtSvelteConditionalWrapperProps
|
|
115
|
+
export type CopyToClipboardProps = YtSvelteCopyToClipboardProps
|
|
113
116
|
export type DarkModeProps = YtSvelteDarkModeProps
|
|
114
117
|
export type HeadlineProps = YtSvelteHeadlineProps
|
|
115
118
|
export type HeroSectionProps = YtSvelteHeroSectionProps
|
package/svelte.js
CHANGED
|
@@ -12,6 +12,7 @@ import Card3Component from './components/Card3/Card3.svelte'
|
|
|
12
12
|
import Card4Component from './components/Card4/Card4.svelte'
|
|
13
13
|
import Card5Component from './components/Card5/Card5.svelte'
|
|
14
14
|
import ConditionalWrapperComponent from './components/ConditionalWrapper/ConditionalWrapper.svelte'
|
|
15
|
+
import CopyToClipboardComponent from './components/CopyToClipboard/CopyToClipboard.svelte'
|
|
15
16
|
import DarkModeComponent from './components/DarkMode/DarkMode.svelte'
|
|
16
17
|
import HeadlineComponent from './components/Headline/Headline.svelte'
|
|
17
18
|
import HeroSectionComponent from './components/HeroSection/HeroSection.svelte'
|
|
@@ -60,6 +61,7 @@ export const Card3 = Card3Component
|
|
|
60
61
|
export const Card4 = Card4Component
|
|
61
62
|
export const Card5 = Card5Component
|
|
62
63
|
export const ConditionalWrapper = ConditionalWrapperComponent
|
|
64
|
+
export const CopyToClipboard = CopyToClipboardComponent
|
|
63
65
|
export const DarkMode = DarkModeComponent
|
|
64
66
|
export const Headline = HeadlineComponent
|
|
65
67
|
export const HeroSection = HeroSectionComponent
|