@opensite/ui 0.7.9 → 0.8.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/dist/carousel-feature-badge.cjs +114 -214
- package/dist/carousel-feature-badge.js +114 -214
- package/dist/carousel-horizontal-cards.cjs +283 -211
- package/dist/carousel-horizontal-cards.d.cts +5 -1
- package/dist/carousel-horizontal-cards.d.ts +5 -1
- package/dist/carousel-horizontal-cards.js +283 -211
- package/dist/carousel-pagination.cjs +601 -0
- package/dist/carousel-pagination.d.cts +75 -0
- package/dist/carousel-pagination.d.ts +75 -0
- package/dist/carousel-pagination.js +579 -0
- package/dist/components.cjs +45 -0
- package/dist/components.d.cts +1 -0
- package/dist/components.d.ts +1 -0
- package/dist/components.js +45 -1
- package/dist/index.cjs +45 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +45 -1
- package/dist/registry.cjs +424 -309
- package/dist/registry.js +424 -309
- package/package.json +6 -1
|
@@ -5,8 +5,8 @@ var React = require('react');
|
|
|
5
5
|
var framerMotion = require('framer-motion');
|
|
6
6
|
var clsx = require('clsx');
|
|
7
7
|
var tailwindMerge = require('tailwind-merge');
|
|
8
|
-
var classVarianceAuthority = require('class-variance-authority');
|
|
9
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
10
10
|
var img = require('@page-speed/img');
|
|
11
11
|
|
|
12
12
|
function _interopNamespace(e) {
|
|
@@ -33,6 +33,111 @@ var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
|
33
33
|
function cn(...inputs) {
|
|
34
34
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
35
35
|
}
|
|
36
|
+
var svgCache = /* @__PURE__ */ new Map();
|
|
37
|
+
function DynamicIcon({
|
|
38
|
+
name,
|
|
39
|
+
size = 28,
|
|
40
|
+
color,
|
|
41
|
+
className,
|
|
42
|
+
alt
|
|
43
|
+
}) {
|
|
44
|
+
const [svgContent, setSvgContent] = React__namespace.useState(null);
|
|
45
|
+
const [isLoading, setIsLoading] = React__namespace.useState(true);
|
|
46
|
+
const [error, setError] = React__namespace.useState(null);
|
|
47
|
+
const { url, iconName } = React__namespace.useMemo(() => {
|
|
48
|
+
const separator = name.includes("/") ? "/" : ":";
|
|
49
|
+
const [prefix, iconName2] = name.split(separator);
|
|
50
|
+
const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}`;
|
|
51
|
+
return {
|
|
52
|
+
url: baseUrl,
|
|
53
|
+
iconName: iconName2
|
|
54
|
+
};
|
|
55
|
+
}, [name, size]);
|
|
56
|
+
React__namespace.useEffect(() => {
|
|
57
|
+
let isMounted = true;
|
|
58
|
+
const fetchSvg = async () => {
|
|
59
|
+
const cached = svgCache.get(url);
|
|
60
|
+
if (cached) {
|
|
61
|
+
if (isMounted) {
|
|
62
|
+
setSvgContent(cached);
|
|
63
|
+
setIsLoading(false);
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
setIsLoading(true);
|
|
69
|
+
setError(null);
|
|
70
|
+
const response = await fetch(url);
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
throw new Error(`Failed to fetch icon: ${response.status}`);
|
|
73
|
+
}
|
|
74
|
+
let svg = await response.text();
|
|
75
|
+
svg = processSvgForCurrentColor(svg);
|
|
76
|
+
svgCache.set(url, svg);
|
|
77
|
+
if (isMounted) {
|
|
78
|
+
setSvgContent(svg);
|
|
79
|
+
setIsLoading(false);
|
|
80
|
+
}
|
|
81
|
+
} catch (err) {
|
|
82
|
+
if (isMounted) {
|
|
83
|
+
setError(err instanceof Error ? err.message : "Failed to load icon");
|
|
84
|
+
setIsLoading(false);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
fetchSvg();
|
|
89
|
+
return () => {
|
|
90
|
+
isMounted = false;
|
|
91
|
+
};
|
|
92
|
+
}, [url]);
|
|
93
|
+
if (isLoading) {
|
|
94
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
95
|
+
"span",
|
|
96
|
+
{
|
|
97
|
+
className: cn("inline-block", className),
|
|
98
|
+
style: { width: size, height: size },
|
|
99
|
+
"aria-hidden": "true"
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
if (error || !svgContent) {
|
|
104
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
105
|
+
"span",
|
|
106
|
+
{
|
|
107
|
+
className: cn("inline-block", className),
|
|
108
|
+
style: { width: size, height: size },
|
|
109
|
+
role: "img",
|
|
110
|
+
"aria-label": alt || iconName
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
115
|
+
"span",
|
|
116
|
+
{
|
|
117
|
+
className: cn("inline-flex items-center justify-center", className),
|
|
118
|
+
style: {
|
|
119
|
+
width: size,
|
|
120
|
+
height: size,
|
|
121
|
+
color: color || "inherit"
|
|
122
|
+
},
|
|
123
|
+
role: "img",
|
|
124
|
+
"aria-label": alt || iconName,
|
|
125
|
+
dangerouslySetInnerHTML: { __html: svgContent }
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
function processSvgForCurrentColor(svg) {
|
|
130
|
+
let processed = svg;
|
|
131
|
+
processed = processed.replace(
|
|
132
|
+
/stroke=["'](#000000|#000|black)["']/gi,
|
|
133
|
+
'stroke="currentColor"'
|
|
134
|
+
);
|
|
135
|
+
processed = processed.replace(
|
|
136
|
+
/fill=["'](#000000|#000|black)["']/gi,
|
|
137
|
+
'fill="currentColor"'
|
|
138
|
+
);
|
|
139
|
+
return processed;
|
|
140
|
+
}
|
|
36
141
|
function normalizePhoneNumber(input) {
|
|
37
142
|
const trimmed = input.trim();
|
|
38
143
|
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
@@ -451,110 +556,49 @@ var Pressable = React__namespace.forwardRef(
|
|
|
451
556
|
}
|
|
452
557
|
);
|
|
453
558
|
Pressable.displayName = "Pressable";
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
559
|
+
function CarouselPagination({
|
|
560
|
+
onPrevious,
|
|
561
|
+
onNext,
|
|
562
|
+
canScrollPrevious = true,
|
|
563
|
+
canScrollNext = true,
|
|
564
|
+
iconSize = 24,
|
|
459
565
|
className,
|
|
460
|
-
|
|
566
|
+
buttonClassName,
|
|
567
|
+
previousIcon = "lucide/arrow-left",
|
|
568
|
+
nextIcon = "lucide/arrow-right",
|
|
569
|
+
previousAriaLabel = "Previous",
|
|
570
|
+
nextAriaLabel = "Next"
|
|
461
571
|
}) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
const { url, iconName } = React__namespace.useMemo(() => {
|
|
466
|
-
const separator = name.includes("/") ? "/" : ":";
|
|
467
|
-
const [prefix, iconName2] = name.split(separator);
|
|
468
|
-
const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}`;
|
|
469
|
-
return {
|
|
470
|
-
url: baseUrl,
|
|
471
|
-
iconName: iconName2
|
|
472
|
-
};
|
|
473
|
-
}, [name, size]);
|
|
474
|
-
React__namespace.useEffect(() => {
|
|
475
|
-
let isMounted = true;
|
|
476
|
-
const fetchSvg = async () => {
|
|
477
|
-
const cached = svgCache.get(url);
|
|
478
|
-
if (cached) {
|
|
479
|
-
if (isMounted) {
|
|
480
|
-
setSvgContent(cached);
|
|
481
|
-
setIsLoading(false);
|
|
482
|
-
}
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
try {
|
|
486
|
-
setIsLoading(true);
|
|
487
|
-
setError(null);
|
|
488
|
-
const response = await fetch(url);
|
|
489
|
-
if (!response.ok) {
|
|
490
|
-
throw new Error(`Failed to fetch icon: ${response.status}`);
|
|
491
|
-
}
|
|
492
|
-
let svg = await response.text();
|
|
493
|
-
svg = processSvgForCurrentColor(svg);
|
|
494
|
-
svgCache.set(url, svg);
|
|
495
|
-
if (isMounted) {
|
|
496
|
-
setSvgContent(svg);
|
|
497
|
-
setIsLoading(false);
|
|
498
|
-
}
|
|
499
|
-
} catch (err) {
|
|
500
|
-
if (isMounted) {
|
|
501
|
-
setError(err instanceof Error ? err.message : "Failed to load icon");
|
|
502
|
-
setIsLoading(false);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
fetchSvg();
|
|
507
|
-
return () => {
|
|
508
|
-
isMounted = false;
|
|
509
|
-
};
|
|
510
|
-
}, [url]);
|
|
511
|
-
if (isLoading) {
|
|
512
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
513
|
-
"span",
|
|
572
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex justify-end gap-2", className), children: [
|
|
573
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
574
|
+
Pressable,
|
|
514
575
|
{
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
"aria-
|
|
576
|
+
onClick: onPrevious,
|
|
577
|
+
disabled: !canScrollPrevious,
|
|
578
|
+
"aria-label": previousAriaLabel,
|
|
579
|
+
asButton: true,
|
|
580
|
+
className: cn(
|
|
581
|
+
"relative z-40 flex h-10 w-10 items-center justify-center rounded-full disabled:opacity-50",
|
|
582
|
+
buttonClassName
|
|
583
|
+
),
|
|
584
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: previousIcon, size: iconSize })
|
|
518
585
|
}
|
|
519
|
-
)
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
523
|
-
"span",
|
|
586
|
+
),
|
|
587
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
588
|
+
Pressable,
|
|
524
589
|
{
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
590
|
+
onClick: onNext,
|
|
591
|
+
disabled: !canScrollNext,
|
|
592
|
+
"aria-label": nextAriaLabel,
|
|
593
|
+
asButton: true,
|
|
594
|
+
className: cn(
|
|
595
|
+
"relative z-40 flex h-10 w-10 items-center justify-center rounded-full disabled:opacity-50",
|
|
596
|
+
buttonClassName
|
|
597
|
+
),
|
|
598
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: nextIcon, size: iconSize })
|
|
529
599
|
}
|
|
530
|
-
)
|
|
531
|
-
}
|
|
532
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
533
|
-
"span",
|
|
534
|
-
{
|
|
535
|
-
className: cn("inline-flex items-center justify-center", className),
|
|
536
|
-
style: {
|
|
537
|
-
width: size,
|
|
538
|
-
height: size,
|
|
539
|
-
color: color || "inherit"
|
|
540
|
-
},
|
|
541
|
-
role: "img",
|
|
542
|
-
"aria-label": alt || iconName,
|
|
543
|
-
dangerouslySetInnerHTML: { __html: svgContent }
|
|
544
|
-
}
|
|
545
|
-
);
|
|
546
|
-
}
|
|
547
|
-
function processSvgForCurrentColor(svg) {
|
|
548
|
-
let processed = svg;
|
|
549
|
-
processed = processed.replace(
|
|
550
|
-
/stroke=["'](#000000|#000|black)["']/gi,
|
|
551
|
-
'stroke="currentColor"'
|
|
552
|
-
);
|
|
553
|
-
processed = processed.replace(
|
|
554
|
-
/fill=["'](#000000|#000|black)["']/gi,
|
|
555
|
-
'fill="currentColor"'
|
|
556
|
-
);
|
|
557
|
-
return processed;
|
|
600
|
+
)
|
|
601
|
+
] });
|
|
558
602
|
}
|
|
559
603
|
var maxWidthStyles = {
|
|
560
604
|
sm: "max-w-screen-sm",
|
|
@@ -953,28 +997,22 @@ function CarouselHorizontalCards({
|
|
|
953
997
|
const carouselRef = React__namespace.useRef(null);
|
|
954
998
|
const [isAtStart, setIsAtStart] = React__namespace.useState(true);
|
|
955
999
|
const [isAtEnd, setIsAtEnd] = React__namespace.useState(false);
|
|
956
|
-
const
|
|
957
|
-
if (
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
const scroll = (direction) => {
|
|
1000
|
+
const scrollLeft = () => {
|
|
1001
|
+
if (carouselRef.current) {
|
|
1002
|
+
carouselRef.current.scrollBy({ left: -300, behavior: "smooth" });
|
|
1003
|
+
}
|
|
1004
|
+
};
|
|
1005
|
+
const scrollRight = () => {
|
|
963
1006
|
if (carouselRef.current) {
|
|
964
|
-
|
|
965
|
-
const cardWidth = getCardWidth();
|
|
966
|
-
const gap = 16;
|
|
967
|
-
const scrollAmount = cardWidth + gap;
|
|
968
|
-
const newScrollLeft = direction === "left" ? scrollLeft - scrollAmount : scrollLeft + scrollAmount;
|
|
969
|
-
carouselRef.current.scrollTo({ left: newScrollLeft, behavior: "smooth" });
|
|
1007
|
+
carouselRef.current.scrollBy({ left: 300, behavior: "smooth" });
|
|
970
1008
|
}
|
|
971
1009
|
};
|
|
972
1010
|
React__namespace.useEffect(() => {
|
|
973
1011
|
const checkScrollPosition = () => {
|
|
974
1012
|
if (carouselRef.current) {
|
|
975
|
-
const { scrollLeft, scrollWidth, clientWidth } = carouselRef.current;
|
|
976
|
-
setIsAtStart(
|
|
977
|
-
setIsAtEnd(
|
|
1013
|
+
const { scrollLeft: scrollLeft2, scrollWidth, clientWidth } = carouselRef.current;
|
|
1014
|
+
setIsAtStart(scrollLeft2 < 10);
|
|
1015
|
+
setIsAtEnd(scrollLeft2 + clientWidth >= scrollWidth - 10);
|
|
978
1016
|
}
|
|
979
1017
|
};
|
|
980
1018
|
const currentRef = carouselRef.current;
|
|
@@ -990,41 +1028,6 @@ function CarouselHorizontalCards({
|
|
|
990
1028
|
window.removeEventListener("resize", checkScrollPosition);
|
|
991
1029
|
};
|
|
992
1030
|
}, [items]);
|
|
993
|
-
const renderItems = () => {
|
|
994
|
-
if (itemsSlot) return itemsSlot;
|
|
995
|
-
if (!items || items.length === 0) return null;
|
|
996
|
-
return items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
997
|
-
framerMotion.motion.div,
|
|
998
|
-
{
|
|
999
|
-
className: cn(
|
|
1000
|
-
"group w-[320px] shrink-0 snap-start sm:w-[360px] lg:w-[400px]",
|
|
1001
|
-
item.className
|
|
1002
|
-
),
|
|
1003
|
-
initial: { opacity: 0, y: 20 },
|
|
1004
|
-
animate: { opacity: 1, y: 0 },
|
|
1005
|
-
transition: { duration: 0.5, delay: index * 0.1 },
|
|
1006
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border bg-card text-card-foreground shadow-sm transition-shadow hover:shadow-md", children: [
|
|
1007
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1008
|
-
img.Img,
|
|
1009
|
-
{
|
|
1010
|
-
alt: typeof item.title === "string" ? item.title : `Card ${index + 1}`,
|
|
1011
|
-
className: cn("aspect-video w-full object-cover transition-transform group-hover:scale-105", item.imageClassName),
|
|
1012
|
-
src: item.imageSrc,
|
|
1013
|
-
optixFlowConfig
|
|
1014
|
-
}
|
|
1015
|
-
),
|
|
1016
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1017
|
-
item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-md font-semibold leading-tight text-card-foreground", children: item.title }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.title })),
|
|
1018
|
-
(item.count !== void 0 || item.countLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
|
|
1019
|
-
item.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-bold", children: item.count }),
|
|
1020
|
-
item.countLabel && (typeof item.countLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: item.countLabel }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.countLabel }))
|
|
1021
|
-
] })
|
|
1022
|
-
] })
|
|
1023
|
-
] })
|
|
1024
|
-
},
|
|
1025
|
-
item.id
|
|
1026
|
-
));
|
|
1027
|
-
};
|
|
1028
1031
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1029
1032
|
Section,
|
|
1030
1033
|
{
|
|
@@ -1035,74 +1038,143 @@ function CarouselHorizontalCards({
|
|
|
1035
1038
|
patternOpacity,
|
|
1036
1039
|
"aria-labelledby": "carousel-title",
|
|
1037
1040
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("container mx-auto px-4 md:px-6", containerClassName), children: [
|
|
1038
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1041
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1042
|
+
"div",
|
|
1043
|
+
{
|
|
1044
|
+
className: cn(
|
|
1045
|
+
"mb-8 flex items-center justify-between gap-4",
|
|
1046
|
+
headerClassName
|
|
1047
|
+
),
|
|
1048
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1049
|
+
heading && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: headingHref, className: "group inline-flex items-center", children: [
|
|
1050
|
+
typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1051
|
+
"h2",
|
|
1052
|
+
{
|
|
1053
|
+
id: "carousel-title",
|
|
1054
|
+
className: cn(
|
|
1055
|
+
"text-2xl font-bold tracking-tight text-card-foreground md:text-3xl",
|
|
1056
|
+
headingClassName
|
|
1057
|
+
),
|
|
1058
|
+
children: heading
|
|
1059
|
+
}
|
|
1060
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading }),
|
|
1061
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1062
|
+
DynamicIcon,
|
|
1063
|
+
{
|
|
1064
|
+
name: "lucide/chevron-right",
|
|
1065
|
+
size: 24,
|
|
1066
|
+
className: "ml-2 shrink-0 self-center transition-transform group-hover:translate-x-1"
|
|
1067
|
+
}
|
|
1068
|
+
)
|
|
1069
|
+
] }),
|
|
1070
|
+
subtitle && (typeof subtitle === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1071
|
+
"p",
|
|
1072
|
+
{
|
|
1073
|
+
className: cn(
|
|
1074
|
+
"mt-1 text-muted-foreground",
|
|
1075
|
+
subtitleClassName
|
|
1076
|
+
),
|
|
1077
|
+
children: subtitle
|
|
1078
|
+
}
|
|
1079
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: subtitleClassName, children: subtitle }))
|
|
1080
|
+
] })
|
|
1081
|
+
}
|
|
1082
|
+
),
|
|
1083
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
|
|
1060
1084
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1061
1085
|
"div",
|
|
1062
1086
|
{
|
|
1087
|
+
className: "flex w-full overflow-x-scroll overscroll-x-auto scroll-smooth py-4 [scrollbar-width:none] md:py-6",
|
|
1063
1088
|
ref: carouselRef,
|
|
1064
|
-
|
|
1065
|
-
"
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1089
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1090
|
+
"div",
|
|
1091
|
+
{
|
|
1092
|
+
className: cn(
|
|
1093
|
+
"flex flex-row justify-start gap-4 pl-4",
|
|
1094
|
+
carouselClassName
|
|
1095
|
+
),
|
|
1096
|
+
children: [
|
|
1097
|
+
items?.map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1098
|
+
framerMotion.motion.div,
|
|
1099
|
+
{
|
|
1100
|
+
className: cn(
|
|
1101
|
+
"rounded-lg last:pr-[5%] md:last:pr-[33%]"
|
|
1102
|
+
),
|
|
1103
|
+
initial: { opacity: 0, y: 20 },
|
|
1104
|
+
animate: { opacity: 1, y: 0 },
|
|
1105
|
+
transition: { duration: 0.5, delay: 0.2 * index, ease: "easeOut" },
|
|
1106
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1107
|
+
"div",
|
|
1108
|
+
{
|
|
1109
|
+
className: cn(
|
|
1110
|
+
"group w-56 shrink-0 md:w-96",
|
|
1111
|
+
item.className
|
|
1112
|
+
),
|
|
1113
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-lg border bg-card text-card-foreground shadow-sm transition-shadow hover:shadow-md", children: [
|
|
1114
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1115
|
+
img.Img,
|
|
1116
|
+
{
|
|
1117
|
+
alt: typeof item.title === "string" ? item.title : `Card ${index + 1}`,
|
|
1118
|
+
className: cn(
|
|
1119
|
+
"aspect-video w-full object-cover transition-transform group-hover:scale-105",
|
|
1120
|
+
item.imageClassName
|
|
1121
|
+
),
|
|
1122
|
+
src: item.imageSrc,
|
|
1123
|
+
optixFlowConfig
|
|
1124
|
+
}
|
|
1125
|
+
),
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4", children: [
|
|
1127
|
+
item.title && (typeof item.title === "string" ? /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-md font-semibold leading-tight text-card-foreground", children: item.title }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.title })),
|
|
1128
|
+
(item.count !== void 0 || item.countLabel) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4", children: [
|
|
1129
|
+
item.count !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xl font-bold", children: item.count }),
|
|
1130
|
+
item.countLabel && (typeof item.countLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium uppercase tracking-wider text-muted-foreground", children: item.countLabel }) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: item.countLabel }))
|
|
1131
|
+
] }),
|
|
1132
|
+
item.actions && item.actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: item.actions.map((action, actionIndex) => {
|
|
1133
|
+
const {
|
|
1134
|
+
label,
|
|
1135
|
+
icon,
|
|
1136
|
+
iconAfter,
|
|
1137
|
+
children,
|
|
1138
|
+
className: actionClassName,
|
|
1139
|
+
asButton,
|
|
1140
|
+
...pressableProps
|
|
1141
|
+
} = action;
|
|
1142
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1143
|
+
Pressable,
|
|
1144
|
+
{
|
|
1145
|
+
asButton,
|
|
1146
|
+
className: actionClassName,
|
|
1147
|
+
...pressableProps,
|
|
1148
|
+
children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1149
|
+
icon,
|
|
1150
|
+
label,
|
|
1151
|
+
iconAfter
|
|
1152
|
+
] })
|
|
1153
|
+
},
|
|
1154
|
+
actionIndex
|
|
1155
|
+
);
|
|
1156
|
+
}) })
|
|
1157
|
+
] })
|
|
1158
|
+
] })
|
|
1159
|
+
}
|
|
1160
|
+
)
|
|
1161
|
+
},
|
|
1162
|
+
item.id
|
|
1163
|
+
)),
|
|
1164
|
+
itemsSlot
|
|
1165
|
+
]
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1070
1168
|
}
|
|
1071
1169
|
),
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
{
|
|
1075
|
-
onClick: () => scroll("left"),
|
|
1076
|
-
className: cn(
|
|
1077
|
-
"absolute left-4 top-1/2 z-10 -translate-y-1/2",
|
|
1078
|
-
"flex h-12 w-12 items-center justify-center",
|
|
1079
|
-
"rounded-full border border-border/50 bg-background shadow-lg",
|
|
1080
|
-
"text-foreground transition-all duration-200",
|
|
1081
|
-
"hover:bg-accent hover:shadow-xl hover:scale-105",
|
|
1082
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1083
|
-
navigationClassName
|
|
1084
|
-
),
|
|
1085
|
-
"aria-label": "Scroll left",
|
|
1086
|
-
asButton: true,
|
|
1087
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-left", size: 24 })
|
|
1088
|
-
}
|
|
1089
|
-
),
|
|
1090
|
-
!isAtEnd && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1091
|
-
Pressable,
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1171
|
+
CarouselPagination,
|
|
1092
1172
|
{
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
"text-foreground transition-all duration-200",
|
|
1099
|
-
"hover:bg-accent hover:shadow-xl hover:scale-105",
|
|
1100
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1101
|
-
navigationClassName
|
|
1102
|
-
),
|
|
1103
|
-
"aria-label": "Scroll right",
|
|
1104
|
-
asButton: true,
|
|
1105
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/chevron-right", size: 24 })
|
|
1173
|
+
onPrevious: scrollLeft,
|
|
1174
|
+
onNext: scrollRight,
|
|
1175
|
+
canScrollPrevious: !isAtStart,
|
|
1176
|
+
canScrollNext: !isAtEnd,
|
|
1177
|
+
className: cn("mr-0 md:mr-10", navigationClassName)
|
|
1106
1178
|
}
|
|
1107
1179
|
)
|
|
1108
1180
|
] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { P as PatternName } from './pattern-background-a7gKHzHy.cjs';
|
|
3
3
|
import { f as SectionBackground, g as SectionSpacing } from './community-initiatives-CES_LEJI.cjs';
|
|
4
|
-
import { O as OptixFlowConfig } from './blocks-tmd_MRJv.cjs';
|
|
4
|
+
import { A as ActionConfig, O as OptixFlowConfig } from './blocks-tmd_MRJv.cjs';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
import 'class-variance-authority';
|
|
7
7
|
import './button-variants-8mtEHxev.cjs';
|
|
@@ -42,6 +42,10 @@ interface CardItem {
|
|
|
42
42
|
* Label for the count
|
|
43
43
|
*/
|
|
44
44
|
countLabel?: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Array of action configurations for buttons/links on the card
|
|
47
|
+
*/
|
|
48
|
+
actions?: ActionConfig[];
|
|
45
49
|
/**
|
|
46
50
|
* Additional CSS classes for the card
|
|
47
51
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { P as PatternName } from './pattern-background-a7gKHzHy.js';
|
|
3
3
|
import { f as SectionBackground, g as SectionSpacing } from './community-initiatives-BRz60ABw.js';
|
|
4
|
-
import { O as OptixFlowConfig } from './blocks-DRE-f6cS.js';
|
|
4
|
+
import { A as ActionConfig, O as OptixFlowConfig } from './blocks-DRE-f6cS.js';
|
|
5
5
|
import 'react/jsx-runtime';
|
|
6
6
|
import 'class-variance-authority';
|
|
7
7
|
import './button-variants-8mtEHxev.js';
|
|
@@ -42,6 +42,10 @@ interface CardItem {
|
|
|
42
42
|
* Label for the count
|
|
43
43
|
*/
|
|
44
44
|
countLabel?: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Array of action configurations for buttons/links on the card
|
|
47
|
+
*/
|
|
48
|
+
actions?: ActionConfig[];
|
|
45
49
|
/**
|
|
46
50
|
* Additional CSS classes for the card
|
|
47
51
|
*/
|