@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
@@ -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';
@@ -60,7 +59,7 @@ var maxWidthStyles = {
60
59
  "4xl": "max-w-[1536px]",
61
60
  full: "max-w-full"
62
61
  };
63
- var Container = React6__default.forwardRef(
62
+ var Container = React4__default.forwardRef(
64
63
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
65
64
  const Component = as;
66
65
  return /* @__PURE__ */ jsx(
@@ -366,7 +365,7 @@ var spacingStyles = {
366
365
  };
367
366
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
368
367
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
369
- var Section = React6__default.forwardRef(
368
+ var Section = React4__default.forwardRef(
370
369
  ({
371
370
  id,
372
371
  title,
@@ -427,1130 +426,65 @@ var Section = React6__default.forwardRef(
427
426
  }
428
427
  );
429
428
  Section.displayName = "Section";
430
- function normalizePhoneNumber(input) {
431
- const trimmed = input.trim();
432
- if (trimmed.toLowerCase().startsWith("tel:")) {
433
- return trimmed;
434
- }
435
- const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
436
- if (match) {
437
- const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
438
- const extension = match[3];
439
- const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
440
- const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
441
- return `tel:${withExtension}`;
442
- }
443
- const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
444
- return `tel:${cleaned}`;
445
- }
446
- function normalizeEmail(input) {
447
- const trimmed = input.trim();
448
- if (trimmed.toLowerCase().startsWith("mailto:")) {
449
- return trimmed;
450
- }
451
- return `mailto:${trimmed}`;
452
- }
453
- function isEmail(input) {
454
- const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
455
- return emailRegex.test(input.trim());
456
- }
457
- function isPhoneNumber(input) {
458
- const trimmed = input.trim();
459
- if (trimmed.toLowerCase().startsWith("tel:")) {
460
- return true;
461
- }
462
- const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
463
- return phoneRegex.test(trimmed);
464
- }
465
- function isInternalUrl(href) {
466
- if (typeof window === "undefined") {
467
- return href.startsWith("/") && !href.startsWith("//");
468
- }
469
- const trimmed = href.trim();
470
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
471
- return true;
472
- }
473
- try {
474
- const url = new URL(trimmed, window.location.href);
475
- const currentOrigin = window.location.origin;
476
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
477
- return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
478
- } catch {
479
- return false;
480
- }
481
- }
482
- function toRelativePath(href) {
483
- if (typeof window === "undefined") {
484
- return href;
485
- }
486
- const trimmed = href.trim();
487
- if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
488
- return trimmed;
489
- }
490
- try {
491
- const url = new URL(trimmed, window.location.href);
492
- const currentOrigin = window.location.origin;
493
- const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
494
- if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
495
- return url.pathname + url.search + url.hash;
496
- }
497
- } catch {
498
- }
499
- return trimmed;
500
- }
501
- function useNavigation({
502
- href,
503
- onClick
504
- } = {}) {
505
- const linkType = React6.useMemo(() => {
506
- if (!href || href.trim() === "") {
507
- return onClick ? "none" : "none";
508
- }
509
- const trimmed = href.trim();
510
- if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
511
- return "mailto";
512
- }
513
- if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
514
- return "tel";
515
- }
516
- if (isInternalUrl(trimmed)) {
517
- return "internal";
518
- }
519
- try {
520
- new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
521
- return "external";
522
- } catch {
523
- return "internal";
524
- }
525
- }, [href, onClick]);
526
- const normalizedHref = React6.useMemo(() => {
527
- if (!href || href.trim() === "") {
528
- return void 0;
529
- }
530
- const trimmed = href.trim();
531
- switch (linkType) {
532
- case "tel":
533
- return normalizePhoneNumber(trimmed);
534
- case "mailto":
535
- return normalizeEmail(trimmed);
536
- case "internal":
537
- return toRelativePath(trimmed);
538
- case "external":
539
- return trimmed;
540
- default:
541
- return trimmed;
542
- }
543
- }, [href, linkType]);
544
- const target = React6.useMemo(() => {
545
- switch (linkType) {
546
- case "external":
547
- return "_blank";
548
- case "internal":
549
- return "_self";
550
- case "mailto":
551
- case "tel":
552
- return void 0;
553
- default:
554
- return void 0;
429
+ var sizeStyles = {
430
+ sm: "max-w-md",
431
+ md: "max-w-2xl",
432
+ lg: "max-w-4xl",
433
+ xl: "max-w-5xl",
434
+ full: "max-w-7xl",
435
+ compact: "max-w-[700px]"
436
+ };
437
+ var dialogTransition = {
438
+ duration: 0.35,
439
+ ease: [0.16, 1, 0.3, 1]
440
+ };
441
+ function AnimatedDialog({
442
+ open,
443
+ onOpenChange,
444
+ title,
445
+ eyebrow,
446
+ description,
447
+ children,
448
+ header,
449
+ footer,
450
+ size = "lg",
451
+ className,
452
+ contentClassName,
453
+ featuredMediaHeader
454
+ }) {
455
+ const titleId = useId();
456
+ const descriptionId = useId();
457
+ const containerRef = useRef(null);
458
+ useOnClickOutside(containerRef, () => {
459
+ if (open) {
460
+ onOpenChange(false);
555
461
  }
556
- }, [linkType]);
557
- const rel = React6.useMemo(() => {
558
- if (linkType === "external") {
559
- return "noopener noreferrer";
462
+ });
463
+ useEffect(() => {
464
+ if (!open) {
465
+ return;
560
466
  }
561
- return void 0;
562
- }, [linkType]);
563
- const isExternal = linkType === "external";
564
- const isInternal = linkType === "internal";
565
- const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
566
- const handleClick = React6.useCallback(
567
- (event) => {
568
- if (onClick) {
569
- try {
570
- onClick(event);
571
- } catch (error) {
572
- console.error("Error in user onClick handler:", error);
573
- }
574
- }
575
- if (event.defaultPrevented) {
576
- return;
467
+ const onKeyDown = (event) => {
468
+ if (event.key === "Escape") {
469
+ onOpenChange(false);
577
470
  }
578
- if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
579
- !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
580
- if (typeof window !== "undefined") {
581
- const handler = window.__opensiteNavigationHandler;
582
- if (typeof handler === "function") {
583
- try {
584
- const handled = handler(normalizedHref, event.nativeEvent || event);
585
- if (handled !== false) {
586
- event.preventDefault();
587
- }
588
- } catch (error) {
589
- console.error("Error in navigation handler:", error);
590
- }
591
- }
592
- }
593
- }
594
- },
595
- [onClick, shouldUseRouter, normalizedHref]
596
- );
597
- return {
598
- linkType,
599
- normalizedHref,
600
- target,
601
- rel,
602
- isExternal,
603
- isInternal,
604
- shouldUseRouter,
605
- handleClick
606
- };
607
- }
608
- var baseStyles = [
609
- // Layout
610
- "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
611
- // Typography - using CSS variables with sensible defaults
612
- "font-[var(--button-font-family,inherit)]",
613
- "font-[var(--button-font-weight,500)]",
614
- "tracking-[var(--button-letter-spacing,0)]",
615
- "leading-[var(--button-line-height,1.25)]",
616
- "[text-transform:var(--button-text-transform,none)]",
617
- "text-sm",
618
- // Border radius
619
- "rounded-[var(--button-radius,var(--radius,0.375rem))]",
620
- // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
621
- "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
622
- // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
623
- "[box-shadow:var(--button-shadow,none)]",
624
- "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
625
- // Disabled state
626
- "disabled:pointer-events-none disabled:opacity-50",
627
- // SVG handling
628
- "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
629
- // Focus styles
630
- "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
631
- // Invalid state
632
- "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
633
- ].join(" ");
634
- var buttonVariants = cva(baseStyles, {
635
- variants: {
636
- variant: {
637
- // Default (Primary) variant - full customization
638
- default: [
639
- "bg-[var(--button-default-bg,hsl(var(--primary)))]",
640
- "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
641
- "border-[length:var(--button-default-border-width,0px)]",
642
- "border-[color:var(--button-default-border,transparent)]",
643
- "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
644
- "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
645
- "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
646
- "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
647
- "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
648
- ].join(" "),
649
- // Destructive variant - full customization
650
- destructive: [
651
- "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
652
- "text-[var(--button-destructive-fg,white)]",
653
- "border-[length:var(--button-destructive-border-width,0px)]",
654
- "border-[color:var(--button-destructive-border,transparent)]",
655
- "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
656
- "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
657
- "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
658
- "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
659
- "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
660
- "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
661
- "dark:bg-destructive/60"
662
- ].join(" "),
663
- // Outline variant - full customization with proper border handling
664
- outline: [
665
- "bg-[var(--button-outline-bg,hsl(var(--background)))]",
666
- "text-[var(--button-outline-fg,inherit)]",
667
- "border-[length:var(--button-outline-border-width,1px)]",
668
- "border-[color:var(--button-outline-border,hsl(var(--border)))]",
669
- "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
670
- "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
671
- "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
672
- "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
673
- "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
674
- "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
675
- ].join(" "),
676
- // Secondary variant - full customization
677
- secondary: [
678
- "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
679
- "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
680
- "border-[length:var(--button-secondary-border-width,0px)]",
681
- "border-[color:var(--button-secondary-border,transparent)]",
682
- "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
683
- "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
684
- "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
685
- "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
686
- "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
687
- ].join(" "),
688
- // Ghost variant - full customization
689
- ghost: [
690
- "bg-[var(--button-ghost-bg,transparent)]",
691
- "text-[var(--button-ghost-fg,inherit)]",
692
- "border-[length:var(--button-ghost-border-width,0px)]",
693
- "border-[color:var(--button-ghost-border,transparent)]",
694
- "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
695
- "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
696
- "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
697
- "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
698
- "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
699
- "dark:hover:bg-accent/50"
700
- ].join(" "),
701
- // Link variant - full customization
702
- link: [
703
- "bg-[var(--button-link-bg,transparent)]",
704
- "text-[var(--button-link-fg,hsl(var(--primary)))]",
705
- "border-[length:var(--button-link-border-width,0px)]",
706
- "border-[color:var(--button-link-border,transparent)]",
707
- "[box-shadow:var(--button-link-shadow,none)]",
708
- "hover:bg-[var(--button-link-hover-bg,transparent)]",
709
- "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
710
- "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
711
- "underline-offset-4 hover:underline"
712
- ].join(" ")
713
- },
714
- size: {
715
- default: [
716
- "h-[var(--button-height-md,2.25rem)]",
717
- "px-[var(--button-padding-x-md,1rem)]",
718
- "py-[var(--button-padding-y-md,0.5rem)]",
719
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
720
- ].join(" "),
721
- sm: [
722
- "h-[var(--button-height-sm,2rem)]",
723
- "px-[var(--button-padding-x-sm,0.75rem)]",
724
- "py-[var(--button-padding-y-sm,0.25rem)]",
725
- "gap-1.5",
726
- "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
727
- ].join(" "),
728
- md: [
729
- "h-[var(--button-height-md,2.25rem)]",
730
- "px-[var(--button-padding-x-md,1rem)]",
731
- "py-[var(--button-padding-y-md,0.5rem)]",
732
- "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
733
- ].join(" "),
734
- lg: [
735
- "h-[var(--button-height-lg,2.5rem)]",
736
- "px-[var(--button-padding-x-lg,1.5rem)]",
737
- "py-[var(--button-padding-y-lg,0.5rem)]",
738
- "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
739
- ].join(" "),
740
- icon: "size-[var(--button-height-md,2.25rem)]",
741
- "icon-sm": "size-[var(--button-height-sm,2rem)]",
742
- "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
743
- }
744
- },
745
- defaultVariants: {
746
- variant: "default",
747
- size: "default"
748
- }
749
- });
750
- var Pressable = React6.forwardRef(
751
- ({
752
- children,
753
- className,
754
- href,
755
- onClick,
756
- variant,
757
- size,
758
- asButton = false,
759
- fallbackComponentType = "span",
760
- componentType,
761
- "aria-label": ariaLabel,
762
- "aria-describedby": ariaDescribedby,
763
- id,
764
- ...props
765
- }, ref) => {
766
- const navigation = useNavigation({ href, onClick });
767
- const {
768
- normalizedHref,
769
- target,
770
- rel,
771
- linkType,
772
- isInternal,
773
- handleClick
774
- } = navigation;
775
- const shouldRenderLink = normalizedHref && linkType !== "none";
776
- const shouldRenderButton = !shouldRenderLink && onClick;
777
- const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
778
- const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
779
- const shouldApplyButtonStyles = asButton || variant || size;
780
- const combinedClassName = cn(
781
- shouldApplyButtonStyles && buttonVariants({ variant, size }),
782
- className
783
- );
784
- const dataProps = Object.fromEntries(
785
- Object.entries(props).filter(([key]) => key.startsWith("data-"))
786
- );
787
- const buttonDataAttributes = shouldApplyButtonStyles ? {
788
- "data-slot": "button",
789
- "data-variant": variant ?? "default",
790
- "data-size": size ?? "default"
791
- } : {};
792
- const commonProps = {
793
- className: combinedClassName,
794
- onClick: handleClick,
795
- "aria-label": ariaLabel,
796
- "aria-describedby": ariaDescribedby,
797
- id,
798
- ...dataProps,
799
- ...buttonDataAttributes
800
- };
801
- if (finalComponentType === "a" && shouldRenderLink) {
802
- return /* @__PURE__ */ jsx(
803
- "a",
804
- {
805
- ref,
806
- href: normalizedHref,
807
- target,
808
- rel,
809
- ...commonProps,
810
- ...props,
811
- children
812
- }
813
- );
814
- }
815
- if (finalComponentType === "button") {
816
- return /* @__PURE__ */ jsx(
817
- "button",
818
- {
819
- ref,
820
- type: props.type || "button",
821
- ...commonProps,
822
- ...props,
823
- children
824
- }
825
- );
826
- }
827
- if (finalComponentType === "div") {
828
- return /* @__PURE__ */ jsx(
829
- "div",
830
- {
831
- ref,
832
- ...commonProps,
833
- children
834
- }
835
- );
836
- }
837
- return /* @__PURE__ */ jsx(
838
- "span",
839
- {
840
- ref,
841
- ...commonProps,
842
- children
843
- }
844
- );
845
- }
846
- );
847
- Pressable.displayName = "Pressable";
848
- var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
849
- var DynamicIcon = React6.memo(function DynamicIcon2({
850
- apiKey,
851
- ...props
852
- }) {
853
- return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
854
- });
855
- DynamicIcon.displayName = "DynamicIcon";
856
- var PANEL_POSITION_CLASS = {
857
- "top-left": "left-4 top-4",
858
- "top-right": "right-4 top-4",
859
- "bottom-left": "bottom-4 left-4",
860
- "bottom-right": "bottom-4 right-4"
861
- };
862
- var DEFAULT_VIEW_STATE = {
863
- latitude: 39.5,
864
- longitude: -98.35,
865
- zoom: 3
866
- };
867
- var VIDEO_FILE_EXTENSION_REGEX = /\.(mp4|webm|ogg|mov|m4v|m3u8)(\?.*)?$/i;
868
- function resolveMediaType(item) {
869
- if (item.type) {
870
- return item.type;
871
- }
872
- return VIDEO_FILE_EXTENSION_REGEX.test(item.src) ? "video" : "image";
873
- }
874
- function normalizeId(value, fallback) {
875
- if (value === null || value === void 0 || value === "") {
876
- return fallback;
877
- }
878
- return String(value);
879
- }
880
- function buildClusterCenter(markers) {
881
- if (!markers.length) {
882
- return null;
883
- }
884
- const total = markers.reduce(
885
- (accumulator, marker) => ({
886
- latitude: accumulator.latitude + marker.latitude,
887
- longitude: accumulator.longitude + marker.longitude
888
- }),
889
- { latitude: 0, longitude: 0 }
890
- );
891
- return {
892
- latitude: total.latitude / markers.length,
893
- longitude: total.longitude / markers.length
894
- };
895
- }
896
- function resolveActionKey(action, index) {
897
- if (typeof action.label === "string" && action.label.trim().length > 0) {
898
- return `label:${action.label}:${index}`;
899
- }
900
- if (action.href) {
901
- return `href:${action.href}:${index}`;
902
- }
903
- return `action:${index}`;
904
- }
905
- function MarkerActions({ actions }) {
906
- if (!actions || actions.length === 0) {
907
- return null;
908
- }
909
- return /* @__PURE__ */ jsx("div", { className: "mt-4 flex flex-wrap gap-2", children: actions.map((action, index) => {
910
- const {
911
- label,
912
- icon,
913
- iconAfter,
914
- children,
915
- href,
916
- onClick,
917
- className: actionClassName,
918
- variant,
919
- size,
920
- asButton,
921
- ...rest
922
- } = action;
923
- return /* @__PURE__ */ jsx(
924
- Pressable,
925
- {
926
- href,
927
- onClick,
928
- variant: variant ?? (index === 0 ? "default" : "outline"),
929
- size: size ?? "sm",
930
- asButton: asButton ?? true,
931
- className: cn("inline-flex items-center gap-2", actionClassName),
932
- ...rest,
933
- children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
934
- icon,
935
- label,
936
- iconAfter
937
- ] })
938
- },
939
- resolveActionKey(action, index)
940
- );
941
- }) });
942
- }
943
- function MarkerMediaCarousel({
944
- mediaItems,
945
- optixFlowConfig
946
- }) {
947
- const [activeIndex, setActiveIndex] = React6.useState(0);
948
- const totalItems = mediaItems.length;
949
- const mediaResetKey = React6.useMemo(
950
- () => mediaItems.map((item, index) => {
951
- const itemId = normalizeId(item.id, `media-${index}`);
952
- return `${itemId}:${item.src}:${item.type ?? ""}:${item.poster ?? ""}`;
953
- }).join("|"),
954
- [mediaItems]
955
- );
956
- const activeItemIndex = Math.min(activeIndex, Math.max(0, totalItems - 1));
957
- React6.useEffect(() => {
958
- setActiveIndex(0);
959
- }, [mediaResetKey]);
960
- const activeMediaItem = mediaItems[activeItemIndex];
961
- const mediaType = resolveMediaType(activeMediaItem);
962
- return /* @__PURE__ */ jsxs("div", { className: "relative border-b border-border/60 bg-muted/40", children: [
963
- /* @__PURE__ */ jsx("div", { className: "relative h-44 w-full overflow-hidden", children: mediaType === "video" ? /* @__PURE__ */ jsx(
964
- "video",
965
- {
966
- className: "h-full w-full object-cover",
967
- controls: true,
968
- preload: "metadata",
969
- poster: activeMediaItem.poster,
970
- children: /* @__PURE__ */ jsx("source", { src: activeMediaItem.src })
971
- }
972
- ) : /* @__PURE__ */ jsx(
973
- Img,
974
- {
975
- src: activeMediaItem.src,
976
- alt: activeMediaItem.alt ?? "Map marker media",
977
- className: "h-full w-full object-cover",
978
- loading: "eager",
979
- optixFlowConfig
980
- }
981
- ) }),
982
- totalItems > 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
983
- /* @__PURE__ */ jsx(
984
- "button",
985
- {
986
- type: "button",
987
- "aria-label": "Show previous media",
988
- 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",
989
- onClick: () => {
990
- setActiveIndex(
991
- (current) => (current - 1 + totalItems) % totalItems
992
- );
993
- },
994
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-left", size: 16 })
995
- }
996
- ),
997
- /* @__PURE__ */ jsx(
998
- "button",
999
- {
1000
- type: "button",
1001
- "aria-label": "Show next media",
1002
- 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",
1003
- onClick: () => {
1004
- setActiveIndex((current) => (current + 1) % totalItems);
1005
- },
1006
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/arrow-right", size: 16 })
1007
- }
1008
- ),
1009
- /* @__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(
1010
- "button",
1011
- {
1012
- type: "button",
1013
- "aria-label": `Show media item ${index + 1}`,
1014
- className: cn(
1015
- "h-2 rounded-full transition-all",
1016
- index === activeItemIndex ? "w-6 bg-card" : "w-2 bg-card opacity-50 hover:opacity-100"
1017
- ),
1018
- onClick: () => setActiveIndex(index)
1019
- },
1020
- normalizeId(item.id, `media-dot-${index}`)
1021
- )) })
1022
- ] }) : null
1023
- ] });
1024
- }
1025
- function getMarkerTitle(marker, markerIndex) {
1026
- if (marker.title !== void 0 && marker.title !== null) {
1027
- return marker.title;
1028
- }
1029
- if (marker.label !== void 0 && marker.label !== null) {
1030
- return marker.label;
1031
- }
1032
- return `Location ${markerIndex + 1}`;
1033
- }
1034
- function GeoMap({
1035
- className,
1036
- mapWrapperClassName,
1037
- mapClassName,
1038
- panelClassName,
1039
- panelPosition = "top-left",
1040
- stadiaApiKey = "",
1041
- mapStyle = "osm-bright",
1042
- styleUrl,
1043
- mapLibreCssHref,
1044
- markers = [],
1045
- clusters = [],
1046
- viewState,
1047
- defaultViewState,
1048
- onViewStateChange,
1049
- onMapClick,
1050
- onMarkerDrag,
1051
- showNavigationControl = true,
1052
- showGeolocateControl = false,
1053
- navigationControlPosition = "top-right",
1054
- geolocateControlPosition = "top-left",
1055
- flyToOptions,
1056
- markerFocusZoom = 14,
1057
- clusterFocusZoom = 5,
1058
- selectedMarkerId,
1059
- initialSelectedMarkerId,
1060
- onSelectionChange,
1061
- clearSelectionOnMapClick = true,
1062
- mapChildren,
1063
- optixFlowConfig
1064
- }) {
1065
- const normalizedStandaloneMarkers = React6.useMemo(
1066
- () => markers.map((marker, index) => ({
1067
- ...marker,
1068
- id: normalizeId(marker.id, `marker-${index}`)
1069
- })),
1070
- [markers]
1071
- );
1072
- const normalizedClusters = React6.useMemo(() => {
1073
- const results = [];
1074
- clusters.forEach((cluster, clusterIndex) => {
1075
- const clusterId = normalizeId(cluster.id, `cluster-${clusterIndex}`);
1076
- const normalizedClusterMarkers = cluster.markers.map(
1077
- (marker, markerIndex) => ({
1078
- ...marker,
1079
- id: normalizeId(marker.id, `${clusterId}-marker-${markerIndex}`),
1080
- clusterId
1081
- })
1082
- );
1083
- const clusterCenter = cluster.latitude !== void 0 && cluster.longitude !== void 0 ? { latitude: cluster.latitude, longitude: cluster.longitude } : buildClusterCenter(normalizedClusterMarkers);
1084
- if (!clusterCenter) {
1085
- return;
1086
- }
1087
- results.push({
1088
- ...cluster,
1089
- id: clusterId,
1090
- latitude: clusterCenter.latitude,
1091
- longitude: clusterCenter.longitude,
1092
- markers: normalizedClusterMarkers
1093
- });
1094
- });
1095
- return results;
1096
- }, [clusters]);
1097
- const markerLookup = React6.useMemo(() => {
1098
- const lookup = /* @__PURE__ */ new Map();
1099
- normalizedStandaloneMarkers.forEach((marker) => {
1100
- lookup.set(marker.id, marker);
1101
- });
1102
- normalizedClusters.forEach((cluster) => {
1103
- cluster.markers.forEach((marker) => {
1104
- lookup.set(marker.id, marker);
1105
- });
1106
- });
1107
- return lookup;
1108
- }, [normalizedClusters, normalizedStandaloneMarkers]);
1109
- const clusterLookup = React6.useMemo(() => {
1110
- const lookup = /* @__PURE__ */ new Map();
1111
- normalizedClusters.forEach((cluster) => {
1112
- lookup.set(cluster.id, cluster);
1113
- });
1114
- return lookup;
1115
- }, [normalizedClusters]);
1116
- const firstCoordinate = React6.useMemo(() => {
1117
- if (normalizedStandaloneMarkers.length > 0) {
1118
- const firstStandaloneMarker = normalizedStandaloneMarkers[0];
1119
- return {
1120
- latitude: firstStandaloneMarker.latitude,
1121
- longitude: firstStandaloneMarker.longitude
1122
- };
1123
- }
1124
- if (normalizedClusters.length > 0) {
1125
- const firstCluster = normalizedClusters[0];
1126
- return {
1127
- latitude: firstCluster.latitude,
1128
- longitude: firstCluster.longitude
1129
- };
1130
- }
1131
- return {
1132
- latitude: DEFAULT_VIEW_STATE.latitude,
1133
- longitude: DEFAULT_VIEW_STATE.longitude
1134
- };
1135
- }, [normalizedClusters, normalizedStandaloneMarkers]);
1136
- const [uncontrolledViewState, setUncontrolledViewState] = React6.useState({
1137
- latitude: defaultViewState?.latitude ?? firstCoordinate.latitude,
1138
- longitude: defaultViewState?.longitude ?? firstCoordinate.longitude,
1139
- zoom: defaultViewState?.zoom ?? DEFAULT_VIEW_STATE.zoom
1140
- });
1141
- const isControlledViewState = viewState !== void 0;
1142
- const resolvedViewState = isControlledViewState ? viewState : uncontrolledViewState;
1143
- const applyViewState = React6.useCallback(
1144
- (nextState) => {
1145
- if (!isControlledViewState) {
1146
- setUncontrolledViewState((current) => {
1147
- const next = { ...current, ...nextState };
1148
- const hasChanged = current.latitude !== next.latitude || current.longitude !== next.longitude || current.zoom !== next.zoom;
1149
- return hasChanged ? next : current;
1150
- });
1151
- }
1152
- onViewStateChange?.(nextState);
1153
- },
1154
- [isControlledViewState, onViewStateChange]
1155
- );
1156
- const [selection, setSelection] = React6.useState(() => {
1157
- if (initialSelectedMarkerId !== void 0 && initialSelectedMarkerId !== null) {
1158
- return {
1159
- type: "marker",
1160
- markerId: String(initialSelectedMarkerId)
1161
- };
1162
- }
1163
- return { type: "none" };
1164
- });
1165
- React6.useEffect(() => {
1166
- if (selectedMarkerId === void 0 || selectedMarkerId === null) {
1167
- return;
1168
- }
1169
- setSelection({
1170
- type: "marker",
1171
- markerId: String(selectedMarkerId)
1172
- });
1173
- }, [selectedMarkerId]);
1174
- const selectedMarker = selection.markerId ? markerLookup.get(selection.markerId) : void 0;
1175
- const selectedCluster = selection.clusterId ? clusterLookup.get(selection.clusterId) : void 0;
1176
- React6.useEffect(() => {
1177
- if (selection.type === "marker" && selection.markerId && !selectedMarker) {
1178
- setSelection({ type: "none" });
1179
- onSelectionChange?.({ type: "none" });
1180
- }
1181
- }, [onSelectionChange, selectedMarker, selection]);
1182
- const emitSelectionChange = React6.useCallback(
1183
- (nextSelection) => {
1184
- if (nextSelection.type === "none") {
1185
- onSelectionChange?.({ type: "none" });
1186
- return;
1187
- }
1188
- if (nextSelection.type === "marker") {
1189
- const parentCluster = nextSelection.marker.clusterId ? clusterLookup.get(nextSelection.marker.clusterId) : void 0;
1190
- onSelectionChange?.({
1191
- type: "marker",
1192
- marker: nextSelection.marker,
1193
- cluster: parentCluster
1194
- });
1195
- return;
1196
- }
1197
- onSelectionChange?.({
1198
- type: "cluster",
1199
- cluster: nextSelection.cluster
1200
- });
1201
- },
1202
- [clusterLookup, onSelectionChange]
1203
- );
1204
- const selectMarker = React6.useCallback(
1205
- (marker) => {
1206
- setSelection({
1207
- type: "marker",
1208
- markerId: marker.id,
1209
- clusterId: marker.clusterId
1210
- });
1211
- applyViewState({
1212
- latitude: marker.latitude,
1213
- longitude: marker.longitude,
1214
- zoom: markerFocusZoom
1215
- });
1216
- emitSelectionChange({ type: "marker", marker });
1217
- },
1218
- [applyViewState, emitSelectionChange, markerFocusZoom]
1219
- );
1220
- const selectCluster = React6.useCallback(
1221
- (cluster) => {
1222
- setSelection({
1223
- type: "cluster",
1224
- clusterId: cluster.id
1225
- });
1226
- applyViewState({
1227
- latitude: cluster.latitude,
1228
- longitude: cluster.longitude,
1229
- zoom: clusterFocusZoom
1230
- });
1231
- emitSelectionChange({ type: "cluster", cluster });
1232
- },
1233
- [applyViewState, clusterFocusZoom, emitSelectionChange]
1234
- );
1235
- const clearSelection = React6.useCallback(() => {
1236
- setSelection({ type: "none" });
1237
- emitSelectionChange({ type: "none" });
1238
- }, [emitSelectionChange]);
1239
- const mapMarkers = React6.useMemo(() => {
1240
- const resolvedMarkers = [];
1241
- normalizedClusters.forEach((cluster) => {
1242
- const isSelected = selection.type === "cluster" && selection.clusterId === cluster.id;
1243
- resolvedMarkers.push({
1244
- id: `cluster-pin:${cluster.id}`,
1245
- latitude: cluster.latitude,
1246
- longitude: cluster.longitude,
1247
- element: () => {
1248
- const customMarkerElement = cluster.markerElement;
1249
- const markerBody = typeof customMarkerElement === "function" ? customMarkerElement({
1250
- isSelected,
1251
- count: cluster.markers.length
1252
- }) : customMarkerElement;
1253
- return /* @__PURE__ */ jsx(
1254
- "button",
1255
- {
1256
- type: "button",
1257
- className: "group cursor-pointer",
1258
- onClick: (event) => {
1259
- event.preventDefault();
1260
- event.stopPropagation();
1261
- selectCluster(cluster);
1262
- },
1263
- "aria-label": `View ${cluster.markers.length} clustered locations`,
1264
- children: markerBody ?? /* @__PURE__ */ jsx(
1265
- "span",
1266
- {
1267
- className: cn(
1268
- "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",
1269
- isSelected && "ring-4 ring-primary/30",
1270
- cluster.pinClassName
1271
- ),
1272
- style: {
1273
- backgroundColor: cluster.pinColor ?? "var(--foreground)"
1274
- },
1275
- children: cluster.markers.length
1276
- }
1277
- )
1278
- }
1279
- );
1280
- }
1281
- });
1282
- });
1283
- normalizedStandaloneMarkers.forEach((marker) => {
1284
- const isSelected = selection.type === "marker" && selection.markerId === marker.id;
1285
- const customMarkerElement = marker.markerElement;
1286
- resolvedMarkers.push({
1287
- id: marker.id,
1288
- latitude: marker.latitude,
1289
- longitude: marker.longitude,
1290
- draggable: marker.draggable,
1291
- element: () => {
1292
- const markerBody = typeof customMarkerElement === "function" ? customMarkerElement({ isSelected }) : customMarkerElement;
1293
- return /* @__PURE__ */ jsx(
1294
- "button",
1295
- {
1296
- type: "button",
1297
- className: "group cursor-pointer",
1298
- onClick: (event) => {
1299
- event.preventDefault();
1300
- event.stopPropagation();
1301
- selectMarker(marker);
1302
- },
1303
- "aria-label": typeof marker.title === "string" ? `View ${marker.title}` : "View location details",
1304
- children: markerBody ?? /* @__PURE__ */ jsx(
1305
- "span",
1306
- {
1307
- className: cn(
1308
- "inline-flex h-4 w-4 rounded-full border-2 border-white shadow-md transition-transform duration-200 group-hover:scale-110",
1309
- isSelected && "h-5 w-5 ring-4 ring-primary/30",
1310
- marker.pinClassName
1311
- ),
1312
- style: {
1313
- backgroundColor: marker.pinColor ?? "#f43f5e"
1314
- }
1315
- }
1316
- )
1317
- }
1318
- );
1319
- }
1320
- });
1321
- });
1322
- return resolvedMarkers;
1323
- }, [
1324
- normalizedClusters,
1325
- normalizedStandaloneMarkers,
1326
- selectCluster,
1327
- selectMarker,
1328
- selection
1329
- ]);
1330
- const renderMarkerPanel = () => {
1331
- if (selectedMarker) {
1332
- const markerMediaItems = selectedMarker.mediaItems ?? [];
1333
- return /* @__PURE__ */ jsxs(
1334
- "div",
1335
- {
1336
- className: cn(
1337
- "relative w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-xl border border-border bg-card text-card-foreground shadow-2xl",
1338
- panelClassName
1339
- ),
1340
- children: [
1341
- /* @__PURE__ */ jsx(
1342
- "button",
1343
- {
1344
- type: "button",
1345
- "aria-label": "Close marker details",
1346
- 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",
1347
- onClick: clearSelection,
1348
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/x", size: 16 })
1349
- }
1350
- ),
1351
- markerMediaItems.length > 0 ? /* @__PURE__ */ jsx(
1352
- MarkerMediaCarousel,
1353
- {
1354
- mediaItems: markerMediaItems,
1355
- optixFlowConfig
1356
- }
1357
- ) : null,
1358
- /* @__PURE__ */ jsxs("div", { className: "space-y-2 p-4", children: [
1359
- /* @__PURE__ */ jsx("div", { className: "flex items-start justify-between gap-3", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-1", children: [
1360
- selectedMarker.eyebrow ? /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide", children: selectedMarker.eyebrow }) : null,
1361
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold leading-tight", children: selectedMarker.title ?? selectedMarker.label ?? "Location" })
1362
- ] }) }),
1363
- selectedMarker.summary ? /* @__PURE__ */ jsx("div", { className: "text-sm leading-relaxed", children: selectedMarker.summary }) : null,
1364
- selectedMarker.locationLine ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center justify-start text-sm gap-2", children: [
1365
- /* @__PURE__ */ jsx(
1366
- DynamicIcon,
1367
- {
1368
- name: "lucide:map-pin",
1369
- className: "opacity-50",
1370
- size: 14
1371
- }
1372
- ),
1373
- typeof selectedMarker.locationLine === "string" ? /* @__PURE__ */ jsx(
1374
- Pressable,
1375
- {
1376
- href: selectedMarker.locationUrl,
1377
- className: cn(
1378
- "transition-all duration-500",
1379
- "font-medium opacity-75 hover:opacity-100",
1380
- selectedMarker.locationUrl ? "underline underline-offset-4" : ""
1381
- ),
1382
- children: selectedMarker.locationLine
1383
- }
1384
- ) : selectedMarker.locationLine
1385
- ] }) : null,
1386
- selectedMarker.hoursLine ? /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center justify-start text-sm gap-2", children: [
1387
- /* @__PURE__ */ jsx(
1388
- DynamicIcon,
1389
- {
1390
- name: "lucide:clock",
1391
- className: "opacity-50",
1392
- size: 14
1393
- }
1394
- ),
1395
- typeof selectedMarker.hoursLine === "string" ? /* @__PURE__ */ jsx("div", { className: "font-medium", children: selectedMarker.hoursLine }) : selectedMarker.hoursLine
1396
- ] }) : null,
1397
- selectedMarker.markerContentComponent ? /* @__PURE__ */ jsx("div", { className: "relative", children: selectedMarker.markerContentComponent }) : null,
1398
- /* @__PURE__ */ jsx(MarkerActions, { actions: selectedMarker.actions })
1399
- ] })
1400
- ]
1401
- }
1402
- );
1403
- }
1404
- if (selectedCluster) {
1405
- return /* @__PURE__ */ jsxs(
1406
- "div",
1407
- {
1408
- className: cn(
1409
- "relative w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-xl border border-border bg-card text-card-foreground p-4 shadow-2xl",
1410
- panelClassName
1411
- ),
1412
- children: [
1413
- /* @__PURE__ */ jsx(
1414
- "button",
1415
- {
1416
- type: "button",
1417
- "aria-label": "Close cluster details",
1418
- 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",
1419
- onClick: clearSelection,
1420
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/x", size: 16 })
1421
- }
1422
- ),
1423
- /* @__PURE__ */ jsx("div", { className: "mb-3 flex items-start justify-between gap-3", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
1424
- selectedCluster.label ? /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: selectedCluster.label }) : null,
1425
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold leading-tight text-foreground", children: selectedCluster.title ?? "Clustered Locations" }),
1426
- /* @__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.` })
1427
- ] }) }),
1428
- /* @__PURE__ */ jsx("div", { className: "max-h-56 space-y-2 overflow-y-auto pr-1", children: selectedCluster.markers.map((marker, markerIndex) => /* @__PURE__ */ jsxs(
1429
- "button",
1430
- {
1431
- type: "button",
1432
- className: "w-full rounded-lg border border-border/60 p-3 text-left transition hover:border-border hover:bg-muted/50",
1433
- onClick: () => selectMarker(marker),
1434
- children: [
1435
- /* @__PURE__ */ jsx("div", { className: "line-clamp-1 text-sm font-semibold text-foreground", children: getMarkerTitle(marker, markerIndex) }),
1436
- marker.summary ? /* @__PURE__ */ jsx("div", { className: "mt-1 line-clamp-2 text-xs text-muted-foreground", children: marker.summary }) : null
1437
- ]
1438
- },
1439
- marker.id
1440
- )) })
1441
- ]
1442
- }
1443
- );
1444
- }
1445
- return null;
1446
- };
1447
- return /* @__PURE__ */ jsxs(
1448
- "div",
1449
- {
1450
- className: cn(
1451
- "relative overflow-hidden rounded-2xl border border-border bg-background",
1452
- className
1453
- ),
1454
- children: [
1455
- /* @__PURE__ */ jsx("div", { className: cn("h-[520px] w-full", mapWrapperClassName), children: /* @__PURE__ */ jsx(
1456
- MapLibre,
1457
- {
1458
- stadiaApiKey,
1459
- mapStyle,
1460
- styleUrl,
1461
- mapLibreCssHref,
1462
- viewState: resolvedViewState,
1463
- onViewStateChange: applyViewState,
1464
- markers: mapMarkers,
1465
- onClick: (coord) => {
1466
- onMapClick?.(coord);
1467
- if (clearSelectionOnMapClick) {
1468
- clearSelection();
1469
- }
1470
- },
1471
- onMarkerDrag,
1472
- showNavigationControl,
1473
- showGeolocateControl,
1474
- navigationControlPosition,
1475
- geolocateControlPosition,
1476
- flyToOptions,
1477
- className: cn("h-full w-full", mapClassName),
1478
- children: mapChildren
1479
- }
1480
- ) }),
1481
- selection.type !== "none" ? /* @__PURE__ */ jsx(
1482
- "div",
1483
- {
1484
- className: cn(
1485
- "pointer-events-none absolute z-20",
1486
- PANEL_POSITION_CLASS[panelPosition]
1487
- ),
1488
- children: /* @__PURE__ */ jsx("div", { className: "pointer-events-auto", children: renderMarkerPanel() })
1489
- }
1490
- ) : null
1491
- ]
1492
- }
1493
- );
1494
- }
1495
- var sizeStyles = {
1496
- sm: "max-w-md",
1497
- md: "max-w-2xl",
1498
- lg: "max-w-4xl",
1499
- xl: "max-w-5xl",
1500
- full: "max-w-7xl",
1501
- compact: "max-w-[700px]"
1502
- };
1503
- var dialogTransition = {
1504
- duration: 0.35,
1505
- ease: [0.16, 1, 0.3, 1]
1506
- };
1507
- function AnimatedDialog({
1508
- open,
1509
- onOpenChange,
1510
- title,
1511
- eyebrow,
1512
- description,
1513
- children,
1514
- header,
1515
- footer,
1516
- size = "lg",
1517
- className,
1518
- contentClassName,
1519
- featuredMediaHeader
1520
- }) {
1521
- const titleId = useId();
1522
- const descriptionId = useId();
1523
- const containerRef = useRef(null);
1524
- useOnClickOutside(containerRef, () => {
1525
- if (open) {
1526
- onOpenChange(false);
1527
- }
1528
- });
1529
- useEffect(() => {
1530
- if (!open) {
1531
- return;
1532
- }
1533
- const onKeyDown = (event) => {
1534
- if (event.key === "Escape") {
1535
- onOpenChange(false);
1536
- }
1537
- };
1538
- const previousOverflow = document.body.style.overflow;
1539
- document.body.style.overflow = "hidden";
1540
- window.addEventListener("keydown", onKeyDown);
1541
- return () => {
1542
- document.body.style.overflow = previousOverflow;
1543
- window.removeEventListener("keydown", onKeyDown);
1544
- };
1545
- }, [open, onOpenChange]);
1546
- return /* @__PURE__ */ jsx(AnimatePresence, { children: open ? /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 h-screen overflow-y-auto", children: [
1547
- /* @__PURE__ */ jsx(
1548
- motion.div,
1549
- {
1550
- initial: { opacity: 0 },
1551
- animate: { opacity: 1, transition: dialogTransition },
1552
- exit: { opacity: 0, transition: dialogTransition },
1553
- className: "fixed inset-0 h-full w-full bg-foreground/80 backdrop-blur-lg"
471
+ };
472
+ const previousOverflow = document.body.style.overflow;
473
+ document.body.style.overflow = "hidden";
474
+ window.addEventListener("keydown", onKeyDown);
475
+ return () => {
476
+ document.body.style.overflow = previousOverflow;
477
+ window.removeEventListener("keydown", onKeyDown);
478
+ };
479
+ }, [open, onOpenChange]);
480
+ return /* @__PURE__ */ jsx(AnimatePresence, { children: open ? /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 h-screen overflow-y-auto", children: [
481
+ /* @__PURE__ */ jsx(
482
+ motion.div,
483
+ {
484
+ initial: { opacity: 0 },
485
+ animate: { opacity: 1, transition: dialogTransition },
486
+ exit: { opacity: 0, transition: dialogTransition },
487
+ className: "fixed inset-0 h-full w-full bg-foreground/80 backdrop-blur-lg"
1554
488
  }
1555
489
  ),
1556
490
  /* @__PURE__ */ jsxs(
@@ -1849,10 +783,10 @@ var ImageSlider = ({
1849
783
  optixFlowConfig
1850
784
  }) => {
1851
785
  const hasImages = images.length > 0;
1852
- const [currentIndex, setCurrentIndex] = React6.useState(
786
+ const [currentIndex, setCurrentIndex] = React4.useState(
1853
787
  () => normalizeIndex(startIndex, images.length)
1854
788
  );
1855
- const handleNext = React6.useCallback(() => {
789
+ const handleNext = React4.useCallback(() => {
1856
790
  if (!hasImages) return;
1857
791
  setCurrentIndex((prevIndex) => {
1858
792
  const nextIndex = prevIndex + 1 >= images.length ? 0 : prevIndex + 1;
@@ -1860,7 +794,7 @@ var ImageSlider = ({
1860
794
  return nextIndex;
1861
795
  });
1862
796
  }, [hasImages, images.length, onSlideChange]);
1863
- const handlePrevious = React6.useCallback(() => {
797
+ const handlePrevious = React4.useCallback(() => {
1864
798
  if (!hasImages) return;
1865
799
  setCurrentIndex((prevIndex) => {
1866
800
  const nextIndex = prevIndex - 1 < 0 ? images.length - 1 : prevIndex - 1;
@@ -1868,11 +802,11 @@ var ImageSlider = ({
1868
802
  return nextIndex;
1869
803
  });
1870
804
  }, [hasImages, images.length, onSlideChange]);
1871
- React6.useEffect(() => {
805
+ React4.useEffect(() => {
1872
806
  if (!hasImages) return;
1873
807
  setCurrentIndex(normalizeIndex(startIndex, images.length));
1874
808
  }, [startIndex, images.length, hasImages]);
1875
- React6.useEffect(() => {
809
+ React4.useEffect(() => {
1876
810
  if (!enableKeyboard || !hasImages) return;
1877
811
  const handleKeyDown = (event) => {
1878
812
  if (event.key === "ArrowRight") {
@@ -1886,7 +820,7 @@ var ImageSlider = ({
1886
820
  window.removeEventListener("keydown", handleKeyDown);
1887
821
  };
1888
822
  }, [enableKeyboard, handleNext, handlePrevious, hasImages]);
1889
- React6.useEffect(() => {
823
+ React4.useEffect(() => {
1890
824
  if (!autoplay || images.length < 2) return;
1891
825
  const interval = window.setInterval(handleNext, autoplayIntervalMs);
1892
826
  return () => window.clearInterval(interval);
@@ -1957,8 +891,150 @@ var ImageSlider = ({
1957
891
  ) : null
1958
892
  ]
1959
893
  }
1960
- );
1961
- };
894
+ );
895
+ };
896
+ var baseStyles = [
897
+ // Layout
898
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
899
+ // Typography - using CSS variables with sensible defaults
900
+ "font-[var(--button-font-family,inherit)]",
901
+ "font-[var(--button-font-weight,500)]",
902
+ "tracking-[var(--button-letter-spacing,0)]",
903
+ "leading-[var(--button-line-height,1.25)]",
904
+ "[text-transform:var(--button-text-transform,none)]",
905
+ "text-sm",
906
+ // Border radius
907
+ "rounded-[var(--button-radius,var(--radius,0.375rem))]",
908
+ // Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
909
+ "[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
910
+ // Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
911
+ "[box-shadow:var(--button-shadow,none)]",
912
+ "hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
913
+ // Disabled state
914
+ "disabled:pointer-events-none disabled:opacity-50",
915
+ // SVG handling
916
+ "[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
917
+ // Focus styles
918
+ "outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
919
+ // Invalid state
920
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
921
+ ].join(" ");
922
+ var buttonVariants = cva(baseStyles, {
923
+ variants: {
924
+ variant: {
925
+ // Default (Primary) variant - full customization
926
+ default: [
927
+ "bg-[var(--button-default-bg,hsl(var(--primary)))]",
928
+ "text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
929
+ "border-[length:var(--button-default-border-width,0px)]",
930
+ "border-[color:var(--button-default-border,transparent)]",
931
+ "[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
932
+ "hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
933
+ "hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
934
+ "hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
935
+ "hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
936
+ ].join(" "),
937
+ // Destructive variant - full customization
938
+ destructive: [
939
+ "bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
940
+ "text-[var(--button-destructive-fg,white)]",
941
+ "border-[length:var(--button-destructive-border-width,0px)]",
942
+ "border-[color:var(--button-destructive-border,transparent)]",
943
+ "[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
944
+ "hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
945
+ "hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
946
+ "hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
947
+ "hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
948
+ "focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
949
+ "dark:bg-destructive/60"
950
+ ].join(" "),
951
+ // Outline variant - full customization with proper border handling
952
+ outline: [
953
+ "bg-[var(--button-outline-bg,hsl(var(--background)))]",
954
+ "text-[var(--button-outline-fg,inherit)]",
955
+ "border-[length:var(--button-outline-border-width,1px)]",
956
+ "border-[color:var(--button-outline-border,hsl(var(--border)))]",
957
+ "[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
958
+ "hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
959
+ "hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
960
+ "hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
961
+ "hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
962
+ "dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
963
+ ].join(" "),
964
+ // Secondary variant - full customization
965
+ secondary: [
966
+ "bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
967
+ "text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
968
+ "border-[length:var(--button-secondary-border-width,0px)]",
969
+ "border-[color:var(--button-secondary-border,transparent)]",
970
+ "[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
971
+ "hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
972
+ "hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
973
+ "hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
974
+ "hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
975
+ ].join(" "),
976
+ // Ghost variant - full customization
977
+ ghost: [
978
+ "bg-[var(--button-ghost-bg,transparent)]",
979
+ "text-[var(--button-ghost-fg,inherit)]",
980
+ "border-[length:var(--button-ghost-border-width,0px)]",
981
+ "border-[color:var(--button-ghost-border,transparent)]",
982
+ "[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
983
+ "hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
984
+ "hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
985
+ "hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
986
+ "hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
987
+ "dark:hover:bg-accent/50"
988
+ ].join(" "),
989
+ // Link variant - full customization
990
+ link: [
991
+ "bg-[var(--button-link-bg,transparent)]",
992
+ "text-[var(--button-link-fg,hsl(var(--primary)))]",
993
+ "border-[length:var(--button-link-border-width,0px)]",
994
+ "border-[color:var(--button-link-border,transparent)]",
995
+ "[box-shadow:var(--button-link-shadow,none)]",
996
+ "hover:bg-[var(--button-link-hover-bg,transparent)]",
997
+ "hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
998
+ "hover:[box-shadow:var(--button-link-shadow-hover,none)]",
999
+ "underline-offset-4 hover:underline"
1000
+ ].join(" ")
1001
+ },
1002
+ size: {
1003
+ default: [
1004
+ "h-[var(--button-height-md,2.25rem)]",
1005
+ "px-[var(--button-padding-x-md,1rem)]",
1006
+ "py-[var(--button-padding-y-md,0.5rem)]",
1007
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
1008
+ ].join(" "),
1009
+ sm: [
1010
+ "h-[var(--button-height-sm,2rem)]",
1011
+ "px-[var(--button-padding-x-sm,0.75rem)]",
1012
+ "py-[var(--button-padding-y-sm,0.25rem)]",
1013
+ "gap-1.5",
1014
+ "has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
1015
+ ].join(" "),
1016
+ md: [
1017
+ "h-[var(--button-height-md,2.25rem)]",
1018
+ "px-[var(--button-padding-x-md,1rem)]",
1019
+ "py-[var(--button-padding-y-md,0.5rem)]",
1020
+ "has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
1021
+ ].join(" "),
1022
+ lg: [
1023
+ "h-[var(--button-height-lg,2.5rem)]",
1024
+ "px-[var(--button-padding-x-lg,1.5rem)]",
1025
+ "py-[var(--button-padding-y-lg,0.5rem)]",
1026
+ "has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
1027
+ ].join(" "),
1028
+ icon: "size-[var(--button-height-md,2.25rem)]",
1029
+ "icon-sm": "size-[var(--button-height-sm,2rem)]",
1030
+ "icon-lg": "size-[var(--button-height-lg,2.5rem)]"
1031
+ }
1032
+ },
1033
+ defaultVariants: {
1034
+ variant: "default",
1035
+ size: "default"
1036
+ }
1037
+ });
1962
1038
  function Button({
1963
1039
  className,
1964
1040
  variant = "default",
@@ -2002,127 +1078,411 @@ function CardHeader({ className, ...props }) {
2002
1078
  ),
2003
1079
  ...props
2004
1080
  }
2005
- );
2006
- }
2007
- function CardTitle({ className, ...props }) {
2008
- return /* @__PURE__ */ jsx(
2009
- "div",
2010
- {
2011
- "data-slot": "card-title",
2012
- className: cn("leading-none font-semibold", className),
2013
- ...props
1081
+ );
1082
+ }
1083
+ function CardTitle({ className, ...props }) {
1084
+ return /* @__PURE__ */ jsx(
1085
+ "div",
1086
+ {
1087
+ "data-slot": "card-title",
1088
+ className: cn("leading-none font-semibold", className),
1089
+ ...props
1090
+ }
1091
+ );
1092
+ }
1093
+ function CardDescription({ className, ...props }) {
1094
+ return /* @__PURE__ */ jsx(
1095
+ "div",
1096
+ {
1097
+ "data-slot": "card-description",
1098
+ className: cn("text-muted-foreground text-sm", className),
1099
+ ...props
1100
+ }
1101
+ );
1102
+ }
1103
+ function CardContent({ className, ...props }) {
1104
+ return /* @__PURE__ */ jsx(
1105
+ "div",
1106
+ {
1107
+ "data-slot": "card-content",
1108
+ className: cn("px-6", className),
1109
+ ...props
1110
+ }
1111
+ );
1112
+ }
1113
+ function CardFooter({ className, ...props }) {
1114
+ return /* @__PURE__ */ jsx(
1115
+ "div",
1116
+ {
1117
+ "data-slot": "card-footer",
1118
+ className: cn("flex items-center px-6 [.border-t]:pt-6", className),
1119
+ ...props
1120
+ }
1121
+ );
1122
+ }
1123
+ var badgeVariants = cva(
1124
+ "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",
1125
+ {
1126
+ variants: {
1127
+ variant: {
1128
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
1129
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
1130
+ 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",
1131
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
1132
+ }
1133
+ },
1134
+ defaultVariants: {
1135
+ variant: "default"
1136
+ }
1137
+ }
1138
+ );
1139
+ function Badge({
1140
+ className,
1141
+ variant,
1142
+ asChild = false,
1143
+ ...props
1144
+ }) {
1145
+ const Comp = asChild ? Slot : "span";
1146
+ return /* @__PURE__ */ jsx(
1147
+ Comp,
1148
+ {
1149
+ "data-slot": "badge",
1150
+ className: cn(badgeVariants({ variant }), className),
1151
+ ...props
1152
+ }
1153
+ );
1154
+ }
1155
+ function Popover({
1156
+ ...props
1157
+ }) {
1158
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
1159
+ }
1160
+ function PopoverTrigger({
1161
+ ...props
1162
+ }) {
1163
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
1164
+ }
1165
+ function PopoverContent({
1166
+ className,
1167
+ align = "center",
1168
+ sideOffset = 4,
1169
+ ...props
1170
+ }) {
1171
+ return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
1172
+ PopoverPrimitive.Content,
1173
+ {
1174
+ "data-slot": "popover-content",
1175
+ align,
1176
+ sideOffset,
1177
+ className: cn(
1178
+ "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",
1179
+ className
1180
+ ),
1181
+ ...props
1182
+ }
1183
+ ) });
1184
+ }
1185
+ var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
1186
+ var DynamicIcon = React4.memo(function DynamicIcon2({
1187
+ apiKey,
1188
+ ...props
1189
+ }) {
1190
+ return /* @__PURE__ */ jsx(Icon, { ...props, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
1191
+ });
1192
+ DynamicIcon.displayName = "DynamicIcon";
1193
+ function StarRating({
1194
+ rating,
1195
+ size = 18,
1196
+ className
1197
+ }) {
1198
+ return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
1199
+ DynamicIcon,
1200
+ {
1201
+ name: "icon-park-solid/star",
1202
+ size,
1203
+ className: cn(
1204
+ star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
1205
+ )
1206
+ },
1207
+ star
1208
+ )) });
1209
+ }
1210
+ function normalizePhoneNumber(input) {
1211
+ const trimmed = input.trim();
1212
+ if (trimmed.toLowerCase().startsWith("tel:")) {
1213
+ return trimmed;
1214
+ }
1215
+ const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
1216
+ if (match) {
1217
+ const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
1218
+ const extension = match[3];
1219
+ const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
1220
+ const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
1221
+ return `tel:${withExtension}`;
1222
+ }
1223
+ const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
1224
+ return `tel:${cleaned}`;
1225
+ }
1226
+ function normalizeEmail(input) {
1227
+ const trimmed = input.trim();
1228
+ if (trimmed.toLowerCase().startsWith("mailto:")) {
1229
+ return trimmed;
1230
+ }
1231
+ return `mailto:${trimmed}`;
1232
+ }
1233
+ function isEmail(input) {
1234
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1235
+ return emailRegex.test(input.trim());
1236
+ }
1237
+ function isPhoneNumber(input) {
1238
+ const trimmed = input.trim();
1239
+ if (trimmed.toLowerCase().startsWith("tel:")) {
1240
+ return true;
1241
+ }
1242
+ const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
1243
+ return phoneRegex.test(trimmed);
1244
+ }
1245
+ function isInternalUrl(href) {
1246
+ if (typeof window === "undefined") {
1247
+ return href.startsWith("/") && !href.startsWith("//");
1248
+ }
1249
+ const trimmed = href.trim();
1250
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
1251
+ return true;
1252
+ }
1253
+ try {
1254
+ const url = new URL(trimmed, window.location.href);
1255
+ const currentOrigin = window.location.origin;
1256
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
1257
+ return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
1258
+ } catch {
1259
+ return false;
1260
+ }
1261
+ }
1262
+ function toRelativePath(href) {
1263
+ if (typeof window === "undefined") {
1264
+ return href;
1265
+ }
1266
+ const trimmed = href.trim();
1267
+ if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
1268
+ return trimmed;
1269
+ }
1270
+ try {
1271
+ const url = new URL(trimmed, window.location.href);
1272
+ const currentOrigin = window.location.origin;
1273
+ const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
1274
+ if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
1275
+ return url.pathname + url.search + url.hash;
1276
+ }
1277
+ } catch {
1278
+ }
1279
+ return trimmed;
1280
+ }
1281
+ function useNavigation({
1282
+ href,
1283
+ onClick
1284
+ } = {}) {
1285
+ const linkType = React4.useMemo(() => {
1286
+ if (!href || href.trim() === "") {
1287
+ return onClick ? "none" : "none";
1288
+ }
1289
+ const trimmed = href.trim();
1290
+ if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
1291
+ return "mailto";
1292
+ }
1293
+ if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
1294
+ return "tel";
1295
+ }
1296
+ if (isInternalUrl(trimmed)) {
1297
+ return "internal";
1298
+ }
1299
+ try {
1300
+ new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
1301
+ return "external";
1302
+ } catch {
1303
+ return "internal";
1304
+ }
1305
+ }, [href, onClick]);
1306
+ const normalizedHref = React4.useMemo(() => {
1307
+ if (!href || href.trim() === "") {
1308
+ return void 0;
1309
+ }
1310
+ const trimmed = href.trim();
1311
+ switch (linkType) {
1312
+ case "tel":
1313
+ return normalizePhoneNumber(trimmed);
1314
+ case "mailto":
1315
+ return normalizeEmail(trimmed);
1316
+ case "internal":
1317
+ return toRelativePath(trimmed);
1318
+ case "external":
1319
+ return trimmed;
1320
+ default:
1321
+ return trimmed;
1322
+ }
1323
+ }, [href, linkType]);
1324
+ const target = React4.useMemo(() => {
1325
+ switch (linkType) {
1326
+ case "external":
1327
+ return "_blank";
1328
+ case "internal":
1329
+ return "_self";
1330
+ case "mailto":
1331
+ case "tel":
1332
+ return void 0;
1333
+ default:
1334
+ return void 0;
1335
+ }
1336
+ }, [linkType]);
1337
+ const rel = React4.useMemo(() => {
1338
+ if (linkType === "external") {
1339
+ return "noopener noreferrer";
2014
1340
  }
1341
+ return void 0;
1342
+ }, [linkType]);
1343
+ const isExternal = linkType === "external";
1344
+ const isInternal = linkType === "internal";
1345
+ const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
1346
+ const handleClick = React4.useCallback(
1347
+ (event) => {
1348
+ if (onClick) {
1349
+ try {
1350
+ onClick(event);
1351
+ } catch (error) {
1352
+ console.error("Error in user onClick handler:", error);
1353
+ }
1354
+ }
1355
+ if (event.defaultPrevented) {
1356
+ return;
1357
+ }
1358
+ if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
1359
+ !event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
1360
+ if (typeof window !== "undefined") {
1361
+ const handler = window.__opensiteNavigationHandler;
1362
+ if (typeof handler === "function") {
1363
+ try {
1364
+ const handled = handler(normalizedHref, event.nativeEvent || event);
1365
+ if (handled !== false) {
1366
+ event.preventDefault();
1367
+ }
1368
+ } catch (error) {
1369
+ console.error("Error in navigation handler:", error);
1370
+ }
1371
+ }
1372
+ }
1373
+ }
1374
+ },
1375
+ [onClick, shouldUseRouter, normalizedHref]
2015
1376
  );
1377
+ return {
1378
+ linkType,
1379
+ normalizedHref,
1380
+ target,
1381
+ rel,
1382
+ isExternal,
1383
+ isInternal,
1384
+ shouldUseRouter,
1385
+ handleClick
1386
+ };
2016
1387
  }
2017
- function CardDescription({ className, ...props }) {
2018
- return /* @__PURE__ */ jsx(
2019
- "div",
2020
- {
2021
- "data-slot": "card-description",
2022
- className: cn("text-muted-foreground text-sm", className),
2023
- ...props
1388
+ var Pressable = React4.forwardRef(
1389
+ ({
1390
+ children,
1391
+ className,
1392
+ href,
1393
+ onClick,
1394
+ variant,
1395
+ size,
1396
+ asButton = false,
1397
+ fallbackComponentType = "span",
1398
+ componentType,
1399
+ "aria-label": ariaLabel,
1400
+ "aria-describedby": ariaDescribedby,
1401
+ id,
1402
+ ...props
1403
+ }, ref) => {
1404
+ const navigation = useNavigation({ href, onClick });
1405
+ const {
1406
+ normalizedHref,
1407
+ target,
1408
+ rel,
1409
+ linkType,
1410
+ isInternal,
1411
+ handleClick
1412
+ } = navigation;
1413
+ const shouldRenderLink = normalizedHref && linkType !== "none";
1414
+ const shouldRenderButton = !shouldRenderLink && onClick;
1415
+ const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
1416
+ const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
1417
+ const shouldApplyButtonStyles = asButton || variant || size;
1418
+ const combinedClassName = cn(
1419
+ shouldApplyButtonStyles && buttonVariants({ variant, size }),
1420
+ className
1421
+ );
1422
+ const dataProps = Object.fromEntries(
1423
+ Object.entries(props).filter(([key]) => key.startsWith("data-"))
1424
+ );
1425
+ const buttonDataAttributes = shouldApplyButtonStyles ? {
1426
+ "data-slot": "button",
1427
+ "data-variant": variant ?? "default",
1428
+ "data-size": size ?? "default"
1429
+ } : {};
1430
+ const commonProps = {
1431
+ className: combinedClassName,
1432
+ onClick: handleClick,
1433
+ "aria-label": ariaLabel,
1434
+ "aria-describedby": ariaDescribedby,
1435
+ id,
1436
+ ...dataProps,
1437
+ ...buttonDataAttributes
1438
+ };
1439
+ if (finalComponentType === "a" && shouldRenderLink) {
1440
+ return /* @__PURE__ */ jsx(
1441
+ "a",
1442
+ {
1443
+ ref,
1444
+ href: normalizedHref,
1445
+ target,
1446
+ rel,
1447
+ ...commonProps,
1448
+ ...props,
1449
+ children
1450
+ }
1451
+ );
2024
1452
  }
2025
- );
2026
- }
2027
- function CardContent({ className, ...props }) {
2028
- return /* @__PURE__ */ jsx(
2029
- "div",
2030
- {
2031
- "data-slot": "card-content",
2032
- className: cn("px-6", className),
2033
- ...props
1453
+ if (finalComponentType === "button") {
1454
+ return /* @__PURE__ */ jsx(
1455
+ "button",
1456
+ {
1457
+ ref,
1458
+ type: props.type || "button",
1459
+ ...commonProps,
1460
+ ...props,
1461
+ children
1462
+ }
1463
+ );
2034
1464
  }
2035
- );
2036
- }
2037
- function CardFooter({ className, ...props }) {
2038
- return /* @__PURE__ */ jsx(
2039
- "div",
2040
- {
2041
- "data-slot": "card-footer",
2042
- className: cn("flex items-center px-6 [.border-t]:pt-6", className),
2043
- ...props
1465
+ if (finalComponentType === "div") {
1466
+ return /* @__PURE__ */ jsx(
1467
+ "div",
1468
+ {
1469
+ ref,
1470
+ ...commonProps,
1471
+ children
1472
+ }
1473
+ );
2044
1474
  }
2045
- );
2046
- }
2047
- var badgeVariants = cva(
2048
- "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",
2049
- {
2050
- variants: {
2051
- variant: {
2052
- default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
2053
- secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
2054
- 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",
2055
- outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
1475
+ return /* @__PURE__ */ jsx(
1476
+ "span",
1477
+ {
1478
+ ref,
1479
+ ...commonProps,
1480
+ children
2056
1481
  }
2057
- },
2058
- defaultVariants: {
2059
- variant: "default"
2060
- }
1482
+ );
2061
1483
  }
2062
1484
  );
2063
- function Badge({
2064
- className,
2065
- variant,
2066
- asChild = false,
2067
- ...props
2068
- }) {
2069
- const Comp = asChild ? Slot : "span";
2070
- return /* @__PURE__ */ jsx(
2071
- Comp,
2072
- {
2073
- "data-slot": "badge",
2074
- className: cn(badgeVariants({ variant }), className),
2075
- ...props
2076
- }
2077
- );
2078
- }
2079
- function Popover({
2080
- ...props
2081
- }) {
2082
- return /* @__PURE__ */ jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
2083
- }
2084
- function PopoverTrigger({
2085
- ...props
2086
- }) {
2087
- return /* @__PURE__ */ jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
2088
- }
2089
- function PopoverContent({
2090
- className,
2091
- align = "center",
2092
- sideOffset = 4,
2093
- ...props
2094
- }) {
2095
- return /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
2096
- PopoverPrimitive.Content,
2097
- {
2098
- "data-slot": "popover-content",
2099
- align,
2100
- sideOffset,
2101
- className: cn(
2102
- "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",
2103
- className
2104
- ),
2105
- ...props
2106
- }
2107
- ) });
2108
- }
2109
- function StarRating({
2110
- rating,
2111
- size = 18,
2112
- className
2113
- }) {
2114
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-center gap-0.5", className), children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx(
2115
- DynamicIcon,
2116
- {
2117
- name: "icon-park-solid/star",
2118
- size,
2119
- className: cn(
2120
- star <= rating ? "fill-primary text-primary" : "fill-muted text-muted"
2121
- )
2122
- },
2123
- star
2124
- )) });
2125
- }
1485
+ Pressable.displayName = "Pressable";
2126
1486
  var BUTTON_SIZES = {
2127
1487
  sm: { buttonSize: "size-8", iconSize: 16 },
2128
1488
  md: { buttonSize: "size-10", iconSize: 20 },
@@ -2214,7 +1574,7 @@ var platformIconMap = {
2214
1574
  dribbble: "cib/dribbble",
2215
1575
  unknown: "icon-park-solid/circular-connection"
2216
1576
  };
2217
- var SocialLinkIcon = React6.forwardRef(
1577
+ var SocialLinkIcon = React4.forwardRef(
2218
1578
  ({
2219
1579
  platformName,
2220
1580
  label,
@@ -2228,16 +1588,16 @@ var SocialLinkIcon = React6.forwardRef(
2228
1588
  ...pressableProps
2229
1589
  }, ref) => {
2230
1590
  const platform = usePlatformFromUrl(href);
2231
- const smartPlatformName = React6.useMemo(() => {
1591
+ const smartPlatformName = React4.useMemo(() => {
2232
1592
  return platform || platformName;
2233
1593
  }, [platform, platformName]);
2234
- const iconName = React6.useMemo(() => {
1594
+ const iconName = React4.useMemo(() => {
2235
1595
  return iconNameOverride || platformIconMap[smartPlatformName];
2236
1596
  }, [iconNameOverride, smartPlatformName]);
2237
- const accessibleLabel = React6.useMemo(() => {
1597
+ const accessibleLabel = React4.useMemo(() => {
2238
1598
  return label || platformName;
2239
1599
  }, [label, platformName]);
2240
- const icon = React6.useMemo(() => {
1600
+ const icon = React4.useMemo(() => {
2241
1601
  return /* @__PURE__ */ jsx(
2242
1602
  DynamicIcon,
2243
1603
  {
@@ -2317,12 +1677,12 @@ function TextInner({ as, className, children, ...props }, ref) {
2317
1677
  const Component = as || "span";
2318
1678
  return /* @__PURE__ */ jsx(Component, { ref, className: cn(className), ...props, children });
2319
1679
  }
2320
- var Text = React6.forwardRef(TextInner);
1680
+ var Text = React4.forwardRef(TextInner);
2321
1681
  Text.displayName = "Text";
2322
1682
  function isContentTextItem(item) {
2323
- return item !== null && typeof item === "object" && !React6.isValidElement(item) && "_type" in item && item._type === "text";
1683
+ return item !== null && typeof item === "object" && !React4.isValidElement(item) && "_type" in item && item._type === "text";
2324
1684
  }
2325
- var ContentGroup = React6.forwardRef(
1685
+ var ContentGroup = React4.forwardRef(
2326
1686
  ({ items, className, children, ...props }, ref) => {
2327
1687
  const hasContent = items && items.length > 0;
2328
1688
  if (!hasContent) {
@@ -2335,10 +1695,10 @@ var ContentGroup = React6.forwardRef(
2335
1695
  return /* @__PURE__ */ jsx(Text, { ...textProps }, idx);
2336
1696
  }
2337
1697
  const reactNode = item;
2338
- if (React6.isValidElement(reactNode)) {
2339
- return React6.cloneElement(reactNode, { key: reactNode.key ?? idx });
1698
+ if (React4.isValidElement(reactNode)) {
1699
+ return React4.cloneElement(reactNode, { key: reactNode.key ?? idx });
2340
1700
  }
2341
- return /* @__PURE__ */ jsx(React6.Fragment, { children: reactNode }, idx);
1701
+ return /* @__PURE__ */ jsx(React4.Fragment, { children: reactNode }, idx);
2342
1702
  }),
2343
1703
  children
2344
1704
  ] });
@@ -2863,7 +2223,7 @@ function AboutExpandableValues({
2863
2223
  pattern,
2864
2224
  patternOpacity
2865
2225
  }) {
2866
- const [expandedValue, setExpandedValue] = React6.useState(null);
2226
+ const [expandedValue, setExpandedValue] = React4.useState(null);
2867
2227
  const toggleExpand = useCallback((id) => {
2868
2228
  setExpandedValue((prev) => prev === id ? null : id);
2869
2229
  }, []);
@@ -3099,7 +2459,7 @@ function CommunityInitiatives({
3099
2459
  pattern,
3100
2460
  patternOpacity
3101
2461
  }) {
3102
- const [activeCategory, setActiveCategory] = React6.useState(
2462
+ const [activeCategory, setActiveCategory] = React4.useState(
3103
2463
  categories?.[0]?.id || ""
3104
2464
  );
3105
2465
  const currentCategory = categories?.find((category) => category.id === activeCategory) || categories?.[0];
@@ -3363,7 +2723,7 @@ function AboutCultureTabs({
3363
2723
  patternOpacity
3364
2724
  }) {
3365
2725
  const resolvedAspects = aspects ?? [];
3366
- const [activeTab, setActiveTab] = React6.useState(
2726
+ const [activeTab, setActiveTab] = React4.useState(
3367
2727
  resolvedAspects[0]?.id || ""
3368
2728
  );
3369
2729
  const headerItems = useMemo(() => {
@@ -3896,7 +3256,7 @@ function BannerDeliveryCountdown({
3896
3256
  }, [prefixText, timerContent, middleText, deliveryDateContent]);
3897
3257
  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: [
3898
3258
  iconContent,
3899
- messageParts.length > 0 && /* @__PURE__ */ jsx("span", { children: messageParts.map((part, index) => /* @__PURE__ */ jsxs(React6.Fragment, { children: [
3259
+ messageParts.length > 0 && /* @__PURE__ */ jsx("span", { children: messageParts.map((part, index) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
3900
3260
  index > 0 ? " " : null,
3901
3261
  part
3902
3262
  ] }, index)) })
@@ -5167,8 +4527,8 @@ var BrandAttribution = ({
5167
4527
  }
5168
4528
  const { prefix = "", anchorText, href, suffix = "" } = options[optionIndex];
5169
4529
  const ContainerEl = variant;
5170
- const [trackedHref, setTrackedHref] = React6.useState(href);
5171
- React6.useEffect(() => {
4530
+ const [trackedHref, setTrackedHref] = React4.useState(href);
4531
+ React4.useEffect(() => {
5172
4532
  setTrackedHref(buildTrackedHref(href));
5173
4533
  }, [href]);
5174
4534
  return /* @__PURE__ */ jsxs(ContainerEl, { className: containerClassName, children: [
@@ -5288,7 +4648,7 @@ function FooterSocialNewsletter({
5288
4648
  patternOpacity,
5289
4649
  optixFlowConfig
5290
4650
  }) {
5291
- const renderForm = React6.useMemo(() => {
4651
+ const renderForm = React4.useMemo(() => {
5292
4652
  if (!formEngineSetup) return null;
5293
4653
  const action = {
5294
4654
  variant: "default",
@@ -5577,7 +4937,7 @@ function FooterSimpleCentered({
5577
4937
  ]);
5578
4938
  const bottomLinksContent = useMemo(() => {
5579
4939
  if (!bottomLinks || bottomLinks.length === 0) return null;
5580
- return bottomLinks.map((link, idx) => /* @__PURE__ */ jsx(React6.Fragment, { children: /* @__PURE__ */ jsx(
4940
+ return bottomLinks.map((link, idx) => /* @__PURE__ */ jsx(React4.Fragment, { children: /* @__PURE__ */ jsx(
5581
4941
  Pressable,
5582
4942
  {
5583
4943
  href: link.href,
@@ -6924,7 +6284,7 @@ function FooterNewsletterMinimal({
6924
6284
  buttonAction,
6925
6285
  formSlot
6926
6286
  }) {
6927
- const navLinksContent = React6.useMemo(() => {
6287
+ const navLinksContent = React4.useMemo(() => {
6928
6288
  if (!navLinks || navLinks.length === 0) return null;
6929
6289
  return navLinks.map((item, idx) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
6930
6290
  Pressable,
@@ -6935,7 +6295,7 @@ function FooterNewsletterMinimal({
6935
6295
  }
6936
6296
  ) }, idx));
6937
6297
  }, [navLinks, navLinkClassName]);
6938
- const socialLinksContent = React6.useMemo(() => {
6298
+ const socialLinksContent = React4.useMemo(() => {
6939
6299
  if (!socialLinks || socialLinks.length === 0) return null;
6940
6300
  return socialLinks.map((item, idx) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
6941
6301
  SocialLinkIcon,
@@ -6951,7 +6311,7 @@ function FooterNewsletterMinimal({
6951
6311
  }
6952
6312
  ) }, idx));
6953
6313
  }, [socialLinks, socialLinkClassName]);
6954
- const footerLinksContent = React6.useMemo(() => {
6314
+ const footerLinksContent = React4.useMemo(() => {
6955
6315
  if (!footerLinks || footerLinks.length === 0) return null;
6956
6316
  return footerLinks.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
6957
6317
  Pressable,
@@ -6965,7 +6325,7 @@ function FooterNewsletterMinimal({
6965
6325
  }
6966
6326
  ) }, item.label));
6967
6327
  }, [footerLinks, footerLinkClassName]);
6968
- const renderForm = React6.useMemo(() => {
6328
+ const renderForm = React4.useMemo(() => {
6969
6329
  if (formSlot) return formSlot;
6970
6330
  if (!formEngineSetup) return null;
6971
6331
  const defaultButtonAction = {
@@ -7512,4 +6872,4 @@ function FooterNavSocial({
7512
6872
  );
7513
6873
  }
7514
6874
 
7515
- 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 };
6875
+ 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 };