@opensite/ui 2.9.0 → 2.9.2
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 +4 -3
- package/dist/carousel-feature-badge.d.cts +1 -1
- package/dist/carousel-feature-badge.d.ts +1 -1
- package/dist/carousel-feature-badge.js +4 -3
- package/dist/carousel-scrolling-feature-showcase.cjs +47 -38
- package/dist/carousel-scrolling-feature-showcase.js +47 -38
- package/dist/registry.cjs +454 -265
- package/dist/registry.js +454 -265
- package/dist/testimonials-grid-add-review.cjs +578 -39
- package/dist/testimonials-grid-add-review.d.cts +26 -26
- package/dist/testimonials-grid-add-review.d.ts +26 -26
- package/dist/testimonials-grid-add-review.js +577 -38
- package/dist/testimonials-images-helpful.cjs +85 -74
- package/dist/testimonials-images-helpful.js +85 -74
- package/dist/testimonials-list-verified.cjs +1 -0
- package/dist/testimonials-list-verified.js +1 -0
- package/dist/testimonials-logo-cards.cjs +8 -5
- package/dist/testimonials-logo-cards.js +8 -5
- package/dist/testimonials-masonry-grid.cjs +87 -11
- package/dist/testimonials-masonry-grid.d.cts +14 -1
- package/dist/testimonials-masonry-grid.d.ts +14 -1
- package/dist/testimonials-masonry-grid.js +88 -12
- package/dist/testimonials-mini-dividers.cjs +438 -26
- package/dist/testimonials-mini-dividers.js +434 -22
- package/dist/testimonials-minimal-numbered.cjs +1 -1
- package/dist/testimonials-minimal-numbered.js +1 -1
- package/dist/testimonials-parallax-number.cjs +1 -1
- package/dist/testimonials-parallax-number.js +1 -1
- package/dist/testimonials-quote-carousel.cjs +39 -37
- package/dist/testimonials-quote-carousel.d.cts +5 -1
- package/dist/testimonials-quote-carousel.d.ts +5 -1
- package/dist/testimonials-quote-carousel.js +39 -37
- package/dist/testimonials-scrolling-columns.cjs +438 -8
- package/dist/testimonials-scrolling-columns.js +436 -6
- package/dist/testimonials-simple-grid.cjs +82 -6
- package/dist/testimonials-simple-grid.d.cts +14 -1
- package/dist/testimonials-simple-grid.d.ts +14 -1
- package/dist/testimonials-simple-grid.js +83 -7
- package/dist/testimonials-stats-header.cjs +88 -8
- package/dist/testimonials-stats-header.d.cts +14 -1
- package/dist/testimonials-stats-header.d.ts +14 -1
- package/dist/testimonials-stats-header.js +89 -9
- package/dist/testimonials-twitter-cards.cjs +150 -25
- package/dist/testimonials-twitter-cards.d.cts +14 -1
- package/dist/testimonials-twitter-cards.d.ts +14 -1
- package/dist/testimonials-twitter-cards.js +151 -26
- package/dist/testimonials-wall-compact.cjs +529 -50
- package/dist/testimonials-wall-compact.d.cts +14 -1
- package/dist/testimonials-wall-compact.d.ts +14 -1
- package/dist/testimonials-wall-compact.js +526 -44
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import
|
|
2
|
+
import * as React3 from 'react';
|
|
3
|
+
import React3__default, { useCallback, useMemo } from 'react';
|
|
3
4
|
import { clsx } from 'clsx';
|
|
4
5
|
import { twMerge } from 'tailwind-merge';
|
|
5
6
|
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
6
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
import { Slot } from '@radix-ui/react-slot';
|
|
8
9
|
import { cva } from 'class-variance-authority';
|
|
9
10
|
|
|
@@ -11,36 +12,6 @@ import { cva } from 'class-variance-authority';
|
|
|
11
12
|
function cn(...inputs) {
|
|
12
13
|
return twMerge(clsx(inputs));
|
|
13
14
|
}
|
|
14
|
-
function getNestedCardBg(parentBg, variant = "muted", options) {
|
|
15
|
-
const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
|
|
16
|
-
if (isDark) {
|
|
17
|
-
switch (variant) {
|
|
18
|
-
case "muted":
|
|
19
|
-
return "bg-background";
|
|
20
|
-
case "card":
|
|
21
|
-
return "bg-card";
|
|
22
|
-
case "accent":
|
|
23
|
-
return "bg-accent";
|
|
24
|
-
case "subtle":
|
|
25
|
-
return "bg-background/50";
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
switch (variant) {
|
|
29
|
-
case "muted":
|
|
30
|
-
return "bg-muted";
|
|
31
|
-
case "card":
|
|
32
|
-
return "bg-card";
|
|
33
|
-
case "accent":
|
|
34
|
-
return "bg-accent";
|
|
35
|
-
case "subtle":
|
|
36
|
-
return "bg-muted/50";
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
function getNestedCardTextColor(parentBg, options) {
|
|
41
|
-
const isDark = parentBg === "dark" || parentBg === "secondary" || parentBg === "primary";
|
|
42
|
-
return isDark ? "text-foreground" : "";
|
|
43
|
-
}
|
|
44
15
|
function Avatar({
|
|
45
16
|
className,
|
|
46
17
|
...props
|
|
@@ -127,7 +98,7 @@ var maxWidthStyles = {
|
|
|
127
98
|
"4xl": "max-w-[1536px]",
|
|
128
99
|
full: "max-w-full"
|
|
129
100
|
};
|
|
130
|
-
var Container =
|
|
101
|
+
var Container = React3__default.forwardRef(
|
|
131
102
|
({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
|
|
132
103
|
const Component = as;
|
|
133
104
|
return /* @__PURE__ */ jsx(
|
|
@@ -433,7 +404,7 @@ var spacingStyles = {
|
|
|
433
404
|
};
|
|
434
405
|
var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
|
|
435
406
|
var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
|
|
436
|
-
var Section =
|
|
407
|
+
var Section = React3__default.forwardRef(
|
|
437
408
|
({
|
|
438
409
|
id,
|
|
439
410
|
title,
|
|
@@ -494,6 +465,488 @@ var Section = React.forwardRef(
|
|
|
494
465
|
}
|
|
495
466
|
);
|
|
496
467
|
Section.displayName = "Section";
|
|
468
|
+
var baseStyles = [
|
|
469
|
+
// Layout
|
|
470
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
|
|
471
|
+
// Typography - using CSS variables with sensible defaults
|
|
472
|
+
"font-[var(--button-font-family,inherit)]",
|
|
473
|
+
"font-[var(--button-font-weight,500)]",
|
|
474
|
+
"tracking-[var(--button-letter-spacing,0)]",
|
|
475
|
+
"leading-[var(--button-line-height,1.25)]",
|
|
476
|
+
"[text-transform:var(--button-text-transform,none)]",
|
|
477
|
+
"text-sm",
|
|
478
|
+
// Border radius
|
|
479
|
+
"rounded-[var(--button-radius,var(--radius,0.375rem))]",
|
|
480
|
+
// Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
|
|
481
|
+
"[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
|
|
482
|
+
// Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
|
|
483
|
+
"[box-shadow:var(--button-shadow,none)]",
|
|
484
|
+
"hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
|
|
485
|
+
// Disabled state
|
|
486
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
487
|
+
// SVG handling
|
|
488
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
|
|
489
|
+
// Focus styles
|
|
490
|
+
"outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
491
|
+
// Invalid state
|
|
492
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
|
|
493
|
+
].join(" ");
|
|
494
|
+
var buttonVariants = cva(baseStyles, {
|
|
495
|
+
variants: {
|
|
496
|
+
variant: {
|
|
497
|
+
// Default (Primary) variant - full customization
|
|
498
|
+
default: [
|
|
499
|
+
"bg-[var(--button-default-bg,hsl(var(--primary)))]",
|
|
500
|
+
"text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
|
|
501
|
+
"border-[length:var(--button-default-border-width,0px)]",
|
|
502
|
+
"border-[color:var(--button-default-border,transparent)]",
|
|
503
|
+
"[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
|
|
504
|
+
"hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
|
|
505
|
+
"hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
|
|
506
|
+
"hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
|
|
507
|
+
"hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
|
|
508
|
+
].join(" "),
|
|
509
|
+
// Destructive variant - full customization
|
|
510
|
+
destructive: [
|
|
511
|
+
"bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
|
|
512
|
+
"text-[var(--button-destructive-fg,white)]",
|
|
513
|
+
"border-[length:var(--button-destructive-border-width,0px)]",
|
|
514
|
+
"border-[color:var(--button-destructive-border,transparent)]",
|
|
515
|
+
"[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
|
|
516
|
+
"hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
|
|
517
|
+
"hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
|
|
518
|
+
"hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
|
|
519
|
+
"hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
|
|
520
|
+
"focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
|
|
521
|
+
"dark:bg-destructive/60"
|
|
522
|
+
].join(" "),
|
|
523
|
+
// Outline variant - full customization with proper border handling
|
|
524
|
+
outline: [
|
|
525
|
+
"bg-[var(--button-outline-bg,hsl(var(--background)))]",
|
|
526
|
+
"text-[var(--button-outline-fg,inherit)]",
|
|
527
|
+
"border-[length:var(--button-outline-border-width,1px)]",
|
|
528
|
+
"border-[color:var(--button-outline-border,hsl(var(--border)))]",
|
|
529
|
+
"[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
|
|
530
|
+
"hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
|
|
531
|
+
"hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
|
|
532
|
+
"hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
|
|
533
|
+
"hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
|
|
534
|
+
"dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
|
|
535
|
+
].join(" "),
|
|
536
|
+
// Secondary variant - full customization
|
|
537
|
+
secondary: [
|
|
538
|
+
"bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
|
|
539
|
+
"text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
|
|
540
|
+
"border-[length:var(--button-secondary-border-width,0px)]",
|
|
541
|
+
"border-[color:var(--button-secondary-border,transparent)]",
|
|
542
|
+
"[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
|
|
543
|
+
"hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
|
|
544
|
+
"hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
|
|
545
|
+
"hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
|
|
546
|
+
"hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
|
|
547
|
+
].join(" "),
|
|
548
|
+
// Ghost variant - full customization
|
|
549
|
+
ghost: [
|
|
550
|
+
"bg-[var(--button-ghost-bg,transparent)]",
|
|
551
|
+
"text-[var(--button-ghost-fg,inherit)]",
|
|
552
|
+
"border-[length:var(--button-ghost-border-width,0px)]",
|
|
553
|
+
"border-[color:var(--button-ghost-border,transparent)]",
|
|
554
|
+
"[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
|
|
555
|
+
"hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
|
|
556
|
+
"hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
|
|
557
|
+
"hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
|
|
558
|
+
"hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
|
|
559
|
+
"dark:hover:bg-accent/50"
|
|
560
|
+
].join(" "),
|
|
561
|
+
// Link variant - full customization
|
|
562
|
+
link: [
|
|
563
|
+
"bg-[var(--button-link-bg,transparent)]",
|
|
564
|
+
"text-[var(--button-link-fg,hsl(var(--primary)))]",
|
|
565
|
+
"border-[length:var(--button-link-border-width,0px)]",
|
|
566
|
+
"border-[color:var(--button-link-border,transparent)]",
|
|
567
|
+
"[box-shadow:var(--button-link-shadow,none)]",
|
|
568
|
+
"hover:bg-[var(--button-link-hover-bg,transparent)]",
|
|
569
|
+
"hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
|
|
570
|
+
"hover:[box-shadow:var(--button-link-shadow-hover,none)]",
|
|
571
|
+
"underline-offset-4 hover:underline"
|
|
572
|
+
].join(" ")
|
|
573
|
+
},
|
|
574
|
+
size: {
|
|
575
|
+
default: [
|
|
576
|
+
"h-[var(--button-height-md,2.25rem)]",
|
|
577
|
+
"px-[var(--button-padding-x-md,1rem)]",
|
|
578
|
+
"py-[var(--button-padding-y-md,0.5rem)]",
|
|
579
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
|
|
580
|
+
].join(" "),
|
|
581
|
+
sm: [
|
|
582
|
+
"h-[var(--button-height-sm,2rem)]",
|
|
583
|
+
"px-[var(--button-padding-x-sm,0.75rem)]",
|
|
584
|
+
"py-[var(--button-padding-y-sm,0.25rem)]",
|
|
585
|
+
"gap-1.5",
|
|
586
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
|
|
587
|
+
].join(" "),
|
|
588
|
+
md: [
|
|
589
|
+
"h-[var(--button-height-md,2.25rem)]",
|
|
590
|
+
"px-[var(--button-padding-x-md,1rem)]",
|
|
591
|
+
"py-[var(--button-padding-y-md,0.5rem)]",
|
|
592
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
|
|
593
|
+
].join(" "),
|
|
594
|
+
lg: [
|
|
595
|
+
"h-[var(--button-height-lg,2.5rem)]",
|
|
596
|
+
"px-[var(--button-padding-x-lg,1.5rem)]",
|
|
597
|
+
"py-[var(--button-padding-y-lg,0.5rem)]",
|
|
598
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
|
|
599
|
+
].join(" "),
|
|
600
|
+
icon: "size-[var(--button-height-md,2.25rem)]",
|
|
601
|
+
"icon-sm": "size-[var(--button-height-sm,2rem)]",
|
|
602
|
+
"icon-lg": "size-[var(--button-height-lg,2.5rem)]"
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
defaultVariants: {
|
|
606
|
+
variant: "default",
|
|
607
|
+
size: "default"
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
function normalizePhoneNumber(input) {
|
|
611
|
+
const trimmed = input.trim();
|
|
612
|
+
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
613
|
+
return trimmed;
|
|
614
|
+
}
|
|
615
|
+
const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
|
|
616
|
+
if (match) {
|
|
617
|
+
const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
|
|
618
|
+
const extension = match[3];
|
|
619
|
+
const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
|
|
620
|
+
const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
|
|
621
|
+
return `tel:${withExtension}`;
|
|
622
|
+
}
|
|
623
|
+
const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
|
|
624
|
+
return `tel:${cleaned}`;
|
|
625
|
+
}
|
|
626
|
+
function normalizeEmail(input) {
|
|
627
|
+
const trimmed = input.trim();
|
|
628
|
+
if (trimmed.toLowerCase().startsWith("mailto:")) {
|
|
629
|
+
return trimmed;
|
|
630
|
+
}
|
|
631
|
+
return `mailto:${trimmed}`;
|
|
632
|
+
}
|
|
633
|
+
function isEmail(input) {
|
|
634
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
635
|
+
return emailRegex.test(input.trim());
|
|
636
|
+
}
|
|
637
|
+
function isPhoneNumber(input) {
|
|
638
|
+
const trimmed = input.trim();
|
|
639
|
+
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
|
|
643
|
+
return phoneRegex.test(trimmed);
|
|
644
|
+
}
|
|
645
|
+
function isInternalUrl(href) {
|
|
646
|
+
if (typeof window === "undefined") {
|
|
647
|
+
return href.startsWith("/") && !href.startsWith("//");
|
|
648
|
+
}
|
|
649
|
+
const trimmed = href.trim();
|
|
650
|
+
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
|
|
651
|
+
return true;
|
|
652
|
+
}
|
|
653
|
+
try {
|
|
654
|
+
const url = new URL(trimmed, window.location.href);
|
|
655
|
+
const currentOrigin = window.location.origin;
|
|
656
|
+
const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
|
|
657
|
+
return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
|
|
658
|
+
} catch {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function toRelativePath(href) {
|
|
663
|
+
if (typeof window === "undefined") {
|
|
664
|
+
return href;
|
|
665
|
+
}
|
|
666
|
+
const trimmed = href.trim();
|
|
667
|
+
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
|
|
668
|
+
return trimmed;
|
|
669
|
+
}
|
|
670
|
+
try {
|
|
671
|
+
const url = new URL(trimmed, window.location.href);
|
|
672
|
+
const currentOrigin = window.location.origin;
|
|
673
|
+
const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
|
|
674
|
+
if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
|
|
675
|
+
return url.pathname + url.search + url.hash;
|
|
676
|
+
}
|
|
677
|
+
} catch {
|
|
678
|
+
}
|
|
679
|
+
return trimmed;
|
|
680
|
+
}
|
|
681
|
+
function useNavigation({
|
|
682
|
+
href,
|
|
683
|
+
onClick
|
|
684
|
+
} = {}) {
|
|
685
|
+
const linkType = React3.useMemo(() => {
|
|
686
|
+
if (!href || href.trim() === "") {
|
|
687
|
+
return onClick ? "none" : "none";
|
|
688
|
+
}
|
|
689
|
+
const trimmed = href.trim();
|
|
690
|
+
if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
|
|
691
|
+
return "mailto";
|
|
692
|
+
}
|
|
693
|
+
if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
|
|
694
|
+
return "tel";
|
|
695
|
+
}
|
|
696
|
+
if (isInternalUrl(trimmed)) {
|
|
697
|
+
return "internal";
|
|
698
|
+
}
|
|
699
|
+
try {
|
|
700
|
+
new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
|
|
701
|
+
return "external";
|
|
702
|
+
} catch {
|
|
703
|
+
return "internal";
|
|
704
|
+
}
|
|
705
|
+
}, [href, onClick]);
|
|
706
|
+
const normalizedHref = React3.useMemo(() => {
|
|
707
|
+
if (!href || href.trim() === "") {
|
|
708
|
+
return void 0;
|
|
709
|
+
}
|
|
710
|
+
const trimmed = href.trim();
|
|
711
|
+
switch (linkType) {
|
|
712
|
+
case "tel":
|
|
713
|
+
return normalizePhoneNumber(trimmed);
|
|
714
|
+
case "mailto":
|
|
715
|
+
return normalizeEmail(trimmed);
|
|
716
|
+
case "internal":
|
|
717
|
+
return toRelativePath(trimmed);
|
|
718
|
+
case "external":
|
|
719
|
+
return trimmed;
|
|
720
|
+
default:
|
|
721
|
+
return trimmed;
|
|
722
|
+
}
|
|
723
|
+
}, [href, linkType]);
|
|
724
|
+
const target = React3.useMemo(() => {
|
|
725
|
+
switch (linkType) {
|
|
726
|
+
case "external":
|
|
727
|
+
return "_blank";
|
|
728
|
+
case "internal":
|
|
729
|
+
return "_self";
|
|
730
|
+
case "mailto":
|
|
731
|
+
case "tel":
|
|
732
|
+
return void 0;
|
|
733
|
+
default:
|
|
734
|
+
return void 0;
|
|
735
|
+
}
|
|
736
|
+
}, [linkType]);
|
|
737
|
+
const rel = React3.useMemo(() => {
|
|
738
|
+
if (linkType === "external") {
|
|
739
|
+
return "noopener noreferrer";
|
|
740
|
+
}
|
|
741
|
+
return void 0;
|
|
742
|
+
}, [linkType]);
|
|
743
|
+
const isExternal = linkType === "external";
|
|
744
|
+
const isInternal = linkType === "internal";
|
|
745
|
+
const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
|
|
746
|
+
const handleClick = React3.useCallback(
|
|
747
|
+
(event) => {
|
|
748
|
+
if (onClick) {
|
|
749
|
+
try {
|
|
750
|
+
onClick(event);
|
|
751
|
+
} catch (error) {
|
|
752
|
+
console.error("Error in user onClick handler:", error);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
if (event.defaultPrevented) {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
|
|
759
|
+
!event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
|
|
760
|
+
if (typeof window !== "undefined") {
|
|
761
|
+
const handler = window.__opensiteNavigationHandler;
|
|
762
|
+
if (typeof handler === "function") {
|
|
763
|
+
try {
|
|
764
|
+
const handled = handler(normalizedHref, event.nativeEvent || event);
|
|
765
|
+
if (handled !== false) {
|
|
766
|
+
event.preventDefault();
|
|
767
|
+
}
|
|
768
|
+
} catch (error) {
|
|
769
|
+
console.error("Error in navigation handler:", error);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
},
|
|
775
|
+
[onClick, shouldUseRouter, normalizedHref]
|
|
776
|
+
);
|
|
777
|
+
return {
|
|
778
|
+
linkType,
|
|
779
|
+
normalizedHref,
|
|
780
|
+
target,
|
|
781
|
+
rel,
|
|
782
|
+
isExternal,
|
|
783
|
+
isInternal,
|
|
784
|
+
shouldUseRouter,
|
|
785
|
+
handleClick
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
var Pressable = React3.forwardRef(
|
|
789
|
+
({
|
|
790
|
+
children,
|
|
791
|
+
className,
|
|
792
|
+
href,
|
|
793
|
+
onClick,
|
|
794
|
+
variant,
|
|
795
|
+
size,
|
|
796
|
+
asButton = false,
|
|
797
|
+
fallbackComponentType = "span",
|
|
798
|
+
componentType,
|
|
799
|
+
"aria-label": ariaLabel,
|
|
800
|
+
"aria-describedby": ariaDescribedby,
|
|
801
|
+
id,
|
|
802
|
+
...props
|
|
803
|
+
}, ref) => {
|
|
804
|
+
const navigation = useNavigation({ href, onClick });
|
|
805
|
+
const {
|
|
806
|
+
normalizedHref,
|
|
807
|
+
target,
|
|
808
|
+
rel,
|
|
809
|
+
linkType,
|
|
810
|
+
isInternal,
|
|
811
|
+
handleClick
|
|
812
|
+
} = navigation;
|
|
813
|
+
const shouldRenderLink = normalizedHref && linkType !== "none";
|
|
814
|
+
const shouldRenderButton = !shouldRenderLink && onClick;
|
|
815
|
+
const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
|
|
816
|
+
const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
|
|
817
|
+
const shouldApplyButtonStyles = asButton || variant || size;
|
|
818
|
+
const combinedClassName = cn(
|
|
819
|
+
shouldApplyButtonStyles && buttonVariants({ variant, size }),
|
|
820
|
+
className
|
|
821
|
+
);
|
|
822
|
+
const dataProps = Object.fromEntries(
|
|
823
|
+
Object.entries(props).filter(([key]) => key.startsWith("data-"))
|
|
824
|
+
);
|
|
825
|
+
const buttonDataAttributes = shouldApplyButtonStyles ? {
|
|
826
|
+
"data-slot": "button",
|
|
827
|
+
"data-variant": variant ?? "default",
|
|
828
|
+
"data-size": size ?? "default"
|
|
829
|
+
} : {};
|
|
830
|
+
const commonProps = {
|
|
831
|
+
className: combinedClassName,
|
|
832
|
+
onClick: handleClick,
|
|
833
|
+
"aria-label": ariaLabel,
|
|
834
|
+
"aria-describedby": ariaDescribedby,
|
|
835
|
+
id,
|
|
836
|
+
...dataProps,
|
|
837
|
+
...buttonDataAttributes
|
|
838
|
+
};
|
|
839
|
+
if (finalComponentType === "a" && shouldRenderLink) {
|
|
840
|
+
return /* @__PURE__ */ jsx(
|
|
841
|
+
"a",
|
|
842
|
+
{
|
|
843
|
+
ref,
|
|
844
|
+
href: normalizedHref,
|
|
845
|
+
target,
|
|
846
|
+
rel,
|
|
847
|
+
...commonProps,
|
|
848
|
+
...props,
|
|
849
|
+
children
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
if (finalComponentType === "button") {
|
|
854
|
+
return /* @__PURE__ */ jsx(
|
|
855
|
+
"button",
|
|
856
|
+
{
|
|
857
|
+
ref,
|
|
858
|
+
type: props.type || "button",
|
|
859
|
+
...commonProps,
|
|
860
|
+
...props,
|
|
861
|
+
children
|
|
862
|
+
}
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
if (finalComponentType === "div") {
|
|
866
|
+
return /* @__PURE__ */ jsx(
|
|
867
|
+
"div",
|
|
868
|
+
{
|
|
869
|
+
ref,
|
|
870
|
+
...commonProps,
|
|
871
|
+
children
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
return /* @__PURE__ */ jsx(
|
|
876
|
+
"span",
|
|
877
|
+
{
|
|
878
|
+
ref,
|
|
879
|
+
...commonProps,
|
|
880
|
+
children
|
|
881
|
+
}
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
);
|
|
885
|
+
Pressable.displayName = "Pressable";
|
|
886
|
+
var MOBILE_CLASSES = {
|
|
887
|
+
"fit-left": "items-start md:items-center",
|
|
888
|
+
"fit-center": "items-center",
|
|
889
|
+
"fit-right": "items-end md:items-center",
|
|
890
|
+
"full-left": "items-stretch md:items-center",
|
|
891
|
+
"full-center": "items-stretch md:items-center",
|
|
892
|
+
"full-right": "items-stretch md:items-center"
|
|
893
|
+
};
|
|
894
|
+
function BlockActions({
|
|
895
|
+
mobileConfig,
|
|
896
|
+
actionsClassName,
|
|
897
|
+
verticalSpacing = "mt-4 md:mt-8",
|
|
898
|
+
actions,
|
|
899
|
+
actionsSlot
|
|
900
|
+
}) {
|
|
901
|
+
const width = mobileConfig?.width ?? "full";
|
|
902
|
+
const position = mobileConfig?.position ?? "center";
|
|
903
|
+
const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
|
|
904
|
+
if (actionsSlot) {
|
|
905
|
+
return /* @__PURE__ */ jsx("div", { children: actionsSlot });
|
|
906
|
+
} else if (actions && actions?.length > 0) {
|
|
907
|
+
return /* @__PURE__ */ jsx(
|
|
908
|
+
"div",
|
|
909
|
+
{
|
|
910
|
+
className: cn(
|
|
911
|
+
"flex flex-col md:flex-row flex-wrap gap-4",
|
|
912
|
+
mobileLayoutClass,
|
|
913
|
+
actionsClassName,
|
|
914
|
+
verticalSpacing
|
|
915
|
+
),
|
|
916
|
+
children: actions.map((action, index) => /* @__PURE__ */ jsx(ActionComponent, { action }, index))
|
|
917
|
+
}
|
|
918
|
+
);
|
|
919
|
+
} else {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
function ActionComponent({ action }) {
|
|
924
|
+
const {
|
|
925
|
+
label,
|
|
926
|
+
icon,
|
|
927
|
+
iconAfter,
|
|
928
|
+
children,
|
|
929
|
+
href,
|
|
930
|
+
onClick,
|
|
931
|
+
className: actionClassName,
|
|
932
|
+
...pressableProps
|
|
933
|
+
} = action;
|
|
934
|
+
return /* @__PURE__ */ jsx(
|
|
935
|
+
Pressable,
|
|
936
|
+
{
|
|
937
|
+
href,
|
|
938
|
+
onClick,
|
|
939
|
+
asButton: action.asButton ?? true,
|
|
940
|
+
className: actionClassName,
|
|
941
|
+
...pressableProps,
|
|
942
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
943
|
+
icon,
|
|
944
|
+
label,
|
|
945
|
+
iconAfter
|
|
946
|
+
] })
|
|
947
|
+
}
|
|
948
|
+
);
|
|
949
|
+
}
|
|
497
950
|
function TestimonialsWallCompact({
|
|
498
951
|
testimonials,
|
|
499
952
|
testimonialsSlot,
|
|
@@ -509,9 +962,12 @@ function TestimonialsWallCompact({
|
|
|
509
962
|
quoteClassName,
|
|
510
963
|
background,
|
|
511
964
|
containerClassName = "px-6 sm:px-6 md:px-8 lg:px-8",
|
|
512
|
-
spacing = "
|
|
965
|
+
spacing = "lg",
|
|
513
966
|
pattern,
|
|
514
|
-
patternOpacity
|
|
967
|
+
patternOpacity,
|
|
968
|
+
actions,
|
|
969
|
+
actionsSlot,
|
|
970
|
+
actionsClassName
|
|
515
971
|
}) {
|
|
516
972
|
const getAuthorName = useCallback(
|
|
517
973
|
(testimonial) => {
|
|
@@ -546,9 +1002,8 @@ function TestimonialsWallCompact({
|
|
|
546
1002
|
"div",
|
|
547
1003
|
{
|
|
548
1004
|
className: cn(
|
|
1005
|
+
"bg-card text-card-foreground",
|
|
549
1006
|
"rounded-lg border p-4 transition-shadow hover:shadow-md",
|
|
550
|
-
getNestedCardBg(background, "card"),
|
|
551
|
-
getNestedCardTextColor(background),
|
|
552
1007
|
cardClassName
|
|
553
1008
|
),
|
|
554
1009
|
children: [
|
|
@@ -567,14 +1022,23 @@ function TestimonialsWallCompact({
|
|
|
567
1022
|
] }),
|
|
568
1023
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
569
1024
|
testimonial.author && (typeof testimonial.author === "string" ? /* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium", children: testimonial.author }) : testimonial.author),
|
|
570
|
-
testimonial.handle && /* @__PURE__ */ jsx("p", { className: "truncate text-xs ", children: testimonial.handle })
|
|
1025
|
+
testimonial.handle && /* @__PURE__ */ jsx("p", { className: "truncate text-xs font-semibold opacity-75", children: testimonial.handle })
|
|
571
1026
|
] })
|
|
572
1027
|
] }),
|
|
573
1028
|
testimonial.badge && (typeof testimonial.badge === "string" ? /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "shrink-0 text-xs", children: testimonial.badge }) : testimonial.badge)
|
|
574
1029
|
]
|
|
575
1030
|
}
|
|
576
1031
|
),
|
|
577
|
-
testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsx(
|
|
1032
|
+
testimonial.quote && (typeof testimonial.quote === "string" ? /* @__PURE__ */ jsx(
|
|
1033
|
+
"p",
|
|
1034
|
+
{
|
|
1035
|
+
className: cn(
|
|
1036
|
+
"text-sm leading-relaxed pt-2",
|
|
1037
|
+
quoteClassName
|
|
1038
|
+
),
|
|
1039
|
+
children: testimonial.quote
|
|
1040
|
+
}
|
|
1041
|
+
) : testimonial.quote)
|
|
578
1042
|
]
|
|
579
1043
|
},
|
|
580
1044
|
index
|
|
@@ -606,23 +1070,41 @@ function TestimonialsWallCompact({
|
|
|
606
1070
|
/* @__PURE__ */ jsxs(
|
|
607
1071
|
"div",
|
|
608
1072
|
{
|
|
609
|
-
className: cn(
|
|
1073
|
+
className: cn(
|
|
1074
|
+
"mx-auto mb-12 max-w-full md:max-w-md text-center",
|
|
1075
|
+
headerClassName
|
|
1076
|
+
),
|
|
610
1077
|
children: [
|
|
611
1078
|
heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
|
|
612
1079
|
"h2",
|
|
613
1080
|
{
|
|
614
1081
|
className: cn(
|
|
615
|
-
"text-3xl font-semibold tracking-tight md:text-4xl",
|
|
1082
|
+
"text-3xl font-semibold tracking-tight md:text-4xl text-pretty",
|
|
616
1083
|
headingClassName
|
|
617
1084
|
),
|
|
618
1085
|
children: heading
|
|
619
1086
|
}
|
|
620
1087
|
) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
|
|
621
|
-
description && (typeof description === "string" ? /* @__PURE__ */ jsx(
|
|
1088
|
+
description && (typeof description === "string" ? /* @__PURE__ */ jsx(
|
|
1089
|
+
"p",
|
|
1090
|
+
{
|
|
1091
|
+
className: cn("mt-4 text-lg text-balance", descriptionClassName),
|
|
1092
|
+
children: description
|
|
1093
|
+
}
|
|
1094
|
+
) : description)
|
|
622
1095
|
]
|
|
623
1096
|
}
|
|
624
1097
|
),
|
|
625
|
-
renderedTestimonials
|
|
1098
|
+
renderedTestimonials,
|
|
1099
|
+
/* @__PURE__ */ jsx(
|
|
1100
|
+
BlockActions,
|
|
1101
|
+
{
|
|
1102
|
+
actions,
|
|
1103
|
+
actionsSlot,
|
|
1104
|
+
actionsClassName: cn("mt-8 md:mt-12 justify-center", actionsClassName),
|
|
1105
|
+
mobileConfig: { width: "full", position: "center" }
|
|
1106
|
+
}
|
|
1107
|
+
)
|
|
626
1108
|
]
|
|
627
1109
|
}
|
|
628
1110
|
);
|