@opensite/ui 3.13.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var React = require('react');
4
+ var React4 = require('react');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var icon = require('@page-speed/icon');
@@ -29,14 +29,14 @@ function _interopNamespace(e) {
29
29
  return Object.freeze(n);
30
30
  }
31
31
 
32
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
32
+ var React4__namespace = /*#__PURE__*/_interopNamespace(React4);
33
33
 
34
34
  // components/blocks/hero/hero-event-registration.tsx
35
35
  function cn(...inputs) {
36
36
  return tailwindMerge.twMerge(clsx.clsx(inputs));
37
37
  }
38
38
  var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
39
- var DynamicIcon = React__namespace.memo(function DynamicIcon2({
39
+ var DynamicIcon = React4__namespace.memo(function DynamicIcon2({
40
40
  apiKey,
41
41
  name,
42
42
  ...props
@@ -89,7 +89,7 @@ var maxWidthStyles = {
89
89
  "4xl": "max-w-[1536px]",
90
90
  full: "max-w-full"
91
91
  };
92
- var Container = React__namespace.default.forwardRef(
92
+ var Container = React4__namespace.default.forwardRef(
93
93
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
94
94
  const Component = as;
95
95
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -395,7 +395,7 @@ var spacingStyles = {
395
395
  };
396
396
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
397
397
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
398
- var Section = React__namespace.default.forwardRef(
398
+ var Section = React4__namespace.default.forwardRef(
399
399
  ({
400
400
  id,
401
401
  title,
@@ -610,14 +610,15 @@ function HeroEventRegistration({
610
610
  logoClassName,
611
611
  directionConfig = { desktop: "mediaRight", mobile: "mediaTop" }
612
612
  }) {
613
- const renderBadge = React.useMemo(() => {
613
+ const renderBadge = React4.useMemo(() => {
614
614
  if (badgeSlot) return badgeSlot;
615
+ if (!badgeText && !badgeIcon) return null;
615
616
  return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { className: "px-4 py-1 gap-2", children: [
616
617
  badgeIcon && /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: badgeIcon, size: 18 }),
617
618
  badgeText
618
619
  ] });
619
620
  }, [badgeSlot, badgeIcon, badgeText]);
620
- const renderStats = React.useMemo(() => {
621
+ const renderStats = React4.useMemo(() => {
621
622
  if (statsSlot) return statsSlot;
622
623
  if (!stats || stats.length === 0) return null;
623
624
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -627,7 +628,7 @@ function HeroEventRegistration({
627
628
  "flex flex-col md:flex-row items-center gap-4 md:gap-6 pt-8 md:pt-12 w-full md:w-fit",
628
629
  statsClassName
629
630
  ),
630
- children: stats.map((stat, index) => /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
631
+ children: stats.map((stat, index) => /* @__PURE__ */ jsxRuntime.jsxs(React4__namespace.Fragment, { children: [
631
632
  index > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-12 w-px bg-border hidden md:flex" }),
632
633
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-between flex-row md:flex-col text-left md:text-center w-full md:w-fit border md:border-none rounded-xl md:rounded-none p-4 md:p-0", children: [
633
634
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -658,57 +659,67 @@ function HeroEventRegistration({
658
659
  }
659
660
  );
660
661
  }, [statsSlot, stats, statsClassName]);
661
- const renderLocation = React.useMemo(() => {
662
- if (locationSlot) return locationSlot;
663
- if (!locationLabel && !locationSublabel) return null;
664
- return /* @__PURE__ */ jsxRuntime.jsx(
665
- "div",
666
- {
667
- className: cn(
668
- "bg-card text-card-foreground",
669
- "rounded-2xl p-2 md:p-4 shadow-lg",
670
- "absolute bottom-0 translate-y-1/2",
671
- "left-1/2 -translate-x-1/2 w-[90%]",
672
- "md:-left-4 md:translate-x-0 md:w-auto",
673
- "ring-4 ring-primary"
674
- ),
675
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
676
- /* @__PURE__ */ jsxRuntime.jsx(
677
- "div",
678
- {
679
- className: cn(
680
- "flex items-center justify-center shrink-0",
681
- "size-12 rounded-xl bg-primary text-primary-foreground"
682
- ),
683
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
684
- }
662
+ const buildLocation = React4__namespace.useCallback(
663
+ (positioned) => {
664
+ if (locationSlot) return locationSlot;
665
+ if (!locationLabel && !locationSublabel) return null;
666
+ return /* @__PURE__ */ jsxRuntime.jsx(
667
+ "div",
668
+ {
669
+ className: cn(
670
+ "bg-card text-card-foreground",
671
+ "rounded-2xl p-2 md:p-4 shadow-lg",
672
+ "ring-4 ring-primary",
673
+ positioned ? cn(
674
+ "absolute bottom-0 translate-y-1/2",
675
+ "left-1/2 -translate-x-1/2 w-[90%]",
676
+ "md:-left-4 md:translate-x-0 md:w-auto"
677
+ ) : "w-full md:w-fit"
685
678
  ),
686
- /* @__PURE__ */ jsxRuntime.jsxs(
687
- "div",
688
- {
689
- className: cn(
690
- "flex flex-col items-start justify-center",
691
- "text-card-foreground gap-0 pr-0 md:pr-2"
692
- ),
693
- children: [
694
- locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
695
- locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
696
- "div",
697
- {
698
- className: cn(
699
- "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
700
- ),
701
- children: locationSublabel
702
- }
703
- ) : locationSublabel)
704
- ]
705
- }
706
- )
707
- ] })
708
- }
709
- );
710
- }, [locationSlot, locationLabel, locationSublabel]);
711
- const renderImage = React.useMemo(() => {
679
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
680
+ /* @__PURE__ */ jsxRuntime.jsx(
681
+ "div",
682
+ {
683
+ className: cn(
684
+ "flex items-center justify-center shrink-0",
685
+ "size-12 rounded-xl bg-primary text-primary-foreground"
686
+ ),
687
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
688
+ }
689
+ ),
690
+ /* @__PURE__ */ jsxRuntime.jsxs(
691
+ "div",
692
+ {
693
+ className: cn(
694
+ "flex flex-col items-start justify-center",
695
+ "text-card-foreground gap-0 pr-0 md:pr-2"
696
+ ),
697
+ children: [
698
+ locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
699
+ locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
700
+ "div",
701
+ {
702
+ className: cn(
703
+ "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
704
+ ),
705
+ children: locationSublabel
706
+ }
707
+ ) : locationSublabel)
708
+ ]
709
+ }
710
+ )
711
+ ] })
712
+ }
713
+ );
714
+ },
715
+ [locationSlot, locationLabel, locationSublabel]
716
+ );
717
+ const renderLocation = React4.useMemo(() => buildLocation(true), [buildLocation]);
718
+ const renderInlineLocation = React4.useMemo(
719
+ () => buildLocation(false),
720
+ [buildLocation]
721
+ );
722
+ const renderImage = React4.useMemo(() => {
712
723
  if (imageSlot) return imageSlot;
713
724
  if (!image) return null;
714
725
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full md:w-[50%]", children: [
@@ -736,6 +747,7 @@ function HeroEventRegistration({
736
747
  }, [imageSlot, image, imageClassName, optixFlowConfig, renderLocation]);
737
748
  const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
738
749
  const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
750
+ const locationInImage = !imageSlot && Boolean(image);
739
751
  return /* @__PURE__ */ jsxRuntime.jsx(
740
752
  Section,
741
753
  {
@@ -784,6 +796,7 @@ function HeroEventRegistration({
784
796
  }
785
797
  ) : heading),
786
798
  description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description),
799
+ !locationInImage && renderInlineLocation,
787
800
  /* @__PURE__ */ jsxRuntime.jsx(
788
801
  BlockActions,
789
802
  {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
- import * as React from 'react';
3
- import React__default, { useMemo } from 'react';
2
+ import * as React4 from 'react';
3
+ import React4__default, { useMemo } from 'react';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { Icon } from '@page-speed/icon';
@@ -15,7 +15,7 @@ function cn(...inputs) {
15
15
  return twMerge(clsx(inputs));
16
16
  }
17
17
  var DEFAULT_ICON_API_KEY = "au382bi7fsh96w9h9xlrnat2jglx";
18
- var DynamicIcon = React.memo(function DynamicIcon2({
18
+ var DynamicIcon = React4.memo(function DynamicIcon2({
19
19
  apiKey,
20
20
  name,
21
21
  ...props
@@ -68,7 +68,7 @@ var maxWidthStyles = {
68
68
  "4xl": "max-w-[1536px]",
69
69
  full: "max-w-full"
70
70
  };
71
- var Container = React__default.forwardRef(
71
+ var Container = React4__default.forwardRef(
72
72
  ({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
73
73
  const Component = as;
74
74
  return /* @__PURE__ */ jsx(
@@ -374,7 +374,7 @@ var spacingStyles = {
374
374
  };
375
375
  var predefinedSpacings = ["none", "sm", "md", "lg", "xl", "hero"];
376
376
  var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
377
- var Section = React__default.forwardRef(
377
+ var Section = React4__default.forwardRef(
378
378
  ({
379
379
  id,
380
380
  title,
@@ -591,6 +591,7 @@ function HeroEventRegistration({
591
591
  }) {
592
592
  const renderBadge = useMemo(() => {
593
593
  if (badgeSlot) return badgeSlot;
594
+ if (!badgeText && !badgeIcon) return null;
594
595
  return /* @__PURE__ */ jsxs(Badge, { className: "px-4 py-1 gap-2", children: [
595
596
  badgeIcon && /* @__PURE__ */ jsx(DynamicIcon, { name: badgeIcon, size: 18 }),
596
597
  badgeText
@@ -606,7 +607,7 @@ function HeroEventRegistration({
606
607
  "flex flex-col md:flex-row items-center gap-4 md:gap-6 pt-8 md:pt-12 w-full md:w-fit",
607
608
  statsClassName
608
609
  ),
609
- children: stats.map((stat, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
610
+ children: stats.map((stat, index) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
610
611
  index > 0 && /* @__PURE__ */ jsx("div", { className: "h-12 w-px bg-border hidden md:flex" }),
611
612
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 justify-between flex-row md:flex-col text-left md:text-center w-full md:w-fit border md:border-none rounded-xl md:rounded-none p-4 md:p-0", children: [
612
613
  /* @__PURE__ */ jsxs(
@@ -637,56 +638,66 @@ function HeroEventRegistration({
637
638
  }
638
639
  );
639
640
  }, [statsSlot, stats, statsClassName]);
640
- const renderLocation = useMemo(() => {
641
- if (locationSlot) return locationSlot;
642
- if (!locationLabel && !locationSublabel) return null;
643
- return /* @__PURE__ */ jsx(
644
- "div",
645
- {
646
- className: cn(
647
- "bg-card text-card-foreground",
648
- "rounded-2xl p-2 md:p-4 shadow-lg",
649
- "absolute bottom-0 translate-y-1/2",
650
- "left-1/2 -translate-x-1/2 w-[90%]",
651
- "md:-left-4 md:translate-x-0 md:w-auto",
652
- "ring-4 ring-primary"
653
- ),
654
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
655
- /* @__PURE__ */ jsx(
656
- "div",
657
- {
658
- className: cn(
659
- "flex items-center justify-center shrink-0",
660
- "size-12 rounded-xl bg-primary text-primary-foreground"
661
- ),
662
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
663
- }
641
+ const buildLocation = React4.useCallback(
642
+ (positioned) => {
643
+ if (locationSlot) return locationSlot;
644
+ if (!locationLabel && !locationSublabel) return null;
645
+ return /* @__PURE__ */ jsx(
646
+ "div",
647
+ {
648
+ className: cn(
649
+ "bg-card text-card-foreground",
650
+ "rounded-2xl p-2 md:p-4 shadow-lg",
651
+ "ring-4 ring-primary",
652
+ positioned ? cn(
653
+ "absolute bottom-0 translate-y-1/2",
654
+ "left-1/2 -translate-x-1/2 w-[90%]",
655
+ "md:-left-4 md:translate-x-0 md:w-auto"
656
+ ) : "w-full md:w-fit"
664
657
  ),
665
- /* @__PURE__ */ jsxs(
666
- "div",
667
- {
668
- className: cn(
669
- "flex flex-col items-start justify-center",
670
- "text-card-foreground gap-0 pr-0 md:pr-2"
671
- ),
672
- children: [
673
- locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
674
- locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsx(
675
- "div",
676
- {
677
- className: cn(
678
- "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
679
- ),
680
- children: locationSublabel
681
- }
682
- ) : locationSublabel)
683
- ]
684
- }
685
- )
686
- ] })
687
- }
688
- );
689
- }, [locationSlot, locationLabel, locationSublabel]);
658
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
659
+ /* @__PURE__ */ jsx(
660
+ "div",
661
+ {
662
+ className: cn(
663
+ "flex items-center justify-center shrink-0",
664
+ "size-12 rounded-xl bg-primary text-primary-foreground"
665
+ ),
666
+ children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
667
+ }
668
+ ),
669
+ /* @__PURE__ */ jsxs(
670
+ "div",
671
+ {
672
+ className: cn(
673
+ "flex flex-col items-start justify-center",
674
+ "text-card-foreground gap-0 pr-0 md:pr-2"
675
+ ),
676
+ children: [
677
+ locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
678
+ locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsx(
679
+ "div",
680
+ {
681
+ className: cn(
682
+ "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
683
+ ),
684
+ children: locationSublabel
685
+ }
686
+ ) : locationSublabel)
687
+ ]
688
+ }
689
+ )
690
+ ] })
691
+ }
692
+ );
693
+ },
694
+ [locationSlot, locationLabel, locationSublabel]
695
+ );
696
+ const renderLocation = useMemo(() => buildLocation(true), [buildLocation]);
697
+ const renderInlineLocation = useMemo(
698
+ () => buildLocation(false),
699
+ [buildLocation]
700
+ );
690
701
  const renderImage = useMemo(() => {
691
702
  if (imageSlot) return imageSlot;
692
703
  if (!image) return null;
@@ -715,6 +726,7 @@ function HeroEventRegistration({
715
726
  }, [imageSlot, image, imageClassName, optixFlowConfig, renderLocation]);
716
727
  const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
717
728
  const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
729
+ const locationInImage = !imageSlot && Boolean(image);
718
730
  return /* @__PURE__ */ jsx(
719
731
  Section,
720
732
  {
@@ -763,6 +775,7 @@ function HeroEventRegistration({
763
775
  }
764
776
  ) : heading),
765
777
  description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description),
778
+ !locationInImage && renderInlineLocation,
766
779
  /* @__PURE__ */ jsx(
767
780
  BlockActions,
768
781
  {
package/dist/registry.cjs CHANGED
@@ -44444,10 +44444,9 @@ function TestimonialsListVerified({
44444
44444
  ] }),
44445
44445
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-base flex-col items-start", children: [
44446
44446
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: review.author }) : review.author),
44447
- review.verified && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
44447
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
44448
44448
  /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
44449
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
44450
- !verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Verified Purchase" })
44449
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
44451
44450
  ] })
44452
44451
  ] })
44453
44452
  ]
@@ -44632,10 +44631,9 @@ function TestimonialsImagesHelpful({
44632
44631
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-0", children: [
44633
44632
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-col md:flex-row", children: [
44634
44633
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: review.author }) : review.author),
44635
- review.verified && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
44634
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
44636
44635
  /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
44637
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
44638
- !verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Verified Purchase" })
44636
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
44639
44637
  ] })
44640
44638
  ] }),
44641
44639
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
@@ -48337,7 +48335,7 @@ function TestimonialsParallaxNumber({
48337
48335
  ),
48338
48336
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex", children: [
48339
48337
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center border-r-0 md:border-r border-border/30 pr-4 md:pr-16", children: [
48340
- /* @__PURE__ */ jsxRuntime.jsxs(
48338
+ verticalLabel && /* @__PURE__ */ jsxRuntime.jsx(
48341
48339
  framerMotion.motion.span,
48342
48340
  {
48343
48341
  className: "text-sm tracking-widest uppercase",
@@ -48345,10 +48343,7 @@ function TestimonialsParallaxNumber({
48345
48343
  initial: { opacity: 0 },
48346
48344
  animate: { opacity: 1 },
48347
48345
  transition: { delay: 0.3 },
48348
- children: [
48349
- verticalLabel && (typeof verticalLabel === "string" ? verticalLabel : verticalLabel),
48350
- !verticalLabel && "Testimonials"
48351
- ]
48346
+ children: verticalLabel
48352
48347
  }
48353
48348
  ),
48354
48349
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative mt-8 h-32 w-4 bg-muted ring-2 ring-primary rounded", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -61969,6 +61964,7 @@ function HeroEventRegistration({
61969
61964
  }) {
61970
61965
  const renderBadge = React30.useMemo(() => {
61971
61966
  if (badgeSlot) return badgeSlot;
61967
+ if (!badgeText && !badgeIcon) return null;
61972
61968
  return /* @__PURE__ */ jsxRuntime.jsxs(Badge, { className: "px-4 py-1 gap-2", children: [
61973
61969
  badgeIcon && /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: badgeIcon, size: 18 }),
61974
61970
  badgeText
@@ -62015,56 +62011,66 @@ function HeroEventRegistration({
62015
62011
  }
62016
62012
  );
62017
62013
  }, [statsSlot, stats, statsClassName]);
62018
- const renderLocation = React30.useMemo(() => {
62019
- if (locationSlot) return locationSlot;
62020
- if (!locationLabel && !locationSublabel) return null;
62021
- return /* @__PURE__ */ jsxRuntime.jsx(
62022
- "div",
62023
- {
62024
- className: cn(
62025
- "bg-card text-card-foreground",
62026
- "rounded-2xl p-2 md:p-4 shadow-lg",
62027
- "absolute bottom-0 translate-y-1/2",
62028
- "left-1/2 -translate-x-1/2 w-[90%]",
62029
- "md:-left-4 md:translate-x-0 md:w-auto",
62030
- "ring-4 ring-primary"
62031
- ),
62032
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
62033
- /* @__PURE__ */ jsxRuntime.jsx(
62034
- "div",
62035
- {
62036
- className: cn(
62037
- "flex items-center justify-center shrink-0",
62038
- "size-12 rounded-xl bg-primary text-primary-foreground"
62039
- ),
62040
- children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
62041
- }
62014
+ const buildLocation = React30__namespace.useCallback(
62015
+ (positioned) => {
62016
+ if (locationSlot) return locationSlot;
62017
+ if (!locationLabel && !locationSublabel) return null;
62018
+ return /* @__PURE__ */ jsxRuntime.jsx(
62019
+ "div",
62020
+ {
62021
+ className: cn(
62022
+ "bg-card text-card-foreground",
62023
+ "rounded-2xl p-2 md:p-4 shadow-lg",
62024
+ "ring-4 ring-primary",
62025
+ positioned ? cn(
62026
+ "absolute bottom-0 translate-y-1/2",
62027
+ "left-1/2 -translate-x-1/2 w-[90%]",
62028
+ "md:-left-4 md:translate-x-0 md:w-auto"
62029
+ ) : "w-full md:w-fit"
62042
62030
  ),
62043
- /* @__PURE__ */ jsxRuntime.jsxs(
62044
- "div",
62045
- {
62046
- className: cn(
62047
- "flex flex-col items-start justify-center",
62048
- "text-card-foreground gap-0 pr-0 md:pr-2"
62049
- ),
62050
- children: [
62051
- locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
62052
- locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
62053
- "div",
62054
- {
62055
- className: cn(
62056
- "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
62057
- ),
62058
- children: locationSublabel
62059
- }
62060
- ) : locationSublabel)
62061
- ]
62062
- }
62063
- )
62064
- ] })
62065
- }
62066
- );
62067
- }, [locationSlot, locationLabel, locationSublabel]);
62031
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
62032
+ /* @__PURE__ */ jsxRuntime.jsx(
62033
+ "div",
62034
+ {
62035
+ className: cn(
62036
+ "flex items-center justify-center shrink-0",
62037
+ "size-12 rounded-xl bg-primary text-primary-foreground"
62038
+ ),
62039
+ children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
62040
+ }
62041
+ ),
62042
+ /* @__PURE__ */ jsxRuntime.jsxs(
62043
+ "div",
62044
+ {
62045
+ className: cn(
62046
+ "flex flex-col items-start justify-center",
62047
+ "text-card-foreground gap-0 pr-0 md:pr-2"
62048
+ ),
62049
+ children: [
62050
+ locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
62051
+ locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
62052
+ "div",
62053
+ {
62054
+ className: cn(
62055
+ "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
62056
+ ),
62057
+ children: locationSublabel
62058
+ }
62059
+ ) : locationSublabel)
62060
+ ]
62061
+ }
62062
+ )
62063
+ ] })
62064
+ }
62065
+ );
62066
+ },
62067
+ [locationSlot, locationLabel, locationSublabel]
62068
+ );
62069
+ const renderLocation = React30.useMemo(() => buildLocation(true), [buildLocation]);
62070
+ const renderInlineLocation = React30.useMemo(
62071
+ () => buildLocation(false),
62072
+ [buildLocation]
62073
+ );
62068
62074
  const renderImage = React30.useMemo(() => {
62069
62075
  if (imageSlot2) return imageSlot2;
62070
62076
  if (!image) return null;
@@ -62093,6 +62099,7 @@ function HeroEventRegistration({
62093
62099
  }, [imageSlot2, image, imageClassName, optixFlowConfig, renderLocation]);
62094
62100
  const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
62095
62101
  const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
62102
+ const locationInImage = !imageSlot2 && Boolean(image);
62096
62103
  return /* @__PURE__ */ jsxRuntime.jsx(
62097
62104
  Section,
62098
62105
  {
@@ -62141,6 +62148,7 @@ function HeroEventRegistration({
62141
62148
  }
62142
62149
  ) : heading),
62143
62150
  description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description),
62151
+ !locationInImage && renderInlineLocation,
62144
62152
  /* @__PURE__ */ jsxRuntime.jsx(
62145
62153
  BlockActions,
62146
62154
  {
@@ -113952,7 +113960,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
113952
113960
  background="white"
113953
113961
  />
113954
113962
  `.trim(),
113955
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. Each review needs a rating (1\u20135), a title, content, and an author. The verified flag should only be set when the review platform actually verifies purchases. avatarSrc must be an absolute image URL.",
113963
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. Each review needs a rating (1\u20135), a title, content, and an author. The verified flag should only be set when the review platform actually verifies purchases. avatarSrc must be an absolute image URL. The verified indicator renders ONLY when verifiedPurchaseLabel is supplied \u2014 there is NO fallback wording; choose a label that fits the client's industry (e.g. 'Verified' / 'Verified Diner' / 'Verified Guest') or omit the prop to hide the indicator entirely.",
113956
113964
  usageRequirements: {
113957
113965
  requiredProps: ["reviews"],
113958
113966
  propConstraints: {
@@ -114024,7 +114032,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
114024
114032
  exampleUsage: `
114025
114033
  <TestimonialsImagesHelpful
114026
114034
  heading="Customer Reviews"
114027
- verifiedPurchaseLabel="Verified Purchase"
114035
+ verifiedPurchaseLabel="Verified"
114028
114036
  reviews={[
114029
114037
  {
114030
114038
  rating: 5,
@@ -114050,7 +114058,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
114050
114058
  ]}
114051
114059
  />
114052
114060
  `.trim(),
114053
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. The images[] array holds supplementary review photos from the reviewer \u2014 these must be real product/experience photos, not stock imagery. helpful counts must reflect actual platform data.",
114061
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. The images[] array holds supplementary review photos from the reviewer \u2014 these must be real product/experience photos, not stock imagery. helpful counts must reflect actual platform data. The verified indicator renders ONLY when verifiedPurchaseLabel is supplied \u2014 there is NO fallback wording; choose a label that fits the client's industry (e.g. 'Verified' / 'Verified Diner' / 'Verified Guest') or omit the prop to hide the indicator entirely.",
114054
114062
  usageRequirements: {
114055
114063
  requiredProps: ["reviews"],
114056
114064
  propConstraints: {
@@ -114090,7 +114098,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
114090
114098
  },
114091
114099
  exampleProps: {
114092
114100
  heading: "Customer Reviews",
114093
- verifiedPurchaseLabel: "Verified Purchase",
114101
+ verifiedPurchaseLabel: "Verified",
114094
114102
  reviews: [
114095
114103
  {
114096
114104
  rating: 5,
@@ -115374,7 +115382,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
115374
115382
  spacing="xl"
115375
115383
  />
115376
115384
  `.trim(),
115377
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. backgroundIcon is a decorative Iconify icon ID (e.g., 'lucide/rocket') rendered as a large watermark behind the testimonial number \u2014 use icons that complement the testimonial theme. backgroundLabel is optional decorative text.",
115385
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. backgroundIcon is a decorative Iconify icon ID (e.g., 'lucide/rocket') rendered as a large watermark behind the testimonial number \u2014 use icons that complement the testimonial theme. backgroundLabel is optional decorative text. The vertical side label renders ONLY when verticalLabel is supplied \u2014 there is NO fallback wording; choose industry-appropriate text or omit the prop to hide it.",
115378
115386
  usageRequirements: {
115379
115387
  requiredProps: ["testimonials"],
115380
115388
  propConstraints: {
@@ -117523,6 +117531,7 @@ var CONTACT_BLOCK_CONTRACTS = {
117523
117531
  };
117524
117532
  var HERO_EXAMPLE_IMAGE_URL = "https://cdn.ing/assets/i/r/308196/g6bbn73f7gxal82uu49m9prfd0u8/workplace-in-cafe.webp";
117525
117533
  var HERO_MEDIA_NOTE = "All media src values must be absolute URLs to real assets; relative paths and placeholder media variables are not allowed.";
117534
+ var EVENTS_FEED_NOTE = "Dynamic feeds (Phase 4): this block can carry a block-level dataSource of type 'events_feed' (expands: true) \u2014 ONE symbolic block hydrates at routing-build time into N hero-event-registration instances, one per event occurrence (dataSource.limit default 6, hard cap 12). Wire mapping (\xA74.1d; never fabricate \u2014 omit any field with no real data): title -> heading, description -> description (omitted when blank), starts_at -> badgeText (short date badge, e.g. 'JUL 18'), starts_at in the event timezone -> locationLabel, location_name or custom_address -> locationSublabel (whichever is real; omitted when neither), image_url -> image ({src, alt: title}, only when an image exists), price_from -> stats[{value: '$X', label: 'From'}], recurring_summary -> stats[{value, label: 'Schedule'}], registration_url -> actions[{label: 'Register', href}]. stats, actions, and image are OMITTED entirely when no real data exists (the block null-guards every region; the propConstraints minItems/maxItems are AI-authoring constraints, not runtime requirements). The 'events' capability is SOFT: hero-event-registration is dual-use and remains legitimate for authored single-event / catering usage, so octane must NOT hard-drop the block on the capability alone \u2014 only feed-driven usage is gated.";
117526
117535
  var heroCapabilities = (...capabilities) => capabilities;
117527
117536
  var EXAMPLE_VIDEO_0 = {
117528
117537
  masterPlaylistUrl: "https://cdn.ing/assets/video/uploads/283393/hls/38865/master.m3u8",
@@ -121086,7 +121095,7 @@ var HERO_BLOCK_CONTRACTS = {
121086
121095
  background="dark"
121087
121096
  />
121088
121097
  `.trim(),
121089
- importantUsageNotes: `Only use if you have real event details. Only supply real stats and location data \u2014 do not fabricate. Requires a real 'image'. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. ${HERO_MEDIA_NOTE}`,
121098
+ importantUsageNotes: `Only use if you have real event details. Only supply real stats and location data \u2014 do not fabricate. Image strongly preferred; omit when none exists \u2014 never use a stock/unrelated image. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. ${HERO_MEDIA_NOTE} ${EVENTS_FEED_NOTE}`,
121090
121099
  usageRequirements: {
121091
121100
  requiredProps: ["heading"],
121092
121101
  propConstraints: {
@@ -135841,7 +135850,7 @@ function createBuilderContractBundle({
135841
135850
  symbolic: true,
135842
135851
  hydrationOwner: "dashtrack-ai",
135843
135852
  hydrationPhase: "routing-build",
135844
- canonicalPayloadExpectation: "Keep events feed requests symbolic in canonical page JSON until routing-build hydration resolves them.",
135853
+ canonicalPayloadExpectation: "Keep events feed requests symbolic in canonical page JSON until routing-build hydration resolves them. events_feed is the first EXPANDING source (expands: true): ONE symbolic block hydrates into N hero-event-registration block instances, one per event occurrence (limit default 6, hard cap 12). Wire mapping (\xA74.1d; never fabricate \u2014 omit any field with no real data): title -> heading, description -> description (omitted when blank), starts_at -> badgeText (short date badge, e.g. 'JUL 18'), starts_at in the event timezone -> locationLabel, location_name or custom_address -> locationSublabel, image_url -> image ({src, alt: title}, only when present), price_from -> stats[{value: '$X', label: 'From'}], recurring_summary -> stats[{value, label: 'Schedule'}], registration_url -> actions[{label: 'Register', href}]. stats, actions, and image are omitted entirely when no real data exists. The 'events' capability is soft: hero-event-registration is dual-use (authored single-event/catering usage stays legitimate), so octane must not hard-drop on the capability alone.",
135845
135854
  requiredFields: ["type"],
135846
135855
  optionalFields: ["limit", "upcomingOnly", "locationIds", "bindTo"],
135847
135856
  expands: true
package/dist/registry.js CHANGED
@@ -44404,10 +44404,9 @@ function TestimonialsListVerified({
44404
44404
  ] }),
44405
44405
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-base flex-col items-start", children: [
44406
44406
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
44407
- review.verified && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
44407
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
44408
44408
  /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
44409
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
44410
- !verifiedPurchaseLabel && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Verified Purchase" })
44409
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
44411
44410
  ] })
44412
44411
  ] })
44413
44412
  ]
@@ -44592,10 +44591,9 @@ function TestimonialsImagesHelpful({
44592
44591
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-0", children: [
44593
44592
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-col md:flex-row", children: [
44594
44593
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
44595
- review.verified && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
44594
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
44596
44595
  /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
44597
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
44598
- !verifiedPurchaseLabel && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Verified Purchase" })
44596
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
44599
44597
  ] })
44600
44598
  ] }),
44601
44599
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
@@ -48297,7 +48295,7 @@ function TestimonialsParallaxNumber({
48297
48295
  ),
48298
48296
  /* @__PURE__ */ jsxs("div", { className: "relative flex", children: [
48299
48297
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center border-r-0 md:border-r border-border/30 pr-4 md:pr-16", children: [
48300
- /* @__PURE__ */ jsxs(
48298
+ verticalLabel && /* @__PURE__ */ jsx(
48301
48299
  motion.span,
48302
48300
  {
48303
48301
  className: "text-sm tracking-widest uppercase",
@@ -48305,10 +48303,7 @@ function TestimonialsParallaxNumber({
48305
48303
  initial: { opacity: 0 },
48306
48304
  animate: { opacity: 1 },
48307
48305
  transition: { delay: 0.3 },
48308
- children: [
48309
- verticalLabel && (typeof verticalLabel === "string" ? verticalLabel : verticalLabel),
48310
- !verticalLabel && "Testimonials"
48311
- ]
48306
+ children: verticalLabel
48312
48307
  }
48313
48308
  ),
48314
48309
  /* @__PURE__ */ jsx("div", { className: "relative mt-8 h-32 w-4 bg-muted ring-2 ring-primary rounded", children: /* @__PURE__ */ jsx(
@@ -61929,6 +61924,7 @@ function HeroEventRegistration({
61929
61924
  }) {
61930
61925
  const renderBadge = useMemo(() => {
61931
61926
  if (badgeSlot) return badgeSlot;
61927
+ if (!badgeText && !badgeIcon) return null;
61932
61928
  return /* @__PURE__ */ jsxs(Badge, { className: "px-4 py-1 gap-2", children: [
61933
61929
  badgeIcon && /* @__PURE__ */ jsx(DynamicIcon, { name: badgeIcon, size: 18 }),
61934
61930
  badgeText
@@ -61975,56 +61971,66 @@ function HeroEventRegistration({
61975
61971
  }
61976
61972
  );
61977
61973
  }, [statsSlot, stats, statsClassName]);
61978
- const renderLocation = useMemo(() => {
61979
- if (locationSlot) return locationSlot;
61980
- if (!locationLabel && !locationSublabel) return null;
61981
- return /* @__PURE__ */ jsx(
61982
- "div",
61983
- {
61984
- className: cn(
61985
- "bg-card text-card-foreground",
61986
- "rounded-2xl p-2 md:p-4 shadow-lg",
61987
- "absolute bottom-0 translate-y-1/2",
61988
- "left-1/2 -translate-x-1/2 w-[90%]",
61989
- "md:-left-4 md:translate-x-0 md:w-auto",
61990
- "ring-4 ring-primary"
61991
- ),
61992
- children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
61993
- /* @__PURE__ */ jsx(
61994
- "div",
61995
- {
61996
- className: cn(
61997
- "flex items-center justify-center shrink-0",
61998
- "size-12 rounded-xl bg-primary text-primary-foreground"
61999
- ),
62000
- children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
62001
- }
61974
+ const buildLocation = React30.useCallback(
61975
+ (positioned) => {
61976
+ if (locationSlot) return locationSlot;
61977
+ if (!locationLabel && !locationSublabel) return null;
61978
+ return /* @__PURE__ */ jsx(
61979
+ "div",
61980
+ {
61981
+ className: cn(
61982
+ "bg-card text-card-foreground",
61983
+ "rounded-2xl p-2 md:p-4 shadow-lg",
61984
+ "ring-4 ring-primary",
61985
+ positioned ? cn(
61986
+ "absolute bottom-0 translate-y-1/2",
61987
+ "left-1/2 -translate-x-1/2 w-[90%]",
61988
+ "md:-left-4 md:translate-x-0 md:w-auto"
61989
+ ) : "w-full md:w-fit"
62002
61990
  ),
62003
- /* @__PURE__ */ jsxs(
62004
- "div",
62005
- {
62006
- className: cn(
62007
- "flex flex-col items-start justify-center",
62008
- "text-card-foreground gap-0 pr-0 md:pr-2"
62009
- ),
62010
- children: [
62011
- locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
62012
- locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsx(
62013
- "div",
62014
- {
62015
- className: cn(
62016
- "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
62017
- ),
62018
- children: locationSublabel
62019
- }
62020
- ) : locationSublabel)
62021
- ]
62022
- }
62023
- )
62024
- ] })
62025
- }
62026
- );
62027
- }, [locationSlot, locationLabel, locationSublabel]);
61991
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
61992
+ /* @__PURE__ */ jsx(
61993
+ "div",
61994
+ {
61995
+ className: cn(
61996
+ "flex items-center justify-center shrink-0",
61997
+ "size-12 rounded-xl bg-primary text-primary-foreground"
61998
+ ),
61999
+ children: /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/map-pin", size: 24 })
62000
+ }
62001
+ ),
62002
+ /* @__PURE__ */ jsxs(
62003
+ "div",
62004
+ {
62005
+ className: cn(
62006
+ "flex flex-col items-start justify-center",
62007
+ "text-card-foreground gap-0 pr-0 md:pr-2"
62008
+ ),
62009
+ children: [
62010
+ locationLabel && (typeof locationLabel === "string" ? /* @__PURE__ */ jsx("div", { className: "text-sm md:text-base text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal font-semibold", children: locationLabel }) : locationLabel),
62011
+ locationSublabel && (typeof locationSublabel === "string" ? /* @__PURE__ */ jsx(
62012
+ "div",
62013
+ {
62014
+ className: cn(
62015
+ "text-xs md:text-sm text-balance leading-tight md:leading-normal tracking-tighter md:tracking-normal"
62016
+ ),
62017
+ children: locationSublabel
62018
+ }
62019
+ ) : locationSublabel)
62020
+ ]
62021
+ }
62022
+ )
62023
+ ] })
62024
+ }
62025
+ );
62026
+ },
62027
+ [locationSlot, locationLabel, locationSublabel]
62028
+ );
62029
+ const renderLocation = useMemo(() => buildLocation(true), [buildLocation]);
62030
+ const renderInlineLocation = useMemo(
62031
+ () => buildLocation(false),
62032
+ [buildLocation]
62033
+ );
62028
62034
  const renderImage = useMemo(() => {
62029
62035
  if (imageSlot2) return imageSlot2;
62030
62036
  if (!image) return null;
@@ -62053,6 +62059,7 @@ function HeroEventRegistration({
62053
62059
  }, [imageSlot2, image, imageClassName, optixFlowConfig, renderLocation]);
62054
62060
  const desktopOrder = directionConfig.desktop === "mediaRight" ? "md:flex-row" : "md:flex-row-reverse";
62055
62061
  const mobileOrder = directionConfig.mobile === "mediaTop" ? "flex-col-reverse" : "flex-col";
62062
+ const locationInImage = !imageSlot2 && Boolean(image);
62056
62063
  return /* @__PURE__ */ jsx(
62057
62064
  Section,
62058
62065
  {
@@ -62101,6 +62108,7 @@ function HeroEventRegistration({
62101
62108
  }
62102
62109
  ) : heading),
62103
62110
  description && (typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: cn("text-lg text-balance", descriptionClassName), children: description }) : description),
62111
+ !locationInImage && renderInlineLocation,
62104
62112
  /* @__PURE__ */ jsx(
62105
62113
  BlockActions,
62106
62114
  {
@@ -113912,7 +113920,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
113912
113920
  background="white"
113913
113921
  />
113914
113922
  `.trim(),
113915
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. Each review needs a rating (1\u20135), a title, content, and an author. The verified flag should only be set when the review platform actually verifies purchases. avatarSrc must be an absolute image URL.",
113923
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. Each review needs a rating (1\u20135), a title, content, and an author. The verified flag should only be set when the review platform actually verifies purchases. avatarSrc must be an absolute image URL. The verified indicator renders ONLY when verifiedPurchaseLabel is supplied \u2014 there is NO fallback wording; choose a label that fits the client's industry (e.g. 'Verified' / 'Verified Diner' / 'Verified Guest') or omit the prop to hide the indicator entirely.",
113916
113924
  usageRequirements: {
113917
113925
  requiredProps: ["reviews"],
113918
113926
  propConstraints: {
@@ -113984,7 +113992,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
113984
113992
  exampleUsage: `
113985
113993
  <TestimonialsImagesHelpful
113986
113994
  heading="Customer Reviews"
113987
- verifiedPurchaseLabel="Verified Purchase"
113995
+ verifiedPurchaseLabel="Verified"
113988
113996
  reviews={[
113989
113997
  {
113990
113998
  rating: 5,
@@ -114010,7 +114018,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
114010
114018
  ]}
114011
114019
  />
114012
114020
  `.trim(),
114013
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. The images[] array holds supplementary review photos from the reviewer \u2014 these must be real product/experience photos, not stock imagery. helpful counts must reflect actual platform data.",
114021
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. The images[] array holds supplementary review photos from the reviewer \u2014 these must be real product/experience photos, not stock imagery. helpful counts must reflect actual platform data. The verified indicator renders ONLY when verifiedPurchaseLabel is supplied \u2014 there is NO fallback wording; choose a label that fits the client's industry (e.g. 'Verified' / 'Verified Diner' / 'Verified Guest') or omit the prop to hide the indicator entirely.",
114014
114022
  usageRequirements: {
114015
114023
  requiredProps: ["reviews"],
114016
114024
  propConstraints: {
@@ -114050,7 +114058,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
114050
114058
  },
114051
114059
  exampleProps: {
114052
114060
  heading: "Customer Reviews",
114053
- verifiedPurchaseLabel: "Verified Purchase",
114061
+ verifiedPurchaseLabel: "Verified",
114054
114062
  reviews: [
114055
114063
  {
114056
114064
  rating: 5,
@@ -115334,7 +115342,7 @@ var TESTIMONIALS_BLOCK_CONTRACTS = {
115334
115342
  spacing="xl"
115335
115343
  />
115336
115344
  `.trim(),
115337
- importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. backgroundIcon is a decorative Iconify icon ID (e.g., 'lucide/rocket') rendered as a large watermark behind the testimonial number \u2014 use icons that complement the testimonial theme. backgroundLabel is optional decorative text.",
115345
+ importantUsageNotes: "Testimonials must come from real, sourced reviews or testimonials. Do not fabricate quotes, names, or company affiliations. backgroundIcon is a decorative Iconify icon ID (e.g., 'lucide/rocket') rendered as a large watermark behind the testimonial number \u2014 use icons that complement the testimonial theme. backgroundLabel is optional decorative text. The vertical side label renders ONLY when verticalLabel is supplied \u2014 there is NO fallback wording; choose industry-appropriate text or omit the prop to hide it.",
115338
115346
  usageRequirements: {
115339
115347
  requiredProps: ["testimonials"],
115340
115348
  propConstraints: {
@@ -117483,6 +117491,7 @@ var CONTACT_BLOCK_CONTRACTS = {
117483
117491
  };
117484
117492
  var HERO_EXAMPLE_IMAGE_URL = "https://cdn.ing/assets/i/r/308196/g6bbn73f7gxal82uu49m9prfd0u8/workplace-in-cafe.webp";
117485
117493
  var HERO_MEDIA_NOTE = "All media src values must be absolute URLs to real assets; relative paths and placeholder media variables are not allowed.";
117494
+ var EVENTS_FEED_NOTE = "Dynamic feeds (Phase 4): this block can carry a block-level dataSource of type 'events_feed' (expands: true) \u2014 ONE symbolic block hydrates at routing-build time into N hero-event-registration instances, one per event occurrence (dataSource.limit default 6, hard cap 12). Wire mapping (\xA74.1d; never fabricate \u2014 omit any field with no real data): title -> heading, description -> description (omitted when blank), starts_at -> badgeText (short date badge, e.g. 'JUL 18'), starts_at in the event timezone -> locationLabel, location_name or custom_address -> locationSublabel (whichever is real; omitted when neither), image_url -> image ({src, alt: title}, only when an image exists), price_from -> stats[{value: '$X', label: 'From'}], recurring_summary -> stats[{value, label: 'Schedule'}], registration_url -> actions[{label: 'Register', href}]. stats, actions, and image are OMITTED entirely when no real data exists (the block null-guards every region; the propConstraints minItems/maxItems are AI-authoring constraints, not runtime requirements). The 'events' capability is SOFT: hero-event-registration is dual-use and remains legitimate for authored single-event / catering usage, so octane must NOT hard-drop the block on the capability alone \u2014 only feed-driven usage is gated.";
117486
117495
  var heroCapabilities = (...capabilities) => capabilities;
117487
117496
  var EXAMPLE_VIDEO_0 = {
117488
117497
  masterPlaylistUrl: "https://cdn.ing/assets/video/uploads/283393/hls/38865/master.m3u8",
@@ -121046,7 +121055,7 @@ var HERO_BLOCK_CONTRACTS = {
121046
121055
  background="dark"
121047
121056
  />
121048
121057
  `.trim(),
121049
- importantUsageNotes: `Only use if you have real event details. Only supply real stats and location data \u2014 do not fabricate. Requires a real 'image'. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. ${HERO_MEDIA_NOTE}`,
121058
+ importantUsageNotes: `Only use if you have real event details. Only supply real stats and location data \u2014 do not fabricate. Image strongly preferred; omit when none exists \u2014 never use a stock/unrelated image. Do not exceed 50 characters for 'heading'. Do not exceed 130 characters for 'description'. ${HERO_MEDIA_NOTE} ${EVENTS_FEED_NOTE}`,
121050
121059
  usageRequirements: {
121051
121060
  requiredProps: ["heading"],
121052
121061
  propConstraints: {
@@ -135801,7 +135810,7 @@ function createBuilderContractBundle({
135801
135810
  symbolic: true,
135802
135811
  hydrationOwner: "dashtrack-ai",
135803
135812
  hydrationPhase: "routing-build",
135804
- canonicalPayloadExpectation: "Keep events feed requests symbolic in canonical page JSON until routing-build hydration resolves them.",
135813
+ canonicalPayloadExpectation: "Keep events feed requests symbolic in canonical page JSON until routing-build hydration resolves them. events_feed is the first EXPANDING source (expands: true): ONE symbolic block hydrates into N hero-event-registration block instances, one per event occurrence (limit default 6, hard cap 12). Wire mapping (\xA74.1d; never fabricate \u2014 omit any field with no real data): title -> heading, description -> description (omitted when blank), starts_at -> badgeText (short date badge, e.g. 'JUL 18'), starts_at in the event timezone -> locationLabel, location_name or custom_address -> locationSublabel, image_url -> image ({src, alt: title}, only when present), price_from -> stats[{value: '$X', label: 'From'}], recurring_summary -> stats[{value, label: 'Schedule'}], registration_url -> actions[{label: 'Register', href}]. stats, actions, and image are omitted entirely when no real data exists. The 'events' capability is soft: hero-event-registration is dual-use (authored single-event/catering usage stays legitimate), so octane must not hard-drop on the capability alone.",
135805
135814
  requiredFields: ["type"],
135806
135815
  optionalFields: ["limit", "upcomingOnly", "locationIds", "bindTo"],
135807
135816
  expands: true
@@ -77,6 +77,6 @@ interface SocialLinkIconProps extends Omit<PressableProps, "children">, SocialLi
77
77
  * />
78
78
  * ```
79
79
  */
80
- declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | HTMLSpanElement>>;
80
+ declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement>>;
81
81
 
82
82
  export { SocialLinkIcon, type SocialLinkIconDynamicIconProps, type SocialLinkIconProps };
@@ -77,6 +77,6 @@ interface SocialLinkIconProps extends Omit<PressableProps, "children">, SocialLi
77
77
  * />
78
78
  * ```
79
79
  */
80
- declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | HTMLSpanElement>>;
80
+ declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement>>;
81
81
 
82
82
  export { SocialLinkIcon, type SocialLinkIconDynamicIconProps, type SocialLinkIconProps };
@@ -636,10 +636,9 @@ function TestimonialsImagesHelpful({
636
636
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-0", children: [
637
637
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-col md:flex-row", children: [
638
638
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: review.author }) : review.author),
639
- review.verified && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
639
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
640
640
  /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
641
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
642
- !verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Verified Purchase" })
641
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
643
642
  ] })
644
643
  ] }),
645
644
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
@@ -613,10 +613,9 @@ function TestimonialsImagesHelpful({
613
613
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-0", children: [
614
614
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-col md:flex-row", children: [
615
615
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
616
- review.verified && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
616
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
617
617
  /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
618
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
619
- !verifiedPurchaseLabel && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Verified Purchase" })
618
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
620
619
  ] })
621
620
  ] }),
622
621
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
@@ -558,10 +558,9 @@ function TestimonialsListVerified({
558
558
  ] }),
559
559
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 text-base flex-col items-start", children: [
560
560
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: review.author }) : review.author),
561
- review.verified && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
561
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1", children: [
562
562
  /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
563
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
564
- !verifiedPurchaseLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Verified Purchase" })
563
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
565
564
  ] })
566
565
  ] })
567
566
  ]
@@ -535,10 +535,9 @@ function TestimonialsListVerified({
535
535
  ] }),
536
536
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-base flex-col items-start", children: [
537
537
  review.author && (typeof review.author === "string" ? /* @__PURE__ */ jsx("span", { className: "font-medium", children: review.author }) : review.author),
538
- review.verified && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
538
+ review.verified && verifiedPurchaseLabel && /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
539
539
  /* @__PURE__ */ jsx(DynamicIcon, { name: "lucide/badge-check", size: 18 }),
540
- verifiedPurchaseLabel && (typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel),
541
- !verifiedPurchaseLabel && /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Verified Purchase" })
540
+ typeof verifiedPurchaseLabel === "string" ? /* @__PURE__ */ jsx("span", { className: "text-sm", children: verifiedPurchaseLabel }) : verifiedPurchaseLabel
542
541
  ] })
543
542
  ] })
544
543
  ]
@@ -554,7 +554,7 @@ function TestimonialsParallaxNumber({
554
554
  ),
555
555
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex", children: [
556
556
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center border-r-0 md:border-r border-border/30 pr-4 md:pr-16", children: [
557
- /* @__PURE__ */ jsxRuntime.jsxs(
557
+ verticalLabel && /* @__PURE__ */ jsxRuntime.jsx(
558
558
  framerMotion.motion.span,
559
559
  {
560
560
  className: "text-sm tracking-widest uppercase",
@@ -562,10 +562,7 @@ function TestimonialsParallaxNumber({
562
562
  initial: { opacity: 0 },
563
563
  animate: { opacity: 1 },
564
564
  transition: { delay: 0.3 },
565
- children: [
566
- verticalLabel && (typeof verticalLabel === "string" ? verticalLabel : verticalLabel),
567
- !verticalLabel && "Testimonials"
568
- ]
565
+ children: verticalLabel
569
566
  }
570
567
  ),
571
568
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative mt-8 h-32 w-4 bg-muted ring-2 ring-primary rounded", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -533,7 +533,7 @@ function TestimonialsParallaxNumber({
533
533
  ),
534
534
  /* @__PURE__ */ jsxs("div", { className: "relative flex", children: [
535
535
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center border-r-0 md:border-r border-border/30 pr-4 md:pr-16", children: [
536
- /* @__PURE__ */ jsxs(
536
+ verticalLabel && /* @__PURE__ */ jsx(
537
537
  motion.span,
538
538
  {
539
539
  className: "text-sm tracking-widest uppercase",
@@ -541,10 +541,7 @@ function TestimonialsParallaxNumber({
541
541
  initial: { opacity: 0 },
542
542
  animate: { opacity: 1 },
543
543
  transition: { delay: 0.3 },
544
- children: [
545
- verticalLabel && (typeof verticalLabel === "string" ? verticalLabel : verticalLabel),
546
- !verticalLabel && "Testimonials"
547
- ]
544
+ children: verticalLabel
548
545
  }
549
546
  ),
550
547
  /* @__PURE__ */ jsx("div", { className: "relative mt-8 h-32 w-4 bg-muted ring-2 ring-primary rounded", children: /* @__PURE__ */ jsx(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensite/ui",
3
- "version": "3.13.0",
3
+ "version": "3.14.0",
4
4
  "description": "Foundational UI component library for OpenSite Semantic Site Builder with tree-shakable exports and abstract styling",
5
5
  "keywords": [
6
6
  "react",