@opensite/ui 2.8.7 → 2.8.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/about-culture-tabs.cjs +174 -174
  2. package/dist/about-culture-tabs.js +174 -174
  3. package/dist/about-developer-profile.cjs +200 -200
  4. package/dist/about-developer-profile.js +198 -198
  5. package/dist/about-developer-story.cjs +142 -142
  6. package/dist/about-developer-story.js +142 -142
  7. package/dist/about-mission-dual-image.cjs +142 -142
  8. package/dist/about-mission-dual-image.js +142 -142
  9. package/dist/about-mission-features.cjs +142 -142
  10. package/dist/about-mission-features.js +142 -142
  11. package/dist/about-network-spotlight.cjs +142 -142
  12. package/dist/about-network-spotlight.js +142 -142
  13. package/dist/about-story-expertise.cjs +142 -142
  14. package/dist/about-story-expertise.js +142 -142
  15. package/dist/about-streamline-team.cjs +142 -142
  16. package/dist/about-streamline-team.js +142 -142
  17. package/dist/carousel-icon-sidebar.cjs +5 -4
  18. package/dist/carousel-icon-sidebar.js +5 -4
  19. package/dist/community-initiatives.cjs +142 -142
  20. package/dist/community-initiatives.js +142 -142
  21. package/dist/components.cjs +723 -1364
  22. package/dist/components.d.cts +0 -2
  23. package/dist/components.d.ts +0 -2
  24. package/dist/components.js +633 -1273
  25. package/dist/contact-map.cjs +14 -1069
  26. package/dist/contact-map.d.cts +13 -3
  27. package/dist/contact-map.d.ts +13 -3
  28. package/dist/contact-map.js +14 -1069
  29. package/dist/cta-feature-checklist.cjs +142 -142
  30. package/dist/cta-feature-checklist.js +142 -142
  31. package/dist/faq-numbered-grid.cjs +142 -142
  32. package/dist/faq-numbered-grid.js +142 -142
  33. package/dist/feature-animated-carousel.cjs +142 -142
  34. package/dist/feature-animated-carousel.js +142 -142
  35. package/dist/feature-bento-utilities.cjs +142 -142
  36. package/dist/feature-bento-utilities.js +142 -142
  37. package/dist/feature-capabilities-grid.cjs +142 -142
  38. package/dist/feature-capabilities-grid.js +142 -142
  39. package/dist/feature-category-image-cards.cjs +142 -142
  40. package/dist/feature-category-image-cards.js +142 -142
  41. package/dist/feature-icon-grid-bordered.cjs +142 -142
  42. package/dist/feature-icon-grid-bordered.js +142 -142
  43. package/dist/feature-icon-grid-muted.cjs +142 -142
  44. package/dist/feature-icon-grid-muted.js +142 -142
  45. package/dist/feature-numbered-cards.cjs +142 -142
  46. package/dist/feature-numbered-cards.js +142 -142
  47. package/dist/feature-three-column-values.cjs +142 -142
  48. package/dist/feature-three-column-values.js +142 -142
  49. package/dist/hero-ad-campaign-expert.cjs +142 -142
  50. package/dist/hero-ad-campaign-expert.js +142 -142
  51. package/dist/hero-adaptable-product-grid.cjs +142 -142
  52. package/dist/hero-adaptable-product-grid.js +142 -142
  53. package/dist/hero-agency-animated-images.cjs +142 -142
  54. package/dist/hero-agency-animated-images.js +142 -142
  55. package/dist/hero-announcement-badge.cjs +142 -142
  56. package/dist/hero-announcement-badge.js +142 -142
  57. package/dist/hero-badge-image-split.cjs +142 -142
  58. package/dist/hero-badge-image-split.js +142 -142
  59. package/dist/hero-business-carousel-dots.cjs +142 -142
  60. package/dist/hero-business-carousel-dots.js +142 -142
  61. package/dist/hero-business-operations-mosaic.cjs +142 -142
  62. package/dist/hero-business-operations-mosaic.js +142 -142
  63. package/dist/hero-conversation-intelligence.cjs +142 -142
  64. package/dist/hero-conversation-intelligence.js +142 -142
  65. package/dist/hero-creative-studio-stacked.cjs +142 -142
  66. package/dist/hero-creative-studio-stacked.js +142 -142
  67. package/dist/hero-crm-streamlined.cjs +142 -142
  68. package/dist/hero-crm-streamlined.js +142 -142
  69. package/dist/hero-customer-support-layered.cjs +142 -142
  70. package/dist/hero-customer-support-layered.js +142 -142
  71. package/dist/hero-design-showcase-logos.cjs +142 -142
  72. package/dist/hero-design-showcase-logos.js +142 -142
  73. package/dist/hero-design-system-3d.cjs +142 -142
  74. package/dist/hero-design-system-3d.js +142 -142
  75. package/dist/hero-developer-tools-code.cjs +142 -142
  76. package/dist/hero-developer-tools-code.js +142 -142
  77. package/dist/hero-digital-agency-fullscreen.cjs +142 -142
  78. package/dist/hero-digital-agency-fullscreen.js +142 -142
  79. package/dist/hero-ecommerce-product-showcase.cjs +174 -174
  80. package/dist/hero-ecommerce-product-showcase.js +174 -174
  81. package/dist/hero-event-registration.cjs +142 -142
  82. package/dist/hero-event-registration.js +142 -142
  83. package/dist/hero-fullscreen-background-image.cjs +142 -142
  84. package/dist/hero-fullscreen-background-image.js +142 -142
  85. package/dist/hero-gradient-avatars-rating.cjs +142 -142
  86. package/dist/hero-gradient-avatars-rating.js +142 -142
  87. package/dist/hero-gradient-client-focused.cjs +142 -142
  88. package/dist/hero-gradient-client-focused.js +142 -142
  89. package/dist/hero-hiring-animated-text.cjs +142 -142
  90. package/dist/hero-hiring-animated-text.js +142 -142
  91. package/dist/hero-image-left-content.cjs +142 -142
  92. package/dist/hero-image-left-content.js +142 -142
  93. package/dist/hero-innovation-image-grid.cjs +142 -142
  94. package/dist/hero-innovation-image-grid.js +142 -142
  95. package/dist/hero-mental-health-team.cjs +142 -142
  96. package/dist/hero-mental-health-team.js +142 -142
  97. package/dist/hero-minimal-centered-dark.cjs +174 -174
  98. package/dist/hero-minimal-centered-dark.js +174 -174
  99. package/dist/hero-presentation-platform-video.cjs +142 -142
  100. package/dist/hero-presentation-platform-video.js +142 -142
  101. package/dist/hero-product-showcase-floating.cjs +174 -174
  102. package/dist/hero-product-showcase-floating.js +174 -174
  103. package/dist/hero-shared-inbox-layered.cjs +142 -142
  104. package/dist/hero-shared-inbox-layered.js +142 -142
  105. package/dist/hero-software-growth-video-dialog.cjs +142 -142
  106. package/dist/hero-software-growth-video-dialog.js +142 -142
  107. package/dist/hero-spiral-pattern-cards.cjs +174 -174
  108. package/dist/hero-spiral-pattern-cards.js +174 -174
  109. package/dist/hero-split-geometric-shapes.cjs +142 -142
  110. package/dist/hero-split-geometric-shapes.js +142 -142
  111. package/dist/hero-startup-launch-cta.cjs +174 -174
  112. package/dist/hero-startup-launch-cta.js +174 -174
  113. package/dist/hero-stats-social-proof.cjs +174 -174
  114. package/dist/hero-stats-social-proof.js +174 -174
  115. package/dist/hero-task-timer-animated.cjs +142 -142
  116. package/dist/hero-task-timer-animated.js +142 -142
  117. package/dist/hero-testimonial-image-grid.cjs +142 -142
  118. package/dist/hero-testimonial-image-grid.js +142 -142
  119. package/dist/hero-therapy-testimonial-grid.cjs +142 -142
  120. package/dist/hero-therapy-testimonial-grid.js +142 -142
  121. package/dist/hero-ui-library-showcase.cjs +142 -142
  122. package/dist/hero-ui-library-showcase.js +142 -142
  123. package/dist/hero-video-background-dark.cjs +174 -174
  124. package/dist/hero-video-background-dark.js +174 -174
  125. package/dist/hero-video-dialog-gradient.cjs +142 -142
  126. package/dist/hero-video-dialog-gradient.js +142 -142
  127. package/dist/hero-video-overlay-stars.cjs +142 -142
  128. package/dist/hero-video-overlay-stars.js +142 -142
  129. package/dist/hero-welcome-asymmetric-images.cjs +142 -142
  130. package/dist/hero-welcome-asymmetric-images.js +142 -142
  131. package/dist/index.cjs +725 -1366
  132. package/dist/index.d.cts +0 -2
  133. package/dist/index.d.ts +0 -2
  134. package/dist/index.js +634 -1274
  135. package/dist/registry.cjs +2371 -2915
  136. package/dist/registry.js +1120 -1664
  137. package/dist/testimonials-large-quote.cjs +74 -43
  138. package/dist/testimonials-large-quote.d.cts +5 -1
  139. package/dist/testimonials-large-quote.d.ts +5 -1
  140. package/dist/testimonials-large-quote.js +74 -43
  141. package/dist/testimonials-logo-cards.cjs +8 -2
  142. package/dist/testimonials-logo-cards.js +8 -2
  143. package/dist/testimonials-masonry-grid.cjs +486 -69
  144. package/dist/testimonials-masonry-grid.d.cts +5 -1
  145. package/dist/testimonials-masonry-grid.d.ts +5 -1
  146. package/dist/testimonials-masonry-grid.js +483 -63
  147. package/dist/testimonials-mini-dividers.cjs +2 -3
  148. package/dist/testimonials-mini-dividers.js +2 -3
  149. package/dist/testimonials-minimal-numbered.cjs +5 -4
  150. package/dist/testimonials-minimal-numbered.js +5 -4
  151. package/dist/testimonials-parallax-number.cjs +5 -4
  152. package/dist/testimonials-parallax-number.js +5 -4
  153. package/dist/testimonials-scrolling-columns.cjs +7 -12
  154. package/dist/testimonials-scrolling-columns.js +7 -12
  155. package/dist/testimonials-stats-header.cjs +528 -87
  156. package/dist/testimonials-stats-header.d.cts +39 -3
  157. package/dist/testimonials-stats-header.d.ts +39 -3
  158. package/dist/testimonials-stats-header.js +523 -82
  159. package/package.json +4 -7
  160. package/dist/geo-map.cjs +0 -1103
  161. package/dist/geo-map.d.cts +0 -92
  162. package/dist/geo-map.d.ts +0 -92
  163. package/dist/geo-map.js +0 -1081
package/dist/index.js CHANGED
@@ -1,18 +1,17 @@
1
1
  "use client";
2
- import * as React6 from 'react';
3
- import React6__default, { useId, useRef, useEffect, useMemo, useCallback, useState } from 'react';
2
+ import * as React4 from 'react';
3
+ import React4__default, { useId, useRef, useEffect, useMemo, useCallback, useState } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
- import { MapLibre } from '@page-speed/maps';
8
- import { cva } from 'class-variance-authority';
9
- import { Icon } from '@page-speed/icon';
10
- import { Img } from '@page-speed/img';
11
7
  import { AnimatePresence, motion } from 'framer-motion';
12
8
  import { useOnClickOutside } from '@opensite/hooks/useOnClickOutside';
13
9
  import { AnimatePresence as AnimatePresence$1, motion as motion$1 } from 'motion/react';
10
+ import { Img } from '@page-speed/img';
14
11
  import { Slot } from '@radix-ui/react-slot';
12
+ import { cva } from 'class-variance-authority';
15
13
  import * as PopoverPrimitive from '@radix-ui/react-popover';
14
+ import { Icon } from '@page-speed/icon';
16
15
  import { usePlatformFromUrl } from '@opensite/hooks/usePlatformFromUrl';
17
16
  import * as TabsPrimitive from '@radix-ui/react-tabs';
18
17
  import { FormEngine } from '@page-speed/forms/integration';
@@ -121,7 +120,7 @@ var maxWidthStyles = {
121
120
  "4xl": "max-w-[1536px]",
122
121
  full: "max-w-full"
123
122
  };
124
- var Container = React6__default.forwardRef(
123
+ var Container = React4__default.forwardRef(
125
124
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
126
125
  const Component = as;
127
126
  return /* @__PURE__ */ jsx(
@@ -427,7 +426,7 @@ var spacingStyles = {
427
426
  };
428
427
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
429
428
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
430
- var Section = React6__default.forwardRef(
429
+ var Section = React4__default.forwardRef(
431
430
  ({
432
431
  id,
433
432
  title,
@@ -488,1131 +487,65 @@ var Section = React6__default.forwardRef(
488
487
  }
489
488
  );
490
489
  Section.displayName = "Section";
491
- function normalizePhoneNumber(input) {
492
- const trimmed = input.trim();
493
- if (trimmed.toLowerCase().startsWith("tel:")) {
494
- return trimmed;
495
- }
496
- const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
497
- if (match) {
498
- const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
499
- const extension = match[3];
500
- const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
501
- const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
502
- return `tel:${withExtension}`;
503
- }
504
- const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
505
- return `tel:${cleaned}`;
506
- }
507
- function normalizeEmail(input) {
508
- const trimmed = input.trim();
509
- if (trimmed.toLowerCase().startsWith("mailto:")) {
510
- return trimmed;
511
- }
512
- return `mailto:${trimmed}`;
513
- }
514
- function isEmail(input) {
515
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
516
- return emailRegex.test(input.trim());
517
- }
518
- function isPhoneNumber(input) {
519
- const trimmed = input.trim();
520
- if (trimmed.toLowerCase().startsWith("tel:")) {
521
- return true;
522
- }
523
- const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
524
- return phoneRegex.test(trimmed);
525
- }
526
- function isInternalUrl(href) {
527
- if (typeof window === "undefined") {
528
- return href.startsWith("/") && !href.startsWith("//");
529
- }
530
- const trimmed = href.trim();
531
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
532
- return true;
533
- }
534
- try {
535
- const url = new URL(trimmed, window.location.href);
536
- const currentOrigin = window.location.origin;
537
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
538
- return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
539
- } catch {
540
- return false;
541
- }
542
- }
543
- function toRelativePath(href) {
544
- if (typeof window === "undefined") {
545
- return href;
546
- }
547
- const trimmed = href.trim();
548
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
549
- return trimmed;
550
- }
551
- try {
552
- const url = new URL(trimmed, window.location.href);
553
- const currentOrigin = window.location.origin;
554
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
555
- if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
556
- return url.pathname + url.search + url.hash;
557
- }
558
- } catch {
559
- }
560
- return trimmed;
561
- }
562
- function useNavigation({
563
- href,
564
- onClick
565
- } = {}) {
566
- const linkType = React6.useMemo(() => {
567
- if (!href || href.trim() === "") {
568
- return onClick ? "none" : "none";
569
- }
570
- const trimmed = href.trim();
571
- if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
572
- return "mailto";
573
- }
574
- if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
575
- return "tel";
576
- }
577
- if (isInternalUrl(trimmed)) {
578
- return "internal";
579
- }
580
- try {
581
- new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
582
- return "external";
583
- } catch {
584
- return "internal";
585
- }
586
- }, [href, onClick]);
587
- const normalizedHref = React6.useMemo(() => {
588
- if (!href || href.trim() === "") {
589
- return void 0;
590
- }
591
- const trimmed = href.trim();
592
- switch (linkType) {
593
- case "tel":
594
- return normalizePhoneNumber(trimmed);
595
- case "mailto":
596
- return normalizeEmail(trimmed);
597
- case "internal":
598
- return toRelativePath(trimmed);
599
- case "external":
600
- return trimmed;
601
- default:
602
- return trimmed;
603
- }
604
- }, [href, linkType]);
605
- const target = React6.useMemo(() => {
606
- switch (linkType) {
607
- case "external":
608
- return "_blank";
609
- case "internal":
610
- return "_self";
611
- case "mailto":
612
- case "tel":
613
- return void 0;
614
- default:
615
- return void 0;
490
+ var sizeStyles = {
491
+ sm: "max-w-md",
492
+ md: "max-w-2xl",
493
+ lg: "max-w-4xl",
494
+ xl: "max-w-5xl",
495
+ full: "max-w-7xl",
496
+ compact: "max-w-[700px]"
497
+ };
498
+ var dialogTransition = {
499
+ duration: 0.35,
500
+ ease: [0.16, 1, 0.3, 1]
501
+ };
502
+ function AnimatedDialog({
503
+ open,
504
+ onOpenChange,
505
+ title,
506
+ eyebrow,
507
+ description,
508
+ children,
509
+ header,
510
+ footer,
511
+ size = "lg",
512
+ className,
513
+ contentClassName,
514
+ featuredMediaHeader
515
+ }) {
516
+ const titleId = useId();
517
+ const descriptionId = useId();
518
+ const containerRef = useRef(null);
519
+ useOnClickOutside(containerRef, () => {
520
+ if (open) {
521
+ onOpenChange(false);
616
522
  }
617
- }, [linkType]);
618
- const rel = React6.useMemo(() => {
619
- if (linkType === "external") {
620
- return "noopener noreferrer";
523
+ });
524
+ useEffect(() => {
525
+ if (!open) {
526
+ return;
621
527
  }
622
- return void 0;
623
- }, [linkType]);
624
- const isExternal = linkType === "external";
625
- const isInternal = linkType === "internal";
626
- const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
627
- const handleClick = React6.useCallback(
628
- (event) => {
629
- if (onClick) {
630
- try {
631
- onClick(event);
632
- } catch (error) {
633
- console.error("Error in user onClick handler:", error);
634
- }
635
- }
636
- if (event.defaultPrevented) {
637
- return;
528
+ const onKeyDown = (event) => {
529
+ if (event.key === "Escape") {
530
+ onOpenChange(false);
638
531
  }
639
- if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
640
- !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
641
- if (typeof window !== "undefined") {
642
- const handler = window.__opensiteNavigationHandler;
643
- if (typeof handler === "function") {
644
- try {
645
- const handled = handler(normalizedHref, event.nativeEvent || event);
646
- if (handled !== false) {
647
- event.preventDefault();
648
- }
649
- } catch (error) {
650
- console.error("Error in navigation handler:", error);
651
- }
652
- }
653
- }
654
- }
655
- },
656
- [onClick, shouldUseRouter, normalizedHref]
657
- );
658
- return {
659
- linkType,
660
- normalizedHref,
661
- target,
662
- rel,
663
- isExternal,
664
- isInternal,
665
- shouldUseRouter,
666
- handleClick
667
- };
668
- }
669
- var baseStyles = [
670
- // Layout
671
- "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
672
- // Typography - using CSS variables with sensible defaults
673
- "font-[var(--button-font-family,inherit)]",
674
- "font-[var(--button-font-weight,500)]",
675
- "tracking-[var(--button-letter-spacing,0)]",
676
- "leading-[var(--button-line-height,1.25)]",
677
- "[text-transform:var(--button-text-transform,none)]",
678
- "text-sm",
679
- // Border radius
680
- "rounded-[var(--button-radius,var(--radius,0.375rem))]",
681
- // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
682
- "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
683
- // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
684
- "[box-shadow:var(--button-shadow,none)]",
685
- "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
686
- // Disabled state
687
- "disabled:pointer-events-none disabled:opacity-50",
688
- // SVG handling
689
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
690
- // Focus styles
691
- "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
692
- // Invalid state
693
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
694
- ].join(" ");
695
- var buttonVariants = cva(baseStyles, {
696
- variants: {
697
- variant: {
698
- // Default (Primary) variant - full customization
699
- default: [
700
- "bg-[var(--button-default-bg,hsl(var(--primary)))]",
701
- "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
702
- "border-[length:var(--button-default-border-width,0px)]",
703
- "border-[color:var(--button-default-border,transparent)]",
704
- "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
705
- "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
706
- "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
707
- "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
708
- "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
709
- ].join(" "),
710
- // Destructive variant - full customization
711
- destructive: [
712
- "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
713
- "text-[var(--button-destructive-fg,white)]",
714
- "border-[length:var(--button-destructive-border-width,0px)]",
715
- "border-[color:var(--button-destructive-border,transparent)]",
716
- "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
717
- "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
718
- "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
719
- "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
720
- "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
721
- "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
722
- "dark:bg-destructive/60"
723
- ].join(" "),
724
- // Outline variant - full customization with proper border handling
725
- outline: [
726
- "bg-[var(--button-outline-bg,hsl(var(--background)))]",
727
- "text-[var(--button-outline-fg,inherit)]",
728
- "border-[length:var(--button-outline-border-width,1px)]",
729
- "border-[color:var(--button-outline-border,hsl(var(--border)))]",
730
- "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
731
- "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
732
- "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
733
- "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
734
- "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
735
- "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
736
- ].join(" "),
737
- // Secondary variant - full customization
738
- secondary: [
739
- "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
740
- "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
741
- "border-[length:var(--button-secondary-border-width,0px)]",
742
- "border-[color:var(--button-secondary-border,transparent)]",
743
- "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
744
- "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
745
- "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
746
- "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
747
- "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
748
- ].join(" "),
749
- // Ghost variant - full customization
750
- ghost: [
751
- "bg-[var(--button-ghost-bg,transparent)]",
752
- "text-[var(--button-ghost-fg,inherit)]",
753
- "border-[length:var(--button-ghost-border-width,0px)]",
754
- "border-[color:var(--button-ghost-border,transparent)]",
755
- "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
756
- "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
757
- "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
758
- "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
759
- "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
760
- "dark:hover:bg-accent/50"
761
- ].join(" "),
762
- // Link variant - full customization
763
- link: [
764
- "bg-[var(--button-link-bg,transparent)]",
765
- "text-[var(--button-link-fg,hsl(var(--primary)))]",
766
- "border-[length:var(--button-link-border-width,0px)]",
767
- "border-[color:var(--button-link-border,transparent)]",
768
- "[box-shadow:var(--button-link-shadow,none)]",
769
- "hover:bg-[var(--button-link-hover-bg,transparent)]",
770
- "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
771
- "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
772
- "underline-offset-4 hover:underline"
773
- ].join(" ")
774
- },
775
- size: {
776
- default: [
777
- "h-[var(--button-height-md,2.25rem)]",
778
- "px-[var(--button-padding-x-md,1rem)]",
779
- "py-[var(--button-padding-y-md,0.5rem)]",
780
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
781
- ].join(" "),
782
- sm: [
783
- "h-[var(--button-height-sm,2rem)]",
784
- "px-[var(--button-padding-x-sm,0.75rem)]",
785
- "py-[var(--button-padding-y-sm,0.25rem)]",
786
- "gap-1.5",
787
- "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
788
- ].join(" "),
789
- md: [
790
- "h-[var(--button-height-md,2.25rem)]",
791
- "px-[var(--button-padding-x-md,1rem)]",
792
- "py-[var(--button-padding-y-md,0.5rem)]",
793
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
794
- ].join(" "),
795
- lg: [
796
- "h-[var(--button-height-lg,2.5rem)]",
797
- "px-[var(--button-padding-x-lg,1.5rem)]",
798
- "py-[var(--button-padding-y-lg,0.5rem)]",
799
- "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
800
- ].join(" "),
801
- icon: "size-[var(--button-height-md,2.25rem)]",
802
- "icon-sm": "size-[var(--button-height-sm,2rem)]",
803
- "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
804
- }
805
- },
806
- defaultVariants: {
807
- variant: "default",
808
- size: "default"
809
- }
810
- });
811
- var Pressable = React6.forwardRef(
812
- ({
813
- children,
814
- className,
815
- href,
816
- onClick,
817
- variant,
818
- size,
819
- asButton = false,
820
- fallbackComponentType = "span",
821
- componentType,
822
- "aria-label": ariaLabel,
823
- "aria-describedby": ariaDescribedby,
824
- id,
825
- ...props
826
- }, ref) => {
827
- const navigation = useNavigation({ href, onClick });
828
- const {
829
- normalizedHref,
830
- target,
831
- rel,
832
- linkType,
833
- isInternal,
834
- isExternal,
835
- handleClick
836
- } = navigation;
837
- const shouldRenderLink = normalizedHref && linkType !== "none";
838
- const shouldRenderButton = !shouldRenderLink && onClick;
839
- const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
840
- const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
841
- const shouldApplyButtonStyles = asButton || variant || size;
842
- const combinedClassName = cn(
843
- shouldApplyButtonStyles && buttonVariants({ variant, size }),
844
- className
845
- );
846
- const dataProps = Object.fromEntries(
847
- Object.entries(props).filter(([key]) => key.startsWith("data-"))
848
- );
849
- const buttonDataAttributes = shouldApplyButtonStyles ? {
850
- "data-slot": "button",
851
- "data-variant": variant ?? "default",
852
- "data-size": size ?? "default"
853
- } : {};
854
- const commonProps = {
855
- className: combinedClassName,
856
- onClick: handleClick,
857
- "aria-label": ariaLabel,
858
- "aria-describedby": ariaDescribedby,
859
- id,
860
- ...dataProps,
861
- ...buttonDataAttributes
862
- };
863
- if (finalComponentType === "a" && shouldRenderLink) {
864
- return /* @__PURE__ */ jsx(
865
- "a",
866
- {
867
- ref,
868
- href: normalizedHref,
869
- target,
870
- rel,
871
- ...commonProps,
872
- ...props,
873
- children
874
- }
875
- );
876
- }
877
- if (finalComponentType === "button") {
878
- return /* @__PURE__ */ jsx(
879
- "button",
880
- {
881
- ref,
882
- type: props.type || "button",
883
- ...commonProps,
884
- ...props,
885
- children
886
- }
887
- );
888
- }
889
- if (finalComponentType === "div") {
890
- return /* @__PURE__ */ jsx(
891
- "div",
892
- {
893
- ref,
894
- ...commonProps,
895
- children
896
- }
897
- );
898
- }
899
- return /* @__PURE__ */ jsx(
900
- "span",
901
- {
902
- ref,
903
- ...commonProps,
904
- children
905
- }
906
- );
907
- }
908
- );
909
- Pressable.displayName = "Pressable";
910
- var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
911
- var DynamicIcon = React6.memo(function DynamicIcon2({
912
- apiKey,
913
- ...props
914
- }) {
915
- return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
916
- });
917
- DynamicIcon.displayName = "DynamicIcon";
918
- var PANEL_POSITION_CLASS = {
919
- "top-left": "left-4 top-4",
920
- "top-right": "right-4 top-4",
921
- "bottom-left": "bottom-4 left-4",
922
- "bottom-right": "bottom-4 right-4"
923
- };
924
- var DEFAULT_VIEW_STATE = {
925
- latitude: 39.5,
926
- longitude: -98.35,
927
- zoom: 3
928
- };
929
- var VIDEO_FILE_EXTENSION_REGEX = /\.(mp4|webm|ogg|mov|m4v|m3u8)(\?.*)?$/i;
930
- function resolveMediaType(item) {
931
- if (item.type) {
932
- return item.type;
933
- }
934
- return VIDEO_FILE_EXTENSION_REGEX.test(item.src) ? "video" : "image";
935
- }
936
- function normalizeId(value, fallback) {
937
- if (value === null || value === void 0 || value === "") {
938
- return fallback;
939
- }
940
- return String(value);
941
- }
942
- function buildClusterCenter(markers) {
943
- if (!markers.length) {
944
- return null;
945
- }
946
- const total = markers.reduce(
947
- (accumulator, marker) => ({
948
- latitude: accumulator.latitude + marker.latitude,
949
- longitude: accumulator.longitude + marker.longitude
950
- }),
951
- { latitude: 0, longitude: 0 }
952
- );
953
- return {
954
- latitude: total.latitude / markers.length,
955
- longitude: total.longitude / markers.length
956
- };
957
- }
958
- function resolveActionKey(action, index) {
959
- if (typeof action.label === "string" && action.label.trim().length > 0) {
960
- return `label:${action.label}:${index}`;
961
- }
962
- if (action.href) {
963
- return `href:${action.href}:${index}`;
964
- }
965
- return `action:${index}`;
966
- }
967
- function MarkerActions({ actions }) {
968
- if (!actions || actions.length === 0) {
969
- return null;
970
- }
971
- return /* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: actions.map((action, index) => {
972
- const {
973
- label,
974
- icon,
975
- iconAfter,
976
- children,
977
- href,
978
- onClick,
979
- className: actionClassName,
980
- variant,
981
- size,
982
- asButton,
983
- ...rest
984
- } = action;
985
- return /* @__PURE__ */ jsx(
986
- Pressable,
987
- {
988
- href,
989
- onClick,
990
- variant: variant ?? (index === 0 ? "default" : "outline"),
991
- size: size ?? "sm",
992
- asButton: asButton ?? true,
993
- className: cn("inline-flex items-center gap-2", actionClassName),
994
- ...rest,
995
- children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
996
- icon,
997
- label,
998
- iconAfter
999
- ] })
1000
- },
1001
- resolveActionKey(action, index)
1002
- );
1003
- }) });
1004
- }
1005
- function MarkerMediaCarousel({
1006
- mediaItems,
1007
- optixFlowConfig
1008
- }) {
1009
- const [activeIndex, setActiveIndex] = React6.useState(0);
1010
- const totalItems = mediaItems.length;
1011
- const mediaResetKey = React6.useMemo(
1012
- () => mediaItems.map((item, index) => {
1013
- const itemId = normalizeId(item.id, `media-${index}`);
1014
- return `${itemId}:${item.src}:${item.type ?? ""}:${item.poster ?? ""}`;
1015
- }).join("|"),
1016
- [mediaItems]
1017
- );
1018
- const activeItemIndex = Math.min(activeIndex, Math.max(0, totalItems - 1));
1019
- React6.useEffect(() => {
1020
- setActiveIndex(0);
1021
- }, [mediaResetKey]);
1022
- const activeMediaItem = mediaItems[activeItemIndex];
1023
- const mediaType = resolveMediaType(activeMediaItem);
1024
- return /* @__PURE__ */ jsxs("div", { className: "relative border-b border-border/60 bg-muted/40", children: [
1025
- /* @__PURE__ */ jsx("div", { className: "relative h-44 w-full overflow-hidden", children: mediaType === "video" ? /* @__PURE__ */ jsx(
1026
- "video",
1027
- {
1028
- className: "h-full w-full object-cover",
1029
- controls: true,
1030
- preload: "metadata",
1031
- poster: activeMediaItem.poster,
1032
- children: /* @__PURE__ */ jsx("source", { src: activeMediaItem.src })
1033
- }
1034
- ) : /* @__PURE__ */ jsx(
1035
- Img,
1036
- {
1037
- src: activeMediaItem.src,
1038
- alt: activeMediaItem.alt ?? "Map marker media",
1039
- className: "h-full w-full object-cover",
1040
- loading: "eager",
1041
- optixFlowConfig
1042
- }
1043
- ) }),
1044
- totalItems > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
1045
- /* @__PURE__ */ jsx(
1046
- "button",
1047
- {
1048
- type: "button",
1049
- "aria-label": "Show previous media",
1050
- className: "absolute left-2 top-1/2 inline-flex size-8 -translate-y-1/2 items-center justify-center rounded-full bg-card text-card-foreground shadow-sm transition hover:bg-muted hover:text-muted-foreground",
1051
- onClick: () => {
1052
- setActiveIndex(
1053
- (current) => (current - 1 + totalItems) % totalItems
1054
- );
1055
- },
1056
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-left", size: 16 })
1057
- }
1058
- ),
1059
- /* @__PURE__ */ jsx(
1060
- "button",
1061
- {
1062
- type: "button",
1063
- "aria-label": "Show next media",
1064
- className: "absolute right-2 top-1/2 inline-flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-full bg-card text-card-foreground shadow-sm transition hover:bg-muted hover:text-muted-foreground",
1065
- onClick: () => {
1066
- setActiveIndex((current) => (current + 1) % totalItems);
1067
- },
1068
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-right", size: 16 })
1069
- }
1070
- ),
1071
- /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 left-1/2 flex -translate-x-1/2 items-center gap-1.5", children: mediaItems.map((item, index) => /* @__PURE__ */ jsx(
1072
- "button",
1073
- {
1074
- type: "button",
1075
- "aria-label": `Show media item ${index + 1}`,
1076
- className: cn(
1077
- "h-2 rounded-full transition-all",
1078
- index === activeItemIndex ? "w-6 bg-card" : "w-2 bg-card opacity-50 hover:opacity-100"
1079
- ),
1080
- onClick: () => setActiveIndex(index)
1081
- },
1082
- normalizeId(item.id, `media-dot-${index}`)
1083
- )) })
1084
- ] }) : null
1085
- ] });
1086
- }
1087
- function getMarkerTitle(marker, markerIndex) {
1088
- if (marker.title !== void 0 && marker.title !== null) {
1089
- return marker.title;
1090
- }
1091
- if (marker.label !== void 0 && marker.label !== null) {
1092
- return marker.label;
1093
- }
1094
- return `Location ${markerIndex + 1}`;
1095
- }
1096
- function GeoMap({
1097
- className,
1098
- mapWrapperClassName,
1099
- mapClassName,
1100
- panelClassName,
1101
- panelPosition = "top-left",
1102
- stadiaApiKey = "",
1103
- mapStyle = "osm-bright",
1104
- styleUrl,
1105
- mapLibreCssHref,
1106
- markers = [],
1107
- clusters = [],
1108
- viewState,
1109
- defaultViewState,
1110
- onViewStateChange,
1111
- onMapClick,
1112
- onMarkerDrag,
1113
- showNavigationControl = true,
1114
- showGeolocateControl = false,
1115
- navigationControlPosition = "top-right",
1116
- geolocateControlPosition = "top-left",
1117
- flyToOptions,
1118
- markerFocusZoom = 14,
1119
- clusterFocusZoom = 5,
1120
- selectedMarkerId,
1121
- initialSelectedMarkerId,
1122
- onSelectionChange,
1123
- clearSelectionOnMapClick = true,
1124
- mapChildren,
1125
- optixFlowConfig
1126
- }) {
1127
- const normalizedStandaloneMarkers = React6.useMemo(
1128
- () => markers.map((marker, index) => ({
1129
- ...marker,
1130
- id: normalizeId(marker.id, `marker-${index}`)
1131
- })),
1132
- [markers]
1133
- );
1134
- const normalizedClusters = React6.useMemo(() => {
1135
- const results = [];
1136
- clusters.forEach((cluster, clusterIndex) => {
1137
- const clusterId = normalizeId(cluster.id, `cluster-${clusterIndex}`);
1138
- const normalizedClusterMarkers = cluster.markers.map(
1139
- (marker, markerIndex) => ({
1140
- ...marker,
1141
- id: normalizeId(marker.id, `${clusterId}-marker-${markerIndex}`),
1142
- clusterId
1143
- })
1144
- );
1145
- const clusterCenter = cluster.latitude !== void 0 && cluster.longitude !== void 0 ? { latitude: cluster.latitude, longitude: cluster.longitude } : buildClusterCenter(normalizedClusterMarkers);
1146
- if (!clusterCenter) {
1147
- return;
1148
- }
1149
- results.push({
1150
- ...cluster,
1151
- id: clusterId,
1152
- latitude: clusterCenter.latitude,
1153
- longitude: clusterCenter.longitude,
1154
- markers: normalizedClusterMarkers
1155
- });
1156
- });
1157
- return results;
1158
- }, [clusters]);
1159
- const markerLookup = React6.useMemo(() => {
1160
- const lookup = /* @__PURE__ */ new Map();
1161
- normalizedStandaloneMarkers.forEach((marker) => {
1162
- lookup.set(marker.id, marker);
1163
- });
1164
- normalizedClusters.forEach((cluster) => {
1165
- cluster.markers.forEach((marker) => {
1166
- lookup.set(marker.id, marker);
1167
- });
1168
- });
1169
- return lookup;
1170
- }, [normalizedClusters, normalizedStandaloneMarkers]);
1171
- const clusterLookup = React6.useMemo(() => {
1172
- const lookup = /* @__PURE__ */ new Map();
1173
- normalizedClusters.forEach((cluster) => {
1174
- lookup.set(cluster.id, cluster);
1175
- });
1176
- return lookup;
1177
- }, [normalizedClusters]);
1178
- const firstCoordinate = React6.useMemo(() => {
1179
- if (normalizedStandaloneMarkers.length > 0) {
1180
- const firstStandaloneMarker = normalizedStandaloneMarkers[0];
1181
- return {
1182
- latitude: firstStandaloneMarker.latitude,
1183
- longitude: firstStandaloneMarker.longitude
1184
- };
1185
- }
1186
- if (normalizedClusters.length > 0) {
1187
- const firstCluster = normalizedClusters[0];
1188
- return {
1189
- latitude: firstCluster.latitude,
1190
- longitude: firstCluster.longitude
1191
- };
1192
- }
1193
- return {
1194
- latitude: DEFAULT_VIEW_STATE.latitude,
1195
- longitude: DEFAULT_VIEW_STATE.longitude
1196
- };
1197
- }, [normalizedClusters, normalizedStandaloneMarkers]);
1198
- const [uncontrolledViewState, setUncontrolledViewState] = React6.useState({
1199
- latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
1200
- longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
1201
- zoom: defaultViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom
1202
- });
1203
- const isControlledViewState = viewState !== void 0;
1204
- const resolvedViewState = isControlledViewState ? viewState : uncontrolledViewState;
1205
- const applyViewState = React6.useCallback(
1206
- (nextState) => {
1207
- if (!isControlledViewState) {
1208
- setUncontrolledViewState((current) => {
1209
- const next = { ...current, ...nextState };
1210
- const hasChanged = current.latitude !== next.latitude || current.longitude !== next.longitude || current.zoom !== next.zoom;
1211
- return hasChanged ? next : current;
1212
- });
1213
- }
1214
- onViewStateChange?.(nextState);
1215
- },
1216
- [isControlledViewState, onViewStateChange]
1217
- );
1218
- const [selection, setSelection] = React6.useState(() => {
1219
- if (initialSelectedMarkerId !== void 0 && initialSelectedMarkerId !== null) {
1220
- return {
1221
- type: "marker",
1222
- markerId: String(initialSelectedMarkerId)
1223
- };
1224
- }
1225
- return { type: "none" };
1226
- });
1227
- React6.useEffect(() => {
1228
- if (selectedMarkerId === void 0 || selectedMarkerId === null) {
1229
- return;
1230
- }
1231
- setSelection({
1232
- type: "marker",
1233
- markerId: String(selectedMarkerId)
1234
- });
1235
- }, [selectedMarkerId]);
1236
- const selectedMarker = selection.markerId ? markerLookup.get(selection.markerId) : void 0;
1237
- const selectedCluster = selection.clusterId ? clusterLookup.get(selection.clusterId) : void 0;
1238
- React6.useEffect(() => {
1239
- if (selection.type === "marker" && selection.markerId && !selectedMarker) {
1240
- setSelection({ type: "none" });
1241
- onSelectionChange?.({ type: "none" });
1242
- }
1243
- }, [onSelectionChange, selectedMarker, selection]);
1244
- const emitSelectionChange = React6.useCallback(
1245
- (nextSelection) => {
1246
- if (nextSelection.type === "none") {
1247
- onSelectionChange?.({ type: "none" });
1248
- return;
1249
- }
1250
- if (nextSelection.type === "marker") {
1251
- const parentCluster = nextSelection.marker.clusterId ? clusterLookup.get(nextSelection.marker.clusterId) : void 0;
1252
- onSelectionChange?.({
1253
- type: "marker",
1254
- marker: nextSelection.marker,
1255
- cluster: parentCluster
1256
- });
1257
- return;
1258
- }
1259
- onSelectionChange?.({
1260
- type: "cluster",
1261
- cluster: nextSelection.cluster
1262
- });
1263
- },
1264
- [clusterLookup, onSelectionChange]
1265
- );
1266
- const selectMarker = React6.useCallback(
1267
- (marker) => {
1268
- setSelection({
1269
- type: "marker",
1270
- markerId: marker.id,
1271
- clusterId: marker.clusterId
1272
- });
1273
- applyViewState({
1274
- latitude: marker.latitude,
1275
- longitude: marker.longitude,
1276
- zoom: markerFocusZoom
1277
- });
1278
- emitSelectionChange({ type: "marker", marker });
1279
- },
1280
- [applyViewState, emitSelectionChange, markerFocusZoom]
1281
- );
1282
- const selectCluster = React6.useCallback(
1283
- (cluster) => {
1284
- setSelection({
1285
- type: "cluster",
1286
- clusterId: cluster.id
1287
- });
1288
- applyViewState({
1289
- latitude: cluster.latitude,
1290
- longitude: cluster.longitude,
1291
- zoom: clusterFocusZoom
1292
- });
1293
- emitSelectionChange({ type: "cluster", cluster });
1294
- },
1295
- [applyViewState, clusterFocusZoom, emitSelectionChange]
1296
- );
1297
- const clearSelection = React6.useCallback(() => {
1298
- setSelection({ type: "none" });
1299
- emitSelectionChange({ type: "none" });
1300
- }, [emitSelectionChange]);
1301
- const mapMarkers = React6.useMemo(() => {
1302
- const resolvedMarkers = [];
1303
- normalizedClusters.forEach((cluster) => {
1304
- const isSelected = selection.type === "cluster" && selection.clusterId === cluster.id;
1305
- resolvedMarkers.push({
1306
- id: `cluster-pin:${cluster.id}`,
1307
- latitude: cluster.latitude,
1308
- longitude: cluster.longitude,
1309
- element: () => {
1310
- const customMarkerElement = cluster.markerElement;
1311
- const markerBody = typeof customMarkerElement === "function" ? customMarkerElement({
1312
- isSelected,
1313
- count: cluster.markers.length
1314
- }) : customMarkerElement;
1315
- return /* @__PURE__ */ jsx(
1316
- "button",
1317
- {
1318
- type: "button",
1319
- className: "group cursor-pointer",
1320
- onClick: (event) => {
1321
- event.preventDefault();
1322
- event.stopPropagation();
1323
- selectCluster(cluster);
1324
- },
1325
- "aria-label": `View ${cluster.markers.length} clustered locations`,
1326
- children: markerBody ?? /* @__PURE__ */ jsx(
1327
- "span",
1328
- {
1329
- className: cn(
1330
- "inline-flex min-h-10 min-w-10 items-center justify-center rounded-full border-2 border-white px-2 text-xs font-semibold text-white shadow-lg transition-transform duration-200 group-hover:scale-105",
1331
- isSelected && "ring-4 ring-primary/30",
1332
- cluster.pinClassName
1333
- ),
1334
- style: {
1335
- backgroundColor: cluster.pinColor ?? "var(--foreground)"
1336
- },
1337
- children: cluster.markers.length
1338
- }
1339
- )
1340
- }
1341
- );
1342
- }
1343
- });
1344
- });
1345
- normalizedStandaloneMarkers.forEach((marker) => {
1346
- const isSelected = selection.type === "marker" && selection.markerId === marker.id;
1347
- const customMarkerElement = marker.markerElement;
1348
- resolvedMarkers.push({
1349
- id: marker.id,
1350
- latitude: marker.latitude,
1351
- longitude: marker.longitude,
1352
- draggable: marker.draggable,
1353
- element: () => {
1354
- const markerBody = typeof customMarkerElement === "function" ? customMarkerElement({ isSelected }) : customMarkerElement;
1355
- return /* @__PURE__ */ jsx(
1356
- "button",
1357
- {
1358
- type: "button",
1359
- className: "group cursor-pointer",
1360
- onClick: (event) => {
1361
- event.preventDefault();
1362
- event.stopPropagation();
1363
- selectMarker(marker);
1364
- },
1365
- "aria-label": typeof marker.title === "string" ? `View ${marker.title}` : "View location details",
1366
- children: markerBody ?? /* @__PURE__ */ jsx(
1367
- "span",
1368
- {
1369
- className: cn(
1370
- "inline-flex h-4 w-4 rounded-full border-2 border-white shadow-md transition-transform duration-200 group-hover:scale-110",
1371
- isSelected && "h-5 w-5 ring-4 ring-primary/30",
1372
- marker.pinClassName
1373
- ),
1374
- style: {
1375
- backgroundColor: marker.pinColor ?? "#f43f5e"
1376
- }
1377
- }
1378
- )
1379
- }
1380
- );
1381
- }
1382
- });
1383
- });
1384
- return resolvedMarkers;
1385
- }, [
1386
- normalizedClusters,
1387
- normalizedStandaloneMarkers,
1388
- selectCluster,
1389
- selectMarker,
1390
- selection
1391
- ]);
1392
- const renderMarkerPanel = () => {
1393
- if (selectedMarker) {
1394
- const markerMediaItems = selectedMarker.mediaItems ?? [];
1395
- return /* @__PURE__ */ jsxs(
1396
- "div",
1397
- {
1398
- className: cn(
1399
- "relative w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-xl border border-border bg-card text-card-foreground shadow-2xl",
1400
- panelClassName
1401
- ),
1402
- children: [
1403
- /* @__PURE__ */ jsx(
1404
- "button",
1405
- {
1406
- type: "button",
1407
- "aria-label": "Close marker details",
1408
- className: "flex size-8 items-center justify-center rounded-full border border-border bg-card text-card-foreground transition hover:bg-muted hover:text-foreground absolute top-2 right-2 z-10",
1409
- onClick: clearSelection,
1410
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/x", size: 16 })
1411
- }
1412
- ),
1413
- markerMediaItems.length > 0 ? /* @__PURE__ */ jsx(
1414
- MarkerMediaCarousel,
1415
- {
1416
- mediaItems: markerMediaItems,
1417
- optixFlowConfig
1418
- }
1419
- ) : null,
1420
- /* @__PURE__ */ jsxs("div", { className: "space-y-2 p-4", children: [
1421
- /* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-3", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
1422
- selectedMarker.eyebrow ? /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide", children: selectedMarker.eyebrow }) : null,
1423
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold leading-tight", children: selectedMarker.title ?? selectedMarker.label ?? "Location" })
1424
- ] }) }),
1425
- selectedMarker.summary ? /* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed", children: selectedMarker.summary }) : null,
1426
- selectedMarker.locationLine ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center justify-start text-sm gap-2", children: [
1427
- /* @__PURE__ */ jsx(
1428
- DynamicIcon,
1429
- {
1430
- name: "lucide:map-pin",
1431
- className: "opacity-50",
1432
- size: 14
1433
- }
1434
- ),
1435
- typeof selectedMarker.locationLine === "string" ? /* @__PURE__ */ jsx(
1436
- Pressable,
1437
- {
1438
- href: selectedMarker.locationUrl,
1439
- className: cn(
1440
- "transition-all duration-500",
1441
- "font-medium opacity-75 hover:opacity-100",
1442
- selectedMarker.locationUrl ? "underline underline-offset-4" : ""
1443
- ),
1444
- children: selectedMarker.locationLine
1445
- }
1446
- ) : selectedMarker.locationLine
1447
- ] }) : null,
1448
- selectedMarker.hoursLine ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center justify-start text-sm gap-2", children: [
1449
- /* @__PURE__ */ jsx(
1450
- DynamicIcon,
1451
- {
1452
- name: "lucide:clock",
1453
- className: "opacity-50",
1454
- size: 14
1455
- }
1456
- ),
1457
- typeof selectedMarker.hoursLine === "string" ? /* @__PURE__ */ jsx("div", { className: "font-medium", children: selectedMarker.hoursLine }) : selectedMarker.hoursLine
1458
- ] }) : null,
1459
- selectedMarker.markerContentComponent ? /* @__PURE__ */ jsx("div", { className: "relative", children: selectedMarker.markerContentComponent }) : null,
1460
- /* @__PURE__ */ jsx(MarkerActions, { actions: selectedMarker.actions })
1461
- ] })
1462
- ]
1463
- }
1464
- );
1465
- }
1466
- if (selectedCluster) {
1467
- return /* @__PURE__ */ jsxs(
1468
- "div",
1469
- {
1470
- className: cn(
1471
- "relative w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-xl border border-border bg-card text-card-foreground p-4 shadow-2xl",
1472
- panelClassName
1473
- ),
1474
- children: [
1475
- /* @__PURE__ */ jsx(
1476
- "button",
1477
- {
1478
- type: "button",
1479
- "aria-label": "Close cluster details",
1480
- className: "flex size-8 items-center justify-center rounded-full border border-border bg-card text-card-foreground transition hover:bg-muted hover:text-foreground absolute top-2 right-2 z-10",
1481
- onClick: clearSelection,
1482
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/x", size: 16 })
1483
- }
1484
- ),
1485
- /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-start justify-between gap-3", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1486
- selectedCluster.label ? /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: selectedCluster.label }) : null,
1487
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold leading-tight text-foreground", children: selectedCluster.title ?? "Clustered Locations" }),
1488
- /* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: selectedCluster.summary ?? `${selectedCluster.markers.length} location${selectedCluster.markers.length === 1 ? "" : "s"} in this cluster.` })
1489
- ] }) }),
1490
- /* @__PURE__ */ jsx("div", { className: "max-h-56 space-y-2 overflow-y-auto pr-1", children: selectedCluster.markers.map((marker, markerIndex) => /* @__PURE__ */ jsxs(
1491
- "button",
1492
- {
1493
- type: "button",
1494
- className: "w-full rounded-lg border border-border/60 p-3 text-left transition hover:border-border hover:bg-muted/50",
1495
- onClick: () => selectMarker(marker),
1496
- children: [
1497
- /* @__PURE__ */ jsx("div", { className: "line-clamp-1 text-sm font-semibold text-foreground", children: getMarkerTitle(marker, markerIndex) }),
1498
- marker.summary ? /* @__PURE__ */ jsx("div", { className: "mt-1 line-clamp-2 text-xs text-muted-foreground", children: marker.summary }) : null
1499
- ]
1500
- },
1501
- marker.id
1502
- )) })
1503
- ]
1504
- }
1505
- );
1506
- }
1507
- return null;
1508
- };
1509
- return /* @__PURE__ */ jsxs(
1510
- "div",
1511
- {
1512
- className: cn(
1513
- "relative overflow-hidden rounded-2xl border border-border bg-background",
1514
- className
1515
- ),
1516
- children: [
1517
- /* @__PURE__ */ jsx("div", { className: cn("h-[520px] w-full", mapWrapperClassName), children: /* @__PURE__ */ jsx(
1518
- MapLibre,
1519
- {
1520
- stadiaApiKey,
1521
- mapStyle,
1522
- styleUrl,
1523
- mapLibreCssHref,
1524
- viewState: resolvedViewState,
1525
- onViewStateChange: applyViewState,
1526
- markers: mapMarkers,
1527
- onClick: (coord) => {
1528
- onMapClick?.(coord);
1529
- if (clearSelectionOnMapClick) {
1530
- clearSelection();
1531
- }
1532
- },
1533
- onMarkerDrag,
1534
- showNavigationControl,
1535
- showGeolocateControl,
1536
- navigationControlPosition,
1537
- geolocateControlPosition,
1538
- flyToOptions,
1539
- className: cn("h-full w-full", mapClassName),
1540
- children: mapChildren
1541
- }
1542
- ) }),
1543
- selection.type !== "none" ? /* @__PURE__ */ jsx(
1544
- "div",
1545
- {
1546
- className: cn(
1547
- "pointer-events-none absolute z-20",
1548
- PANEL_POSITION_CLASS[panelPosition]
1549
- ),
1550
- children: /* @__PURE__ */ jsx("div", { className: "pointer-events-auto", children: renderMarkerPanel() })
1551
- }
1552
- ) : null
1553
- ]
1554
- }
1555
- );
1556
- }
1557
- var sizeStyles = {
1558
- sm: "max-w-md",
1559
- md: "max-w-2xl",
1560
- lg: "max-w-4xl",
1561
- xl: "max-w-5xl",
1562
- full: "max-w-7xl",
1563
- compact: "max-w-[700px]"
1564
- };
1565
- var dialogTransition = {
1566
- duration: 0.35,
1567
- ease: [0.16, 1, 0.3, 1]
1568
- };
1569
- function AnimatedDialog({
1570
- open,
1571
- onOpenChange,
1572
- title,
1573
- eyebrow,
1574
- description,
1575
- children,
1576
- header,
1577
- footer,
1578
- size = "lg",
1579
- className,
1580
- contentClassName,
1581
- featuredMediaHeader
1582
- }) {
1583
- const titleId = useId();
1584
- const descriptionId = useId();
1585
- const containerRef = useRef(null);
1586
- useOnClickOutside(containerRef, () => {
1587
- if (open) {
1588
- onOpenChange(false);
1589
- }
1590
- });
1591
- useEffect(() => {
1592
- if (!open) {
1593
- return;
1594
- }
1595
- const onKeyDown = (event) => {
1596
- if (event.key === "Escape") {
1597
- onOpenChange(false);
1598
- }
1599
- };
1600
- const previousOverflow = document.body.style.overflow;
1601
- document.body.style.overflow = "hidden";
1602
- window.addEventListener("keydown", onKeyDown);
1603
- return () => {
1604
- document.body.style.overflow = previousOverflow;
1605
- window.removeEventListener("keydown", onKeyDown);
1606
- };
1607
- }, [open, onOpenChange]);
1608
- return /* @__PURE__ */ jsx(AnimatePresence, { children: open ? /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 h-screen overflow-y-auto", children: [
1609
- /* @__PURE__ */ jsx(
1610
- motion.div,
1611
- {
1612
- initial: { opacity: 0 },
1613
- animate: { opacity: 1, transition: dialogTransition },
1614
- exit: { opacity: 0, transition: dialogTransition },
1615
- className: "fixed inset-0 h-full w-full bg-foreground/80 backdrop-blur-lg"
532
+ };
533
+ const previousOverflow = document.body.style.overflow;
534
+ document.body.style.overflow = "hidden";
535
+ window.addEventListener("keydown", onKeyDown);
536
+ return () => {
537
+ document.body.style.overflow = previousOverflow;
538
+ window.removeEventListener("keydown", onKeyDown);
539
+ };
540
+ }, [open, onOpenChange]);
541
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: open ? /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 h-screen overflow-y-auto", children: [
542
+ /* @__PURE__ */ jsx(
543
+ motion.div,
544
+ {
545
+ initial: { opacity: 0 },
546
+ animate: { opacity: 1, transition: dialogTransition },
547
+ exit: { opacity: 0, transition: dialogTransition },
548
+ className: "fixed inset-0 h-full w-full bg-foreground/80 backdrop-blur-lg"
1616
549
  }
1617
550
  ),
1618
551
  /* @__PURE__ */ jsxs(
@@ -1911,10 +844,10 @@ var ImageSlider = ({
1911
844
  optixFlowConfig
1912
845
  }) => {
1913
846
  const hasImages = images.length > 0;
1914
- const [currentIndex, setCurrentIndex] = React6.useState(
847
+ const [currentIndex, setCurrentIndex] = React4.useState(
1915
848
  () => normalizeIndex(startIndex, images.length)
1916
849
  );
1917
- const handleNext = React6.useCallback(() => {
850
+ const handleNext = React4.useCallback(() => {
1918
851
  if (!hasImages) return;
1919
852
  setCurrentIndex((prevIndex) => {
1920
853
  const nextIndex = prevIndex + 1 >= images.length ? 0 : prevIndex + 1;
@@ -1922,7 +855,7 @@ var ImageSlider = ({
1922
855
  return nextIndex;
1923
856
  });
1924
857
  }, [hasImages, images.length, onSlideChange]);
1925
- const handlePrevious = React6.useCallback(() => {
858
+ const handlePrevious = React4.useCallback(() => {
1926
859
  if (!hasImages) return;
1927
860
  setCurrentIndex((prevIndex) => {
1928
861
  const nextIndex = prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1;
@@ -1930,11 +863,11 @@ var ImageSlider = ({
1930
863
  return nextIndex;
1931
864
  });
1932
865
  }, [hasImages, images.length, onSlideChange]);
1933
- React6.useEffect(() => {
866
+ React4.useEffect(() => {
1934
867
  if (!hasImages) return;
1935
868
  setCurrentIndex(normalizeIndex(startIndex, images.length));
1936
869
  }, [startIndex, images.length, hasImages]);
1937
- React6.useEffect(() => {
870
+ React4.useEffect(() => {
1938
871
  if (!enableKeyboard || !hasImages) return;
1939
872
  const handleKeyDown = (event) => {
1940
873
  if (event.key === "ArrowRight") {
@@ -1948,7 +881,7 @@ var ImageSlider = ({
1948
881
  window.removeEventListener("keydown", handleKeyDown);
1949
882
  };
1950
883
  }, [enableKeyboard, handleNext, handlePrevious, hasImages]);
1951
- React6.useEffect(() => {
884
+ React4.useEffect(() => {
1952
885
  if (!autoplay || images.length < 2) return;
1953
886
  const interval = window.setInterval(handleNext, autoplayIntervalMs);
1954
887
  return () => window.clearInterval(interval);
@@ -2019,8 +952,150 @@ var ImageSlider = ({
2019
952
  ) : null
2020
953
  ]
2021
954
  }
2022
- );
2023
- };
955
+ );
956
+ };
957
+ var baseStyles = [
958
+ // Layout
959
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
960
+ // Typography - using CSS variables with sensible defaults
961
+ "font-[var(--button-font-family,inherit)]",
962
+ "font-[var(--button-font-weight,500)]",
963
+ "tracking-[var(--button-letter-spacing,0)]",
964
+ "leading-[var(--button-line-height,1.25)]",
965
+ "[text-transform:var(--button-text-transform,none)]",
966
+ "text-sm",
967
+ // Border radius
968
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
969
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
970
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
971
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
972
+ "[box-shadow:var(--button-shadow,none)]",
973
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
974
+ // Disabled state
975
+ "disabled:pointer-events-none disabled:opacity-50",
976
+ // SVG handling
977
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
978
+ // Focus styles
979
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
980
+ // Invalid state
981
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
982
+ ].join(" ");
983
+ var buttonVariants = cva(baseStyles, {
984
+ variants: {
985
+ variant: {
986
+ // Default (Primary) variant - full customization
987
+ default: [
988
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
989
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
990
+ "border-[length:var(--button-default-border-width,0px)]",
991
+ "border-[color:var(--button-default-border,transparent)]",
992
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
993
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
994
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
995
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
996
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
997
+ ].join(" "),
998
+ // Destructive variant - full customization
999
+ destructive: [
1000
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
1001
+ "text-[var(--button-destructive-fg,white)]",
1002
+ "border-[length:var(--button-destructive-border-width,0px)]",
1003
+ "border-[color:var(--button-destructive-border,transparent)]",
1004
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
1005
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
1006
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
1007
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
1008
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
1009
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
1010
+ "dark:bg-destructive/60"
1011
+ ].join(" "),
1012
+ // Outline variant - full customization with proper border handling
1013
+ outline: [
1014
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
1015
+ "text-[var(--button-outline-fg,inherit)]",
1016
+ "border-[length:var(--button-outline-border-width,1px)]",
1017
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
1018
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
1019
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
1020
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
1021
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
1022
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
1023
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
1024
+ ].join(" "),
1025
+ // Secondary variant - full customization
1026
+ secondary: [
1027
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
1028
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
1029
+ "border-[length:var(--button-secondary-border-width,0px)]",
1030
+ "border-[color:var(--button-secondary-border,transparent)]",
1031
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
1032
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
1033
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
1034
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
1035
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
1036
+ ].join(" "),
1037
+ // Ghost variant - full customization
1038
+ ghost: [
1039
+ "bg-[var(--button-ghost-bg,transparent)]",
1040
+ "text-[var(--button-ghost-fg,inherit)]",
1041
+ "border-[length:var(--button-ghost-border-width,0px)]",
1042
+ "border-[color:var(--button-ghost-border,transparent)]",
1043
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
1044
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
1045
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
1046
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
1047
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
1048
+ "dark:hover:bg-accent/50"
1049
+ ].join(" "),
1050
+ // Link variant - full customization
1051
+ link: [
1052
+ "bg-[var(--button-link-bg,transparent)]",
1053
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
1054
+ "border-[length:var(--button-link-border-width,0px)]",
1055
+ "border-[color:var(--button-link-border,transparent)]",
1056
+ "[box-shadow:var(--button-link-shadow,none)]",
1057
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
1058
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
1059
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
1060
+ "underline-offset-4 hover:underline"
1061
+ ].join(" ")
1062
+ },
1063
+ size: {
1064
+ default: [
1065
+ "h-[var(--button-height-md,2.25rem)]",
1066
+ "px-[var(--button-padding-x-md,1rem)]",
1067
+ "py-[var(--button-padding-y-md,0.5rem)]",
1068
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
1069
+ ].join(" "),
1070
+ sm: [
1071
+ "h-[var(--button-height-sm,2rem)]",
1072
+ "px-[var(--button-padding-x-sm,0.75rem)]",
1073
+ "py-[var(--button-padding-y-sm,0.25rem)]",
1074
+ "gap-1.5",
1075
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
1076
+ ].join(" "),
1077
+ md: [
1078
+ "h-[var(--button-height-md,2.25rem)]",
1079
+ "px-[var(--button-padding-x-md,1rem)]",
1080
+ "py-[var(--button-padding-y-md,0.5rem)]",
1081
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
1082
+ ].join(" "),
1083
+ lg: [
1084
+ "h-[var(--button-height-lg,2.5rem)]",
1085
+ "px-[var(--button-padding-x-lg,1.5rem)]",
1086
+ "py-[var(--button-padding-y-lg,0.5rem)]",
1087
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
1088
+ ].join(" "),
1089
+ icon: "size-[var(--button-height-md,2.25rem)]",
1090
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
1091
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
1092
+ }
1093
+ },
1094
+ defaultVariants: {
1095
+ variant: "default",
1096
+ size: "default"
1097
+ }
1098
+ });
2024
1099
  function Button({
2025
1100
  className,
2026
1101
  variant = "default",
@@ -2064,127 +1139,412 @@ function CardHeader({ className, ...props }) {
2064
1139
  ),
2065
1140
  ...props
2066
1141
  }
2067
- );
2068
- }
2069
- function CardTitle({ className, ...props }) {
2070
- return /* @__PURE__ */ jsx(
2071
- "div",
2072
- {
2073
- "data-slot": "card-title",
2074
- className: cn("leading-none font-semibold", className),
2075
- ...props
1142
+ );
1143
+ }
1144
+ function CardTitle({ className, ...props }) {
1145
+ return /* @__PURE__ */ jsx(
1146
+ "div",
1147
+ {
1148
+ "data-slot": "card-title",
1149
+ className: cn("leading-none font-semibold", className),
1150
+ ...props
1151
+ }
1152
+ );
1153
+ }
1154
+ function CardDescription({ className, ...props }) {
1155
+ return /* @__PURE__ */ jsx(
1156
+ "div",
1157
+ {
1158
+ "data-slot": "card-description",
1159
+ className: cn("text-muted-foreground text-sm", className),
1160
+ ...props
1161
+ }
1162
+ );
1163
+ }
1164
+ function CardContent({ className, ...props }) {
1165
+ return /* @__PURE__ */ jsx(
1166
+ "div",
1167
+ {
1168
+ "data-slot": "card-content",
1169
+ className: cn("px-6", className),
1170
+ ...props
1171
+ }
1172
+ );
1173
+ }
1174
+ function CardFooter({ className, ...props }) {
1175
+ return /* @__PURE__ */ jsx(
1176
+ "div",
1177
+ {
1178
+ "data-slot": "card-footer",
1179
+ className: cn("flex items-center px-6 [.border-t]:pt-6", className),
1180
+ ...props
1181
+ }
1182
+ );
1183
+ }
1184
+ var badgeVariants = cva(
1185
+ "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
1186
+ {
1187
+ variants: {
1188
+ variant: {
1189
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
1190
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
1191
+ destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1192
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
1193
+ }
1194
+ },
1195
+ defaultVariants: {
1196
+ variant: "default"
1197
+ }
1198
+ }
1199
+ );
1200
+ function Badge({
1201
+ className,
1202
+ variant,
1203
+ asChild = false,
1204
+ ...props
1205
+ }) {
1206
+ const Comp = asChild ? Slot : "span";
1207
+ return /* @__PURE__ */ jsx(
1208
+ Comp,
1209
+ {
1210
+ "data-slot": "badge",
1211
+ className: cn(badgeVariants({ variant }), className),
1212
+ ...props
1213
+ }
1214
+ );
1215
+ }
1216
+ function Popover({
1217
+ ...props
1218
+ }) {
1219
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
1220
+ }
1221
+ function PopoverTrigger({
1222
+ ...props
1223
+ }) {
1224
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
1225
+ }
1226
+ function PopoverContent({
1227
+ className,
1228
+ align = "center",
1229
+ sideOffset = 4,
1230
+ ...props
1231
+ }) {
1232
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1233
+ PopoverPrimitive.Content,
1234
+ {
1235
+ "data-slot": "popover-content",
1236
+ align,
1237
+ sideOffset,
1238
+ className: cn(
1239
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
1240
+ className
1241
+ ),
1242
+ ...props
1243
+ }
1244
+ ) });
1245
+ }
1246
+ var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
1247
+ var DynamicIcon = React4.memo(function DynamicIcon2({
1248
+ apiKey,
1249
+ ...props
1250
+ }) {
1251
+ return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
1252
+ });
1253
+ DynamicIcon.displayName = "DynamicIcon";
1254
+ function StarRating({
1255
+ rating,
1256
+ size = 18,
1257
+ className
1258
+ }) {
1259
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
1260
+ DynamicIcon,
1261
+ {
1262
+ name: "icon-park-solid/star",
1263
+ size,
1264
+ className: cn(
1265
+ star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
1266
+ )
1267
+ },
1268
+ star
1269
+ )) });
1270
+ }
1271
+ function normalizePhoneNumber(input) {
1272
+ const trimmed = input.trim();
1273
+ if (trimmed.toLowerCase().startsWith("tel:")) {
1274
+ return trimmed;
1275
+ }
1276
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
1277
+ if (match) {
1278
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
1279
+ const extension = match[3];
1280
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
1281
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
1282
+ return `tel:${withExtension}`;
1283
+ }
1284
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
1285
+ return `tel:${cleaned}`;
1286
+ }
1287
+ function normalizeEmail(input) {
1288
+ const trimmed = input.trim();
1289
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
1290
+ return trimmed;
1291
+ }
1292
+ return `mailto:${trimmed}`;
1293
+ }
1294
+ function isEmail(input) {
1295
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1296
+ return emailRegex.test(input.trim());
1297
+ }
1298
+ function isPhoneNumber(input) {
1299
+ const trimmed = input.trim();
1300
+ if (trimmed.toLowerCase().startsWith("tel:")) {
1301
+ return true;
1302
+ }
1303
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
1304
+ return phoneRegex.test(trimmed);
1305
+ }
1306
+ function isInternalUrl(href) {
1307
+ if (typeof window === "undefined") {
1308
+ return href.startsWith("/") && !href.startsWith("//");
1309
+ }
1310
+ const trimmed = href.trim();
1311
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
1312
+ return true;
1313
+ }
1314
+ try {
1315
+ const url = new URL(trimmed, window.location.href);
1316
+ const currentOrigin = window.location.origin;
1317
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
1318
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
1319
+ } catch {
1320
+ return false;
1321
+ }
1322
+ }
1323
+ function toRelativePath(href) {
1324
+ if (typeof window === "undefined") {
1325
+ return href;
1326
+ }
1327
+ const trimmed = href.trim();
1328
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
1329
+ return trimmed;
1330
+ }
1331
+ try {
1332
+ const url = new URL(trimmed, window.location.href);
1333
+ const currentOrigin = window.location.origin;
1334
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
1335
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
1336
+ return url.pathname + url.search + url.hash;
1337
+ }
1338
+ } catch {
1339
+ }
1340
+ return trimmed;
1341
+ }
1342
+ function useNavigation({
1343
+ href,
1344
+ onClick
1345
+ } = {}) {
1346
+ const linkType = React4.useMemo(() => {
1347
+ if (!href || href.trim() === "") {
1348
+ return onClick ? "none" : "none";
1349
+ }
1350
+ const trimmed = href.trim();
1351
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
1352
+ return "mailto";
1353
+ }
1354
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
1355
+ return "tel";
1356
+ }
1357
+ if (isInternalUrl(trimmed)) {
1358
+ return "internal";
1359
+ }
1360
+ try {
1361
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
1362
+ return "external";
1363
+ } catch {
1364
+ return "internal";
1365
+ }
1366
+ }, [href, onClick]);
1367
+ const normalizedHref = React4.useMemo(() => {
1368
+ if (!href || href.trim() === "") {
1369
+ return void 0;
1370
+ }
1371
+ const trimmed = href.trim();
1372
+ switch (linkType) {
1373
+ case "tel":
1374
+ return normalizePhoneNumber(trimmed);
1375
+ case "mailto":
1376
+ return normalizeEmail(trimmed);
1377
+ case "internal":
1378
+ return toRelativePath(trimmed);
1379
+ case "external":
1380
+ return trimmed;
1381
+ default:
1382
+ return trimmed;
1383
+ }
1384
+ }, [href, linkType]);
1385
+ const target = React4.useMemo(() => {
1386
+ switch (linkType) {
1387
+ case "external":
1388
+ return "_blank";
1389
+ case "internal":
1390
+ return "_self";
1391
+ case "mailto":
1392
+ case "tel":
1393
+ return void 0;
1394
+ default:
1395
+ return void 0;
1396
+ }
1397
+ }, [linkType]);
1398
+ const rel = React4.useMemo(() => {
1399
+ if (linkType === "external") {
1400
+ return "noopener noreferrer";
2076
1401
  }
1402
+ return void 0;
1403
+ }, [linkType]);
1404
+ const isExternal = linkType === "external";
1405
+ const isInternal = linkType === "internal";
1406
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
1407
+ const handleClick = React4.useCallback(
1408
+ (event) => {
1409
+ if (onClick) {
1410
+ try {
1411
+ onClick(event);
1412
+ } catch (error) {
1413
+ console.error("Error in user onClick handler:", error);
1414
+ }
1415
+ }
1416
+ if (event.defaultPrevented) {
1417
+ return;
1418
+ }
1419
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
1420
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
1421
+ if (typeof window !== "undefined") {
1422
+ const handler = window.__opensiteNavigationHandler;
1423
+ if (typeof handler === "function") {
1424
+ try {
1425
+ const handled = handler(normalizedHref, event.nativeEvent || event);
1426
+ if (handled !== false) {
1427
+ event.preventDefault();
1428
+ }
1429
+ } catch (error) {
1430
+ console.error("Error in navigation handler:", error);
1431
+ }
1432
+ }
1433
+ }
1434
+ }
1435
+ },
1436
+ [onClick, shouldUseRouter, normalizedHref]
2077
1437
  );
1438
+ return {
1439
+ linkType,
1440
+ normalizedHref,
1441
+ target,
1442
+ rel,
1443
+ isExternal,
1444
+ isInternal,
1445
+ shouldUseRouter,
1446
+ handleClick
1447
+ };
2078
1448
  }
2079
- function CardDescription({ className, ...props }) {
2080
- return /* @__PURE__ */ jsx(
2081
- "div",
2082
- {
2083
- "data-slot": "card-description",
2084
- className: cn("text-muted-foreground text-sm", className),
2085
- ...props
1449
+ var Pressable = React4.forwardRef(
1450
+ ({
1451
+ children,
1452
+ className,
1453
+ href,
1454
+ onClick,
1455
+ variant,
1456
+ size,
1457
+ asButton = false,
1458
+ fallbackComponentType = "span",
1459
+ componentType,
1460
+ "aria-label": ariaLabel,
1461
+ "aria-describedby": ariaDescribedby,
1462
+ id,
1463
+ ...props
1464
+ }, ref) => {
1465
+ const navigation = useNavigation({ href, onClick });
1466
+ const {
1467
+ normalizedHref,
1468
+ target,
1469
+ rel,
1470
+ linkType,
1471
+ isInternal,
1472
+ isExternal,
1473
+ handleClick
1474
+ } = navigation;
1475
+ const shouldRenderLink = normalizedHref && linkType !== "none";
1476
+ const shouldRenderButton = !shouldRenderLink && onClick;
1477
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
1478
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
1479
+ const shouldApplyButtonStyles = asButton || variant || size;
1480
+ const combinedClassName = cn(
1481
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
1482
+ className
1483
+ );
1484
+ const dataProps = Object.fromEntries(
1485
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
1486
+ );
1487
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
1488
+ "data-slot": "button",
1489
+ "data-variant": variant ?? "default",
1490
+ "data-size": size ?? "default"
1491
+ } : {};
1492
+ const commonProps = {
1493
+ className: combinedClassName,
1494
+ onClick: handleClick,
1495
+ "aria-label": ariaLabel,
1496
+ "aria-describedby": ariaDescribedby,
1497
+ id,
1498
+ ...dataProps,
1499
+ ...buttonDataAttributes
1500
+ };
1501
+ if (finalComponentType === "a" && shouldRenderLink) {
1502
+ return /* @__PURE__ */ jsx(
1503
+ "a",
1504
+ {
1505
+ ref,
1506
+ href: normalizedHref,
1507
+ target,
1508
+ rel,
1509
+ ...commonProps,
1510
+ ...props,
1511
+ children
1512
+ }
1513
+ );
2086
1514
  }
2087
- );
2088
- }
2089
- function CardContent({ className, ...props }) {
2090
- return /* @__PURE__ */ jsx(
2091
- "div",
2092
- {
2093
- "data-slot": "card-content",
2094
- className: cn("px-6", className),
2095
- ...props
1515
+ if (finalComponentType === "button") {
1516
+ return /* @__PURE__ */ jsx(
1517
+ "button",
1518
+ {
1519
+ ref,
1520
+ type: props.type || "button",
1521
+ ...commonProps,
1522
+ ...props,
1523
+ children
1524
+ }
1525
+ );
2096
1526
  }
2097
- );
2098
- }
2099
- function CardFooter({ className, ...props }) {
2100
- return /* @__PURE__ */ jsx(
2101
- "div",
2102
- {
2103
- "data-slot": "card-footer",
2104
- className: cn("flex items-center px-6 [.border-t]:pt-6", className),
2105
- ...props
1527
+ if (finalComponentType === "div") {
1528
+ return /* @__PURE__ */ jsx(
1529
+ "div",
1530
+ {
1531
+ ref,
1532
+ ...commonProps,
1533
+ children
1534
+ }
1535
+ );
2106
1536
  }
2107
- );
2108
- }
2109
- var badgeVariants = cva(
2110
- "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
2111
- {
2112
- variants: {
2113
- variant: {
2114
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
2115
- secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
2116
- destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
2117
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
1537
+ return /* @__PURE__ */ jsx(
1538
+ "span",
1539
+ {
1540
+ ref,
1541
+ ...commonProps,
1542
+ children
2118
1543
  }
2119
- },
2120
- defaultVariants: {
2121
- variant: "default"
2122
- }
1544
+ );
2123
1545
  }
2124
1546
  );
2125
- function Badge({
2126
- className,
2127
- variant,
2128
- asChild = false,
2129
- ...props
2130
- }) {
2131
- const Comp = asChild ? Slot : "span";
2132
- return /* @__PURE__ */ jsx(
2133
- Comp,
2134
- {
2135
- "data-slot": "badge",
2136
- className: cn(badgeVariants({ variant }), className),
2137
- ...props
2138
- }
2139
- );
2140
- }
2141
- function Popover({
2142
- ...props
2143
- }) {
2144
- return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
2145
- }
2146
- function PopoverTrigger({
2147
- ...props
2148
- }) {
2149
- return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
2150
- }
2151
- function PopoverContent({
2152
- className,
2153
- align = "center",
2154
- sideOffset = 4,
2155
- ...props
2156
- }) {
2157
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2158
- PopoverPrimitive.Content,
2159
- {
2160
- "data-slot": "popover-content",
2161
- align,
2162
- sideOffset,
2163
- className: cn(
2164
- "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
2165
- className
2166
- ),
2167
- ...props
2168
- }
2169
- ) });
2170
- }
2171
- function StarRating({
2172
- rating,
2173
- size = 18,
2174
- className
2175
- }) {
2176
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
2177
- DynamicIcon,
2178
- {
2179
- name: "icon-park-solid/star",
2180
- size,
2181
- className: cn(
2182
- star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
2183
- )
2184
- },
2185
- star
2186
- )) });
2187
- }
1547
+ Pressable.displayName = "Pressable";
2188
1548
  var BUTTON_SIZES = {
2189
1549
  sm: { buttonSize: "size-8", iconSize: 16 },
2190
1550
  md: { buttonSize: "size-10", iconSize: 20 },
@@ -2276,7 +1636,7 @@ var platformIconMap = {
2276
1636
  dribbble: "cib/dribbble",
2277
1637
  unknown: "icon-park-solid/circular-connection"
2278
1638
  };
2279
- var SocialLinkIcon = React6.forwardRef(
1639
+ var SocialLinkIcon = React4.forwardRef(
2280
1640
  ({
2281
1641
  platformName,
2282
1642
  label,
@@ -2290,16 +1650,16 @@ var SocialLinkIcon = React6.forwardRef(
2290
1650
  ...pressableProps
2291
1651
  }, ref) => {
2292
1652
  const platform = usePlatformFromUrl(href);
2293
- const smartPlatformName = React6.useMemo(() => {
1653
+ const smartPlatformName = React4.useMemo(() => {
2294
1654
  return platform || platformName;
2295
1655
  }, [platform, platformName]);
2296
- const iconName = React6.useMemo(() => {
1656
+ const iconName = React4.useMemo(() => {
2297
1657
  return iconNameOverride || platformIconMap[smartPlatformName];
2298
1658
  }, [iconNameOverride, smartPlatformName]);
2299
- const accessibleLabel = React6.useMemo(() => {
1659
+ const accessibleLabel = React4.useMemo(() => {
2300
1660
  return label || platformName;
2301
1661
  }, [label, platformName]);
2302
- const icon = React6.useMemo(() => {
1662
+ const icon = React4.useMemo(() => {
2303
1663
  return /* @__PURE__ */ jsx(
2304
1664
  DynamicIcon,
2305
1665
  {
@@ -2379,12 +1739,12 @@ function TextInner({ as, className, children, ...props }, ref) {
2379
1739
  const Component = as || "span";
2380
1740
  return /* @__PURE__ */ jsx(Component, { ref, className: cn(className), ...props, children });
2381
1741
  }
2382
- var Text = React6.forwardRef(TextInner);
1742
+ var Text = React4.forwardRef(TextInner);
2383
1743
  Text.displayName = "Text";
2384
1744
  function isContentTextItem(item) {
2385
- return item !== null && typeof item === "object" && !React6.isValidElement(item) && "_type" in item && item._type === "text";
1745
+ return item !== null && typeof item === "object" && !React4.isValidElement(item) && "_type" in item && item._type === "text";
2386
1746
  }
2387
- var ContentGroup = React6.forwardRef(
1747
+ var ContentGroup = React4.forwardRef(
2388
1748
  ({ items, className, children, ...props }, ref) => {
2389
1749
  const hasContent = items && items.length > 0;
2390
1750
  if (!hasContent) {
@@ -2397,10 +1757,10 @@ var ContentGroup = React6.forwardRef(
2397
1757
  return /* @__PURE__ */ jsx(Text, { ...textProps }, idx);
2398
1758
  }
2399
1759
  const reactNode = item;
2400
- if (React6.isValidElement(reactNode)) {
2401
- return React6.cloneElement(reactNode, { key: reactNode.key ?? idx });
1760
+ if (React4.isValidElement(reactNode)) {
1761
+ return React4.cloneElement(reactNode, { key: reactNode.key ?? idx });
2402
1762
  }
2403
- return /* @__PURE__ */ jsx(React6.Fragment, { children: reactNode }, idx);
1763
+ return /* @__PURE__ */ jsx(React4.Fragment, { children: reactNode }, idx);
2404
1764
  }),
2405
1765
  children
2406
1766
  ] });
@@ -2925,7 +2285,7 @@ function AboutExpandableValues({
2925
2285
  pattern,
2926
2286
  patternOpacity
2927
2287
  }) {
2928
- const [expandedValue, setExpandedValue] = React6.useState(null);
2288
+ const [expandedValue, setExpandedValue] = React4.useState(null);
2929
2289
  const toggleExpand = useCallback((id) => {
2930
2290
  setExpandedValue((prev) => prev === id ? null : id);
2931
2291
  }, []);
@@ -3161,7 +2521,7 @@ function CommunityInitiatives({
3161
2521
  pattern,
3162
2522
  patternOpacity
3163
2523
  }) {
3164
- const [activeCategory, setActiveCategory] = React6.useState(
2524
+ const [activeCategory, setActiveCategory] = React4.useState(
3165
2525
  categories?.[0]?.id || ""
3166
2526
  );
3167
2527
  const currentCategory = categories?.find((category) => category.id === activeCategory) || categories?.[0];
@@ -3425,7 +2785,7 @@ function AboutCultureTabs({
3425
2785
  patternOpacity
3426
2786
  }) {
3427
2787
  const resolvedAspects = aspects ?? [];
3428
- const [activeTab, setActiveTab] = React6.useState(
2788
+ const [activeTab, setActiveTab] = React4.useState(
3429
2789
  resolvedAspects[0]?.id || ""
3430
2790
  );
3431
2791
  const headerItems = useMemo(() => {
@@ -3958,7 +3318,7 @@ function BannerDeliveryCountdown({
3958
3318
  }, [prefixText, timerContent, middleText, deliveryDateContent]);
3959
3319
  return /* @__PURE__ */ jsx(Section, { background, spacing: "none", className: cn("bg-accent text-accent-foreground", className), children: /* @__PURE__ */ jsx("div", { className: cn("container py-2.5", containerClassName), children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-wrap items-center justify-center gap-3 text-sm", contentClassName), children: /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2", messageClassName), children: [
3960
3320
  iconContent,
3961
- messageParts.length > 0 && /* @__PURE__ */ jsx("span", { children: messageParts.map((part, index) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
3321
+ messageParts.length > 0 && /* @__PURE__ */ jsx("span", { children: messageParts.map((part, index) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
3962
3322
  index > 0 ? " " : null,
3963
3323
  part
3964
3324
  ] }, index)) })
@@ -5229,8 +4589,8 @@ var BrandAttribution = ({
5229
4589
  }
5230
4590
  const { prefix = "", anchorText, href, suffix = "" } = options[optionIndex];
5231
4591
  const ContainerEl = variant;
5232
- const [trackedHref, setTrackedHref] = React6.useState(href);
5233
- React6.useEffect(() => {
4592
+ const [trackedHref, setTrackedHref] = React4.useState(href);
4593
+ React4.useEffect(() => {
5234
4594
  setTrackedHref(buildTrackedHref(href));
5235
4595
  }, [href]);
5236
4596
  return /* @__PURE__ */ jsxs(ContainerEl, { className: containerClassName, children: [
@@ -5350,7 +4710,7 @@ function FooterSocialNewsletter({
5350
4710
  patternOpacity,
5351
4711
  optixFlowConfig
5352
4712
  }) {
5353
- const renderForm = React6.useMemo(() => {
4713
+ const renderForm = React4.useMemo(() => {
5354
4714
  if (!formEngineSetup) return null;
5355
4715
  const action = {
5356
4716
  variant: "default",
@@ -5639,7 +4999,7 @@ function FooterSimpleCentered({
5639
4999
  ]);
5640
5000
  const bottomLinksContent = useMemo(() => {
5641
5001
  if (!bottomLinks || bottomLinks.length === 0) return null;
5642
- return bottomLinks.map((link, idx) => /* @__PURE__ */ jsx(React6.Fragment, { children: /* @__PURE__ */ jsx(
5002
+ return bottomLinks.map((link, idx) => /* @__PURE__ */ jsx(React4.Fragment, { children: /* @__PURE__ */ jsx(
5643
5003
  Pressable,
5644
5004
  {
5645
5005
  href: link.href,
@@ -6986,7 +6346,7 @@ function FooterNewsletterMinimal({
6986
6346
  buttonAction,
6987
6347
  formSlot
6988
6348
  }) {
6989
- const navLinksContent = React6.useMemo(() => {
6349
+ const navLinksContent = React4.useMemo(() => {
6990
6350
  if (!navLinks || navLinks.length === 0) return null;
6991
6351
  return navLinks.map((item, idx) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
6992
6352
  Pressable,
@@ -6997,7 +6357,7 @@ function FooterNewsletterMinimal({
6997
6357
  }
6998
6358
  ) }, idx));
6999
6359
  }, [navLinks, navLinkClassName]);
7000
- const socialLinksContent = React6.useMemo(() => {
6360
+ const socialLinksContent = React4.useMemo(() => {
7001
6361
  if (!socialLinks || socialLinks.length === 0) return null;
7002
6362
  return socialLinks.map((item, idx) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
7003
6363
  SocialLinkIcon,
@@ -7013,7 +6373,7 @@ function FooterNewsletterMinimal({
7013
6373
  }
7014
6374
  ) }, idx));
7015
6375
  }, [socialLinks, socialLinkClassName]);
7016
- const footerLinksContent = React6.useMemo(() => {
6376
+ const footerLinksContent = React4.useMemo(() => {
7017
6377
  if (!footerLinks || footerLinks.length === 0) return null;
7018
6378
  return footerLinks.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
7019
6379
  Pressable,
@@ -7027,7 +6387,7 @@ function FooterNewsletterMinimal({
7027
6387
  }
7028
6388
  ) }, item.label));
7029
6389
  }, [footerLinks, footerLinkClassName]);
7030
- const renderForm = React6.useMemo(() => {
6390
+ const renderForm = React4.useMemo(() => {
7031
6391
  if (formSlot) return formSlot;
7032
6392
  if (!formEngineSetup) return null;
7033
6393
  const defaultButtonAction = {
@@ -7584,4 +6944,4 @@ var useResponsiveLayout = ({
7584
6944
  return { responsiveClassName };
7585
6945
  };
7586
6946
 
7587
- export { AboutCultureTabs, AboutExpandableValues, AboutMissionPrinciples, AboutSplitHero, AlternatingBlocks, AnimatedDialog, Badge, BannerAnnouncementDismissible, BannerCountdownSale, BannerDeliveryCountdown, BannerEventPromo, BannerFloatingOffer, BannerGdprRights, BannerPrivacyNotice, BannerPromoCta, BannerSocialFollow, BannerSurveyIncentive, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CarouselPagination, CommunityInitiatives, Container, DynamicIcon, FooterAnimatedSocial, FooterBackgroundCard, FooterBrandDescription, FooterContactCard, FooterCtaBanner, FooterCtaSocial, FooterLinksGrid, FooterNavSocial, FooterNewsletterGrid, FooterNewsletterMinimal, FooterSimpleCentered, FooterSocialApps, FooterSocialNewsletter, GeoMap, ImageSlider, MediaHoverCtas, PageHeroBanner, PaymentPlatformIcon, Popover, PopoverContent, PopoverTrigger, Pressable, Section, SocialLinkIcon, StarRating, cn, getAccentColor, getBorderColor, getNestedCardBg, getNestedCardTextColor, getTextColor, useNavigation, useResponsiveLayout };
6947
+ export { AboutCultureTabs, AboutExpandableValues, AboutMissionPrinciples, AboutSplitHero, AlternatingBlocks, AnimatedDialog, Badge, BannerAnnouncementDismissible, BannerCountdownSale, BannerDeliveryCountdown, BannerEventPromo, BannerFloatingOffer, BannerGdprRights, BannerPrivacyNotice, BannerPromoCta, BannerSocialFollow, BannerSurveyIncentive, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CarouselPagination, CommunityInitiatives, Container, DynamicIcon, FooterAnimatedSocial, FooterBackgroundCard, FooterBrandDescription, FooterContactCard, FooterCtaBanner, FooterCtaSocial, FooterLinksGrid, FooterNavSocial, FooterNewsletterGrid, FooterNewsletterMinimal, FooterSimpleCentered, FooterSocialApps, FooterSocialNewsletter, ImageSlider, MediaHoverCtas, PageHeroBanner, PaymentPlatformIcon, Popover, PopoverContent, PopoverTrigger, Pressable, Section, SocialLinkIcon, StarRating, cn, getAccentColor, getBorderColor, getNestedCardBg, getNestedCardTextColor, getTextColor, useNavigation, useResponsiveLayout };