@androbinco/library-cli 0.1.0 → 0.3.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/README.md +86 -37
- package/package.json +11 -16
- package/src/commands/add.js +107 -0
- package/src/commands/list.js +51 -0
- package/src/index.js +46 -15
- package/src/templates/carousel/components/navigation-buttons.tsx +1 -0
- package/src/templates/carousel/components/pagination/bullet.pagination.carousel.tsx +69 -0
- package/src/templates/carousel/components/pagination/number.pagination.carousel.tsx +30 -0
- package/src/templates/carousel/components/pagination/progress/progress.pagination.carousel.tsx +99 -0
- package/src/templates/carousel/components/pagination/progress/use-slide-progress.tsx +31 -0
- package/src/templates/carousel/components/pagination.tsx +47 -82
- package/src/templates/faqs-accordion/examples/faqs-showcase.tsx +42 -0
- package/src/templates/faqs-accordion/faqs-accordion.tsx +70 -0
- package/src/templates/faqs-accordion/mock-data.ts +38 -0
- package/src/templates/faqs-accordion/types.ts +18 -0
- package/src/templates/in-view/data.in-view.ts +89 -0
- package/src/templates/in-view/examples/in-view-examples.home.tsx +101 -0
- package/src/templates/in-view/examples/in-view-grid-showcase.tsx +41 -0
- package/src/templates/in-view/in-view-animation.tsx +72 -0
- package/src/templates/in-view/in-view-grid.tsx +81 -0
- package/src/templates/in-view/in-view-hidden-text.tsx +45 -0
- package/src/templates/in-view/in-view-stroke-line.tsx +30 -0
- package/src/templates/lenis/examples/providers.tsx +23 -0
- package/src/templates/lenis/lenis-provider.tsx +46 -0
- package/src/templates/scroll-components/hooks/use-client-dimensions.ts +21 -0
- package/src/templates/scroll-components/parallax/examples/parallax-showcase.tsx +87 -0
- package/src/templates/scroll-components/parallax/parallax.css +36 -0
- package/src/templates/scroll-components/parallax/parallax.tsx +67 -0
- package/src/templates/scroll-components/scale-gallery/components/expanding-element.tsx +40 -0
- package/src/templates/scroll-components/scale-gallery/examples/scale-gallery-showcase.tsx +68 -0
- package/src/templates/scroll-components/scale-gallery/scale-gallery.tsx +57 -0
- package/src/templates/scroll-components/scroll-tracker-provider.tsx +78 -0
- package/src/templates/scroll-components/scroll-tracker-showcase.tsx +44 -0
- package/src/templates/strapi-dynamic-zone/README.md +157 -0
- package/src/templates/strapi-dynamic-zone/dynamic-zone.tsx +113 -0
- package/src/templates/strapi-dynamic-zone/examples/page.tsx +53 -0
- package/src/templates/strapi-dynamic-zone/examples/renderers.tsx +74 -0
- package/src/templates/strapi-dynamic-zone/examples/types.ts +41 -0
- package/src/templates/strapi-dynamic-zone/index.ts +11 -0
- package/src/templates/strapi-dynamic-zone/types.ts +73 -0
- package/src/templates/ticker/css-ticker/css-ticker.tsx +61 -0
- package/src/templates/ticker/css-ticker/ticker.keyframes.css +86 -0
- package/src/templates/ticker/examples/ticker-hover-showcase.home.tsx +57 -0
- package/src/templates/ticker/examples/ticker-static-showcase.home.tsx +56 -0
- package/src/templates/ticker/hooks/use-ticker-clones.tsx +70 -0
- package/src/templates/ticker/hooks/use-ticker-incremental.tsx +72 -0
- package/src/templates/ticker/motion-ticker.tsx +93 -0
- package/src/utils/components.js +587 -54
- package/src/utils/files.js +89 -5
- package/src/templates/button/button.tsx +0 -5
- package/src/templates/card/card.tsx +0 -5
- package/src/templates/example/example.tsx +0 -5
- package/src/templates/hero/hero.tsx +0 -5
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useSlideProgress = ({ isActive }: { isActive: boolean }) => {
|
|
4
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
5
|
+
const barRef = useRef<HTMLButtonElement>(null);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (!isActive) return;
|
|
9
|
+
const cancelDrag = () => setIsDragging(false);
|
|
10
|
+
|
|
11
|
+
if (isDragging) {
|
|
12
|
+
document.body.addEventListener('mouseup', cancelDrag);
|
|
13
|
+
document.body.addEventListener('touchend', cancelDrag);
|
|
14
|
+
barRef.current?.style.setProperty('cursor', 'grabbing');
|
|
15
|
+
document.body.style.setProperty('cursor', 'grabbing');
|
|
16
|
+
}
|
|
17
|
+
if (!isDragging) {
|
|
18
|
+
document.body.removeEventListener('mouseup', cancelDrag);
|
|
19
|
+
document.body.removeEventListener('touchend', cancelDrag);
|
|
20
|
+
document.body.style.setProperty('cursor', 'default');
|
|
21
|
+
barRef.current?.style.setProperty('cursor', 'grab');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
document.body.removeEventListener('mouseup', cancelDrag);
|
|
26
|
+
document.body.removeEventListener('touchend', cancelDrag);
|
|
27
|
+
};
|
|
28
|
+
}, [isDragging, isActive]);
|
|
29
|
+
|
|
30
|
+
return { isDragging, barRef, setIsDragging };
|
|
31
|
+
};
|
|
@@ -1,89 +1,54 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
import React from 'react';
|
|
2
3
|
|
|
3
|
-
import { cva, VariantProps } from 'class-variance-authority';
|
|
4
|
-
|
|
5
|
-
import { cn } from '@/common/utils/classname-builder';
|
|
6
|
-
|
|
7
4
|
import { useCarouselContext } from './provider/carousel.provider';
|
|
8
5
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { BulletPagination, DotPaginationProps } from './pagination/bullet.pagination.carousel';
|
|
7
|
+
import { NumberPagination, NumberPaginationProps } from './pagination/number.pagination.carousel';
|
|
8
|
+
import {
|
|
9
|
+
ProgressPagination,
|
|
10
|
+
ProgressPaginationProps,
|
|
11
|
+
} from './pagination/progress/progress.pagination.carousel';
|
|
12
|
+
|
|
13
|
+
type OmitContext<T> = Omit<T, 'selectedIndex' | 'scrollSnaps' | 'onDotButtonClick'>;
|
|
14
|
+
type PaginationProps =
|
|
15
|
+
| ({ type: 'number' } & OmitContext<NumberPaginationProps>)
|
|
16
|
+
| ({ type: 'progress' } & OmitContext<ProgressPaginationProps>)
|
|
17
|
+
| ({ type: 'bullet' } & OmitContext<DotPaginationProps>);
|
|
18
|
+
|
|
19
|
+
export const Pagination = (props: PaginationProps) => {
|
|
20
|
+
const { type, variant, className, ...restProps } = props;
|
|
12
21
|
const { scrollSnaps, selectedIndex, onDotButtonClick } = useCarouselContext();
|
|
13
22
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
if (type === 'dot')
|
|
49
|
-
return (
|
|
50
|
-
<div className={cn('mx-auto flex w-max gap-2', className)} {...props}>
|
|
51
|
-
{scrollSnaps.map((_, index) => (
|
|
52
|
-
<DotButton key={index} index={index} variant="primary" />
|
|
53
|
-
))}
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
type DotButtonVariants = VariantProps<typeof dotButtonVariants>['variant'];
|
|
59
|
-
const dotButtonVariants = cva(
|
|
60
|
-
'size-3 cursor-pointer rounded-full transition-all duration-300 ease-out focus:outline-2',
|
|
61
|
-
{
|
|
62
|
-
variants: {
|
|
63
|
-
variant: {
|
|
64
|
-
primary: 'bg-fill-brand-primary',
|
|
65
|
-
},
|
|
66
|
-
selected: {
|
|
67
|
-
true: 'w-9 !bg-amber-950',
|
|
68
|
-
false: '',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
export const DotButton: React.FC<{ index: number; variant: DotButtonVariants }> = ({
|
|
75
|
-
index,
|
|
76
|
-
variant = 'primary',
|
|
77
|
-
...restProps
|
|
78
|
-
}) => {
|
|
79
|
-
const { selectedIndex, onDotButtonClick } = useCarouselContext();
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<button
|
|
83
|
-
className={dotButtonVariants({ variant, selected: selectedIndex === index })}
|
|
84
|
-
disabled={selectedIndex === index}
|
|
85
|
-
onClick={() => onDotButtonClick(index)}
|
|
86
|
-
{...restProps}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
23
|
+
const paginationComponents = {
|
|
24
|
+
number: () => (
|
|
25
|
+
<NumberPagination
|
|
26
|
+
className={className}
|
|
27
|
+
scrollSnaps={scrollSnaps}
|
|
28
|
+
selectedIndex={selectedIndex}
|
|
29
|
+
variant={variant as NumberPaginationProps['variant']}
|
|
30
|
+
{...restProps}
|
|
31
|
+
/>
|
|
32
|
+
),
|
|
33
|
+
progress: () => (
|
|
34
|
+
<ProgressPagination
|
|
35
|
+
className={className}
|
|
36
|
+
scrollSnaps={scrollSnaps}
|
|
37
|
+
selectedIndex={selectedIndex}
|
|
38
|
+
variant={variant as ProgressPaginationProps['variant']}
|
|
39
|
+
onDotButtonClick={onDotButtonClick}
|
|
40
|
+
{...restProps}
|
|
41
|
+
/>
|
|
42
|
+
),
|
|
43
|
+
bullet: () => (
|
|
44
|
+
<BulletPagination
|
|
45
|
+
className={className}
|
|
46
|
+
scrollSnaps={scrollSnaps}
|
|
47
|
+
variant={variant as DotPaginationProps['variant']}
|
|
48
|
+
{...restProps}
|
|
49
|
+
/>
|
|
50
|
+
),
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
return paginationComponents[type]();
|
|
89
54
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { FaqsAccordion, MOCK_FAQS_DATA } from '../faqs-accordion';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Example showcase for FaqsAccordion component
|
|
7
|
+
*
|
|
8
|
+
* This simulates a Strapi API call with mock data.
|
|
9
|
+
* In production, replace MOCK_FAQS_DATA with:
|
|
10
|
+
*
|
|
11
|
+
* const response = await fetch('your-strapi-url/api/faqs?populate=questions');
|
|
12
|
+
* const faqs = await response.json();
|
|
13
|
+
*/
|
|
14
|
+
export default function FaqsShowcase() {
|
|
15
|
+
// Simulating Strapi response with mock data
|
|
16
|
+
const faqsData = MOCK_FAQS_DATA;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="min-h-screen bg-gray-50 py-12">
|
|
20
|
+
<div className="container mx-auto px-4">
|
|
21
|
+
<h1 className="mb-12 text-center text-4xl font-bold">
|
|
22
|
+
FAQs Accordion Example
|
|
23
|
+
</h1>
|
|
24
|
+
|
|
25
|
+
<FaqsAccordion faqs={faqsData} />
|
|
26
|
+
|
|
27
|
+
{/* Example with custom styling */}
|
|
28
|
+
<div className="mt-16">
|
|
29
|
+
<h2 className="mb-8 text-center text-3xl font-bold">
|
|
30
|
+
Custom Styled Version
|
|
31
|
+
</h2>
|
|
32
|
+
<FaqsAccordion
|
|
33
|
+
faqs={faqsData}
|
|
34
|
+
className="rounded-lg bg-white p-8 shadow-lg"
|
|
35
|
+
questionClassName="text-blue-600"
|
|
36
|
+
answerClassName="text-gray-700"
|
|
37
|
+
/>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import * as Accordion from '@radix-ui/react-accordion';
|
|
4
|
+
import { FaqsAccordionProps } from './types';
|
|
5
|
+
|
|
6
|
+
const ChevronDownIcon = ({ className }: { className?: string }) => (
|
|
7
|
+
<svg
|
|
8
|
+
width="24"
|
|
9
|
+
height="24"
|
|
10
|
+
viewBox="0 0 24 24"
|
|
11
|
+
fill="none"
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
className={className}
|
|
14
|
+
>
|
|
15
|
+
<path
|
|
16
|
+
d="M6 9L12 15L18 9"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
strokeWidth="2"
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
strokeLinejoin="round"
|
|
21
|
+
/>
|
|
22
|
+
</svg>
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
export const FaqsAccordion = ({
|
|
26
|
+
faqs,
|
|
27
|
+
className = '',
|
|
28
|
+
questionClassName = '',
|
|
29
|
+
answerClassName = '',
|
|
30
|
+
}: FaqsAccordionProps) => {
|
|
31
|
+
return (
|
|
32
|
+
<div className={`mx-auto w-full max-w-[910px] ${className}`}>
|
|
33
|
+
<h2 className="mb-8 text-3xl font-bold">{faqs.title}</h2>
|
|
34
|
+
|
|
35
|
+
<Accordion.Root type="single" collapsible className="w-full">
|
|
36
|
+
{faqs.questions.map((faq, index) => (
|
|
37
|
+
<div key={faq.id}>
|
|
38
|
+
<Accordion.Item value={`item-${faq.id}`} className="border-b">
|
|
39
|
+
<Accordion.Header>
|
|
40
|
+
<Accordion.Trigger
|
|
41
|
+
className={`group flex w-full items-center justify-between py-6 text-left transition-all hover:opacity-80 ${questionClassName}`}
|
|
42
|
+
>
|
|
43
|
+
<span className="text-lg font-semibold">{faq.question}</span>
|
|
44
|
+
<ChevronDownIcon className="transition-transform duration-300 group-data-[state=open]:rotate-180" />
|
|
45
|
+
</Accordion.Trigger>
|
|
46
|
+
</Accordion.Header>
|
|
47
|
+
|
|
48
|
+
<Accordion.Content
|
|
49
|
+
className={`overflow-hidden transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down ${answerClassName}`}
|
|
50
|
+
>
|
|
51
|
+
<div className="pb-6 text-base text-gray-600">
|
|
52
|
+
{faq.answer}
|
|
53
|
+
</div>
|
|
54
|
+
</Accordion.Content>
|
|
55
|
+
</Accordion.Item>
|
|
56
|
+
</div>
|
|
57
|
+
))}
|
|
58
|
+
</Accordion.Root>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default FaqsAccordion;
|
|
64
|
+
|
|
65
|
+
export type {
|
|
66
|
+
FaqsAccordionProps,
|
|
67
|
+
FaqsResponse,
|
|
68
|
+
FaqQuestion,
|
|
69
|
+
} from './types';
|
|
70
|
+
export { MOCK_FAQS_DATA } from './mock-data';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FaqsResponse } from './types';
|
|
2
|
+
|
|
3
|
+
export const MOCK_FAQS_DATA: FaqsResponse = {
|
|
4
|
+
id: 1,
|
|
5
|
+
title: 'Frequently Asked Questions',
|
|
6
|
+
questions: [
|
|
7
|
+
{
|
|
8
|
+
id: 1,
|
|
9
|
+
question: 'What is the return policy?',
|
|
10
|
+
answer:
|
|
11
|
+
'You can return any item within 30 days of purchase for a full refund. Items must be in original condition with tags attached.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
id: 2,
|
|
15
|
+
question: 'How long does shipping take?',
|
|
16
|
+
answer:
|
|
17
|
+
'Standard shipping takes 5-7 business days. Express shipping is available and takes 2-3 business days.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 3,
|
|
21
|
+
question: 'Do you ship internationally?',
|
|
22
|
+
answer:
|
|
23
|
+
'Yes, we ship to over 50 countries worldwide. International shipping times vary by location.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 4,
|
|
27
|
+
question: 'How do I track my order?',
|
|
28
|
+
answer:
|
|
29
|
+
'Once your order ships, you\'ll receive a tracking number via email. You can use this to track your package on our website.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 5,
|
|
33
|
+
question: 'What payment methods do you accept?',
|
|
34
|
+
answer:
|
|
35
|
+
'We accept all major credit cards, PayPal, Apple Pay, and Google Pay for your convenience.',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type FaqQuestion = {
|
|
2
|
+
id: number;
|
|
3
|
+
question: string;
|
|
4
|
+
answer: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type FaqsResponse = {
|
|
8
|
+
id: number;
|
|
9
|
+
title: string;
|
|
10
|
+
questions: FaqQuestion[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type FaqsAccordionProps = {
|
|
14
|
+
faqs: FaqsResponse;
|
|
15
|
+
className?: string;
|
|
16
|
+
questionClassName?: string;
|
|
17
|
+
answerClassName?: string;
|
|
18
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const IN_VIEW_ANIMATIONS = {
|
|
2
|
+
fadeInUp: {
|
|
3
|
+
hidden: {
|
|
4
|
+
y: '100px',
|
|
5
|
+
opacity: 0,
|
|
6
|
+
},
|
|
7
|
+
visible: {
|
|
8
|
+
opacity: 1,
|
|
9
|
+
y: '0%',
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
fadeInLeft: {
|
|
13
|
+
hidden: { opacity: 0, transform: `translateX(-100px)` },
|
|
14
|
+
visible: { opacity: 1, transform: `translateX(0px)` },
|
|
15
|
+
},
|
|
16
|
+
fadeInDown: {
|
|
17
|
+
hidden: { opacity: 0, transform: `translateY(-50px)` },
|
|
18
|
+
visible: { opacity: 1, transform: `translateY(0px)` },
|
|
19
|
+
},
|
|
20
|
+
fadeInRight: {
|
|
21
|
+
hidden: { opacity: 0, transform: `translateX(100px)` },
|
|
22
|
+
visible: { opacity: 1, transform: `translateX(0px)` },
|
|
23
|
+
},
|
|
24
|
+
opacity: {
|
|
25
|
+
hidden: { opacity: 0 },
|
|
26
|
+
visible: { opacity: 1 },
|
|
27
|
+
},
|
|
28
|
+
imgBlur: {
|
|
29
|
+
hidden: {
|
|
30
|
+
filter: 'blur(10px)',
|
|
31
|
+
backdropFilter: 'blur(10px)',
|
|
32
|
+
WebkitBackdropFilter: 'blur(10px)',
|
|
33
|
+
overflow: 'hidden',
|
|
34
|
+
},
|
|
35
|
+
visible: {
|
|
36
|
+
overflow: 'hidden',
|
|
37
|
+
filter: 'blur(0px)',
|
|
38
|
+
backdropFilter: 'blur(0px)',
|
|
39
|
+
WebkitBackdropFilter: 'blur(0)',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
scaleX: {
|
|
43
|
+
hidden: {
|
|
44
|
+
scaleX: 0,
|
|
45
|
+
},
|
|
46
|
+
visible: {
|
|
47
|
+
scaleX: 1,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
strokeLine: {
|
|
51
|
+
hidden: {
|
|
52
|
+
scaleX: 0.001,
|
|
53
|
+
transformOrigin: 'left center',
|
|
54
|
+
},
|
|
55
|
+
visible: {
|
|
56
|
+
scaleX: 1,
|
|
57
|
+
transformOrigin: 'left center',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
slideInUp: {
|
|
61
|
+
hidden: {
|
|
62
|
+
y: '85%',
|
|
63
|
+
},
|
|
64
|
+
visible: {
|
|
65
|
+
y: '0%',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
slideInLeftFull: {
|
|
69
|
+
hidden: {
|
|
70
|
+
x: '-100%',
|
|
71
|
+
},
|
|
72
|
+
visible: {
|
|
73
|
+
x: '0%',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
fadeInRightFull: {
|
|
77
|
+
hidden: {
|
|
78
|
+
opacity: 0,
|
|
79
|
+
x: '100%',
|
|
80
|
+
},
|
|
81
|
+
visible: {
|
|
82
|
+
opacity: 1,
|
|
83
|
+
x: '0%',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export default IN_VIEW_ANIMATIONS;
|
|
89
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Fragment } from "react";
|
|
2
|
+
|
|
3
|
+
import InViewAnimation from "../in-view-animation";
|
|
4
|
+
import { InViewHiddenText } from "../in-view/in-view-hidden-text";
|
|
5
|
+
import { InViewStrokeLine } from "../in-view/in-view-stroke-line";
|
|
6
|
+
import { Text } from "@/common/ui/text/text";
|
|
7
|
+
|
|
8
|
+
const InViewExampleCard = ({ text }: { text?: string }) => {
|
|
9
|
+
return (
|
|
10
|
+
<div className="flex flex-col items-center justify-center h-50 w-full rounded-2xl border-2 border-fill-brand-primary bg-bg-primary-inverse p-2">
|
|
11
|
+
<Text
|
|
12
|
+
className="text-text-interactive-neutral-primary-inverse"
|
|
13
|
+
variant="title.6"
|
|
14
|
+
>
|
|
15
|
+
{text}
|
|
16
|
+
</Text>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const InViewExamplesHome = () => {
|
|
22
|
+
return (
|
|
23
|
+
<div className="container mx-auto max-w-480">
|
|
24
|
+
<Text className="pb-15" variant="title.6">
|
|
25
|
+
In View Examples {"(Individual Elements)"}
|
|
26
|
+
</Text>
|
|
27
|
+
<div className="grid w-full gap-2 gap-y-2 overflow-hidden max-lg:grid-cols-1 lg:grid-cols-3 lg:gap-y-10">
|
|
28
|
+
<InViewAnimation effect="fadeInLeft">
|
|
29
|
+
<InViewExampleCard text="Fade Left Effect" />
|
|
30
|
+
</InViewAnimation>
|
|
31
|
+
<InViewAnimation
|
|
32
|
+
effect="opacity"
|
|
33
|
+
transition={{
|
|
34
|
+
delay: 0.2,
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<InViewExampleCard text="Opacity Effect" />
|
|
38
|
+
</InViewAnimation>
|
|
39
|
+
<InViewAnimation effect="fadeInRight">
|
|
40
|
+
<InViewExampleCard text="Fade Right Effect" />
|
|
41
|
+
</InViewAnimation>
|
|
42
|
+
<div className="flex w-full flex-col flex-wrap justify-end gap-5 lg:col-span-2">
|
|
43
|
+
<InViewStrokeLine
|
|
44
|
+
className="bg-fill-brand-primary opacity-40"
|
|
45
|
+
transition={{
|
|
46
|
+
duration: 0.8,
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
<InViewHiddenText>
|
|
50
|
+
<Text className="py-1 text-grey-100-80">
|
|
51
|
+
Hidden text effect and stroke line
|
|
52
|
+
</Text>
|
|
53
|
+
</InViewHiddenText>
|
|
54
|
+
|
|
55
|
+
{Array.from({ length: 4 }).map((_, index) => (
|
|
56
|
+
<Fragment key={index}>
|
|
57
|
+
<InViewStrokeLine
|
|
58
|
+
className="bg-fill-brand-primary opacity-40"
|
|
59
|
+
transition={{
|
|
60
|
+
duration: 0.8,
|
|
61
|
+
delay: 0.1 * (index + 1),
|
|
62
|
+
}}
|
|
63
|
+
/>
|
|
64
|
+
<InViewHiddenText
|
|
65
|
+
transition={{
|
|
66
|
+
delay: 0.2 * (index + 1),
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<Text className="text-grey-100-80">
|
|
70
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
71
|
+
</Text>
|
|
72
|
+
</InViewHiddenText>
|
|
73
|
+
</Fragment>
|
|
74
|
+
))}
|
|
75
|
+
<InViewStrokeLine
|
|
76
|
+
className="bg-fill-brand-primary opacity-40"
|
|
77
|
+
transition={{
|
|
78
|
+
duration: 0.8,
|
|
79
|
+
delay: 0.4,
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
<InViewAnimation
|
|
84
|
+
className="lg:col-start-3"
|
|
85
|
+
effect="imgBlur"
|
|
86
|
+
once={false}
|
|
87
|
+
>
|
|
88
|
+
<Center className="relative h-102 w-full overflow-hidden rounded-2xl bg-fill-brand-primary">
|
|
89
|
+
<img alt="Placeholder" src="/img/racti-sireno.jpeg" />
|
|
90
|
+
<Text
|
|
91
|
+
className="absolute bottom-1/4 rounded-2xl bg-grey-50-30 p-2 text-text-primary"
|
|
92
|
+
variant="title.6"
|
|
93
|
+
>
|
|
94
|
+
Blur Effect
|
|
95
|
+
</Text>
|
|
96
|
+
</Center>
|
|
97
|
+
</InViewAnimation>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { GridInView } from "@/common/animations/in-view/in-view-grid";
|
|
2
|
+
import { Center } from "@/common/ui/containers/center";
|
|
3
|
+
import { Text } from "@/common/ui/text/text";
|
|
4
|
+
import { cn } from "@/common/utils/classname-builder";
|
|
5
|
+
|
|
6
|
+
const CardComponent = ({
|
|
7
|
+
pepito,
|
|
8
|
+
className,
|
|
9
|
+
}: {
|
|
10
|
+
pepito: number;
|
|
11
|
+
className?: string;
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<div className="flex flex-col items-center justify-center h-50 w-full rounded-2xl border-2 border-fill-brand-primary bg-bg-primary-inverse p-2">
|
|
15
|
+
<Text>{pepito}</Text>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const InViewGridShowcase = () => {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<div>
|
|
24
|
+
<h1>In View Grid:</h1>
|
|
25
|
+
<GridInView columns={5} delayByColumn={false}>
|
|
26
|
+
{Array.from({ length: 10 }, (_, index) => index).map((item) => (
|
|
27
|
+
<CardComponent key={item} pepito={item + 1} />
|
|
28
|
+
))}
|
|
29
|
+
</GridInView>
|
|
30
|
+
</div>
|
|
31
|
+
<div>
|
|
32
|
+
<h1>In View Grid with delay by column:</h1>
|
|
33
|
+
<GridInView columns={{ desktop: 4, mobile: 2 }}>
|
|
34
|
+
{Array.from({ length: 12 }, (_, index) => index).map((item) => (
|
|
35
|
+
<CardComponent key={item} className="h-100" pepito={item + 1} />
|
|
36
|
+
))}
|
|
37
|
+
</GridInView>
|
|
38
|
+
</div>
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { FC, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
motion,
|
|
6
|
+
MotionProps,
|
|
7
|
+
TargetAndTransition,
|
|
8
|
+
Transition,
|
|
9
|
+
} from 'motion/react';
|
|
10
|
+
|
|
11
|
+
import IN_VIEW_ANIMATIONS from './data.in-view';
|
|
12
|
+
|
|
13
|
+
const transitionsDefault: Transition = {
|
|
14
|
+
duration: 0.6,
|
|
15
|
+
delay: 0,
|
|
16
|
+
ease: 'easeInOut',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type InViewAnimationProps = {
|
|
20
|
+
margin?: string;
|
|
21
|
+
transition?: Transition;
|
|
22
|
+
effect?: keyof typeof IN_VIEW_ANIMATIONS;
|
|
23
|
+
customEffect?: {
|
|
24
|
+
hidden: TargetAndTransition;
|
|
25
|
+
visible: TargetAndTransition;
|
|
26
|
+
};
|
|
27
|
+
execute?: boolean;
|
|
28
|
+
once?: boolean;
|
|
29
|
+
style?: React.CSSProperties;
|
|
30
|
+
className?: string;
|
|
31
|
+
children?: ReactNode;
|
|
32
|
+
} & MotionProps &
|
|
33
|
+
React.HTMLAttributes<HTMLDivElement>;
|
|
34
|
+
|
|
35
|
+
const InViewAnimation: FC<InViewAnimationProps> = ({
|
|
36
|
+
margin = '-10% 0%',
|
|
37
|
+
execute = true,
|
|
38
|
+
transition = {},
|
|
39
|
+
customEffect,
|
|
40
|
+
effect = 'fadeInUp',
|
|
41
|
+
once = true,
|
|
42
|
+
style,
|
|
43
|
+
className,
|
|
44
|
+
children,
|
|
45
|
+
...props
|
|
46
|
+
}) => (
|
|
47
|
+
<motion.div
|
|
48
|
+
className={className}
|
|
49
|
+
initial={customEffect?.hidden || IN_VIEW_ANIMATIONS[effect].hidden}
|
|
50
|
+
style={style}
|
|
51
|
+
transition={{
|
|
52
|
+
...transitionsDefault,
|
|
53
|
+
...transition,
|
|
54
|
+
}}
|
|
55
|
+
viewport={
|
|
56
|
+
execute
|
|
57
|
+
? {
|
|
58
|
+
once,
|
|
59
|
+
margin,
|
|
60
|
+
}
|
|
61
|
+
: {}
|
|
62
|
+
}
|
|
63
|
+
whileInView={
|
|
64
|
+
execute ? customEffect?.visible || IN_VIEW_ANIMATIONS[effect].visible : {}
|
|
65
|
+
}
|
|
66
|
+
{...props}
|
|
67
|
+
>
|
|
68
|
+
{children}
|
|
69
|
+
</motion.div>
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export default InViewAnimation;
|