@opensite/ui 3.3.6 → 3.3.7

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.
@@ -8,6 +8,9 @@ var img = require('@page-speed/img');
8
8
  var lightbox = require('@page-speed/lightbox');
9
9
  var jsxRuntime = require('react/jsx-runtime');
10
10
  var icon = require('@page-speed/icon');
11
+ var reactSlot = require('@radix-ui/react-slot');
12
+ var classVarianceAuthority = require('class-variance-authority');
13
+ var pressable = require('@page-speed/pressable');
11
14
 
12
15
  function _interopNamespace(e) {
13
16
  if (e && e.__esModule) return e;
@@ -422,9 +425,110 @@ var DynamicIcon = React__namespace.memo(function DynamicIcon2({
422
425
  return /* @__PURE__ */ jsxRuntime.jsx(icon.Icon, { ...props, name, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
423
426
  });
424
427
  DynamicIcon.displayName = "DynamicIcon";
428
+ var badgeVariants = classVarianceAuthority.cva(
429
+ "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",
430
+ {
431
+ variants: {
432
+ variant: {
433
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
434
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
435
+ 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",
436
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
437
+ }
438
+ },
439
+ defaultVariants: {
440
+ variant: "default"
441
+ }
442
+ }
443
+ );
444
+ function Badge({
445
+ className,
446
+ variant,
447
+ asChild = false,
448
+ ...props
449
+ }) {
450
+ const Comp = asChild ? reactSlot.Slot : "span";
451
+ return /* @__PURE__ */ jsxRuntime.jsx(
452
+ Comp,
453
+ {
454
+ "data-slot": "badge",
455
+ className: cn(badgeVariants({ variant }), className),
456
+ ...props
457
+ }
458
+ );
459
+ }
460
+ var MOBILE_CLASSES = {
461
+ "fit-left": "items-start md:items-center",
462
+ "fit-center": "items-center",
463
+ "fit-right": "items-end md:items-center",
464
+ "full-left": "items-stretch md:items-center",
465
+ "full-center": "items-stretch md:items-center",
466
+ "full-right": "items-stretch md:items-center"
467
+ };
468
+ function BlockActions({
469
+ mobileConfig,
470
+ actionsClassName,
471
+ verticalSpacing = "mt-4 md:mt-8",
472
+ actions,
473
+ actionsSlot
474
+ }) {
475
+ const width = mobileConfig?.width ?? "full";
476
+ const position = mobileConfig?.position ?? "center";
477
+ const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
478
+ if (actionsSlot) {
479
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: actionsSlot });
480
+ } else if (actions && actions?.length > 0) {
481
+ return /* @__PURE__ */ jsxRuntime.jsx(
482
+ "div",
483
+ {
484
+ className: cn(
485
+ "flex flex-col md:flex-row flex-wrap gap-4",
486
+ mobileLayoutClass,
487
+ actionsClassName,
488
+ verticalSpacing
489
+ ),
490
+ children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(ActionComponent, { action }, index))
491
+ }
492
+ );
493
+ } else {
494
+ return null;
495
+ }
496
+ }
497
+ function ActionComponent({ action }) {
498
+ const {
499
+ label,
500
+ icon,
501
+ iconAfter,
502
+ children,
503
+ href,
504
+ onClick,
505
+ className: actionClassName,
506
+ ...pressableProps
507
+ } = action;
508
+ return /* @__PURE__ */ jsxRuntime.jsx(
509
+ pressable.Pressable,
510
+ {
511
+ href,
512
+ onClick,
513
+ asButton: action.asButton ?? true,
514
+ className: actionClassName,
515
+ ...pressableProps,
516
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
517
+ icon,
518
+ label,
519
+ iconAfter
520
+ ] })
521
+ }
522
+ );
523
+ }
425
524
  function HeroFloatingImages({
426
525
  sectionId = "hero-floating-images",
427
- children,
526
+ badge,
527
+ badgeIcon,
528
+ heading,
529
+ description,
530
+ actions,
531
+ actionsSlot,
428
532
  images,
429
533
  imagesSlot,
430
534
  zoomIconName = "lucide/zoom-in",
@@ -435,6 +539,10 @@ function HeroFloatingImages({
435
539
  className,
436
540
  gridClassName,
437
541
  contentClassName,
542
+ badgeClassName,
543
+ headingClassName,
544
+ descriptionClassName,
545
+ actionsClassName,
438
546
  galleryClassName,
439
547
  featuredImageClassName,
440
548
  secondaryImageClassName,
@@ -610,8 +718,10 @@ function HeroFloatingImages({
610
718
  secondaryImagesContent
611
719
  ]);
612
720
  const hasContent = React.useMemo(() => {
613
- return children !== void 0 && children !== null;
614
- }, [children]);
721
+ return Boolean(
722
+ badge || badgeIcon || heading || description || actionsSlot || actions && actions.length > 0
723
+ );
724
+ }, [actions, actionsSlot, badge, badgeIcon, description, heading]);
615
725
  const hasGallery = React.useMemo(() => {
616
726
  return imagesSlot || images && images.length > 0;
617
727
  }, [imagesSlot, images]);
@@ -634,7 +744,48 @@ function HeroFloatingImages({
634
744
  gridClassName
635
745
  ),
636
746
  children: [
637
- hasContent ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col justify-center", contentClassName), children }) : null,
747
+ hasContent ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col justify-center", contentClassName), children: [
748
+ (badge || badgeIcon) && /* @__PURE__ */ jsxRuntime.jsxs(
749
+ Badge,
750
+ {
751
+ variant: "secondary",
752
+ className: cn("mb-6 w-fit", badgeClassName),
753
+ children: [
754
+ badge,
755
+ badgeIcon
756
+ ]
757
+ }
758
+ ),
759
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
760
+ "h1",
761
+ {
762
+ className: cn(
763
+ "mb-6 text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl",
764
+ headingClassName
765
+ ),
766
+ children: heading
767
+ }
768
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
769
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
770
+ "p",
771
+ {
772
+ className: cn(
773
+ "mb-8 max-w-lg text-lg text-muted-foreground",
774
+ descriptionClassName
775
+ ),
776
+ children: description
777
+ }
778
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
779
+ /* @__PURE__ */ jsxRuntime.jsx(
780
+ BlockActions,
781
+ {
782
+ actions,
783
+ actionsSlot,
784
+ actionsClassName,
785
+ verticalSpacing: description ? "mt-0" : void 0
786
+ }
787
+ )
788
+ ] }) : null,
638
789
  hasGallery ? galleryContent : null
639
790
  ]
640
791
  }
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-Cgd-IXlI.cjs';
3
- import { O as OptixFlowConfig } from './blocks-DyouPohq.cjs';
3
+ import { A as ActionConfig, O as OptixFlowConfig } from './blocks-DyouPohq.cjs';
4
4
  import 'react/jsx-runtime';
5
5
  import 'class-variance-authority';
6
6
  import '@page-speed/pressable';
@@ -30,11 +30,29 @@ interface HeroFloatingImagesImage {
30
30
  }
31
31
  interface HeroFloatingImagesProps {
32
32
  /**
33
- * Flexible content slot for the left side of the hero.
34
- * Renders any content the application/AI builder provides (badges, headings, descriptions, actions, etc.)
35
- * This allows maximum flexibility without prescribing specific content structure.
33
+ * Badge content displayed above the heading
36
34
  */
37
- children?: React.ReactNode;
35
+ badge?: React.ReactNode;
36
+ /**
37
+ * Badge icon
38
+ */
39
+ badgeIcon?: React.ReactNode;
40
+ /**
41
+ * Main heading content
42
+ */
43
+ heading?: React.ReactNode;
44
+ /**
45
+ * Description text below heading
46
+ */
47
+ description?: React.ReactNode;
48
+ /**
49
+ * Array of action configurations for CTA buttons
50
+ */
51
+ actions?: ActionConfig[];
52
+ /**
53
+ * Custom slot for rendering actions (overrides actions array)
54
+ */
55
+ actionsSlot?: React.ReactNode;
38
56
  /**
39
57
  * Array of images for the gallery section.
40
58
  * First image with `featured: true` (or first image if none marked) displays as the tall featured image.
@@ -88,6 +106,22 @@ interface HeroFloatingImagesProps {
88
106
  * Additional CSS classes for the content area (left side)
89
107
  */
90
108
  contentClassName?: string;
109
+ /**
110
+ * Additional CSS classes for the badge
111
+ */
112
+ badgeClassName?: string;
113
+ /**
114
+ * Additional CSS classes for the heading
115
+ */
116
+ headingClassName?: string;
117
+ /**
118
+ * Additional CSS classes for the description
119
+ */
120
+ descriptionClassName?: string;
121
+ /**
122
+ * Additional CSS classes for the actions container
123
+ */
124
+ actionsClassName?: string;
91
125
  /**
92
126
  * Additional CSS classes for the gallery container (right side)
93
127
  */
@@ -118,34 +152,25 @@ interface HeroFloatingImagesProps {
118
152
  /**
119
153
  * HeroFloatingImages - A split-layout hero with flexible content and an interactive image gallery.
120
154
  *
121
- * Features a two-column layout: content on the left (fully customizable via children prop)
122
- * and a gallery on the right with a featured tall image and stacked secondary images.
155
+ * Features a two-column layout: named hero content on the left and a gallery on the right
156
+ * with a featured tall image and stacked secondary images.
123
157
  * Each image has a hover effect with zoom indicator and opens in a lightbox when clicked.
124
158
  *
125
- * The component uses the children prop pattern for maximum flexibility - the application
126
- * or AI builder can render any content structure without being constrained to specific
127
- * heading/description/badge props.
128
- *
129
159
  * @example
130
160
  * ```tsx
131
161
  * <HeroFloatingImages
162
+ * badge="Featured Work"
163
+ * heading="Your Headline Here"
164
+ * description="Your description..."
165
+ * actions={[{ label: "View Portfolio", href: "/portfolio", variant: "default" }]}
132
166
  * images={[
133
167
  * { src: "/featured.jpg", alt: "Featured work", featured: true },
134
168
  * { src: "/work-1.jpg", alt: "Project 1" },
135
169
  * { src: "/work-2.jpg", alt: "Project 2" },
136
170
  * ]}
137
- * >
138
- * <Badge className="mb-6 w-fit" variant="secondary">Featured Work</Badge>
139
- * <h1 className="mb-6 text-4xl font-bold">Your Headline Here</h1>
140
- * <p className="mb-8 text-lg text-muted-foreground">Your description...</p>
141
- * <div className="flex gap-4">
142
- * <Pressable href="/portfolio" variant="default" size="lg" asButton>
143
- * View Portfolio
144
- * </Pressable>
145
- * </div>
146
- * </HeroFloatingImages>
171
+ * />
147
172
  * ```
148
173
  */
149
- declare function HeroFloatingImages({ sectionId, children, images, imagesSlot, zoomIconName, enableLightbox, background, pattern, patternOpacity, className, gridClassName, contentClassName, galleryClassName, featuredImageClassName, secondaryImageClassName, imageClassName, zoomIndicatorClassName, optixFlowConfig, containerClassName, spacing, }: HeroFloatingImagesProps): React.JSX.Element;
174
+ declare function HeroFloatingImages({ sectionId, badge, badgeIcon, heading, description, actions, actionsSlot, images, imagesSlot, zoomIconName, enableLightbox, background, pattern, patternOpacity, className, gridClassName, contentClassName, badgeClassName, headingClassName, descriptionClassName, actionsClassName, galleryClassName, featuredImageClassName, secondaryImageClassName, imageClassName, zoomIndicatorClassName, optixFlowConfig, containerClassName, spacing, }: HeroFloatingImagesProps): React.JSX.Element;
150
175
 
151
176
  export { HeroFloatingImages, type HeroFloatingImagesProps };
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { S as SectionBackground, s as SectionSpacing, t as PatternName } from './community-initiatives-Dud0DKXB.js';
3
- import { O as OptixFlowConfig } from './blocks-DyouPohq.js';
3
+ import { A as ActionConfig, O as OptixFlowConfig } from './blocks-DyouPohq.js';
4
4
  import 'react/jsx-runtime';
5
5
  import 'class-variance-authority';
6
6
  import '@page-speed/pressable';
@@ -30,11 +30,29 @@ interface HeroFloatingImagesImage {
30
30
  }
31
31
  interface HeroFloatingImagesProps {
32
32
  /**
33
- * Flexible content slot for the left side of the hero.
34
- * Renders any content the application/AI builder provides (badges, headings, descriptions, actions, etc.)
35
- * This allows maximum flexibility without prescribing specific content structure.
33
+ * Badge content displayed above the heading
36
34
  */
37
- children?: React.ReactNode;
35
+ badge?: React.ReactNode;
36
+ /**
37
+ * Badge icon
38
+ */
39
+ badgeIcon?: React.ReactNode;
40
+ /**
41
+ * Main heading content
42
+ */
43
+ heading?: React.ReactNode;
44
+ /**
45
+ * Description text below heading
46
+ */
47
+ description?: React.ReactNode;
48
+ /**
49
+ * Array of action configurations for CTA buttons
50
+ */
51
+ actions?: ActionConfig[];
52
+ /**
53
+ * Custom slot for rendering actions (overrides actions array)
54
+ */
55
+ actionsSlot?: React.ReactNode;
38
56
  /**
39
57
  * Array of images for the gallery section.
40
58
  * First image with `featured: true` (or first image if none marked) displays as the tall featured image.
@@ -88,6 +106,22 @@ interface HeroFloatingImagesProps {
88
106
  * Additional CSS classes for the content area (left side)
89
107
  */
90
108
  contentClassName?: string;
109
+ /**
110
+ * Additional CSS classes for the badge
111
+ */
112
+ badgeClassName?: string;
113
+ /**
114
+ * Additional CSS classes for the heading
115
+ */
116
+ headingClassName?: string;
117
+ /**
118
+ * Additional CSS classes for the description
119
+ */
120
+ descriptionClassName?: string;
121
+ /**
122
+ * Additional CSS classes for the actions container
123
+ */
124
+ actionsClassName?: string;
91
125
  /**
92
126
  * Additional CSS classes for the gallery container (right side)
93
127
  */
@@ -118,34 +152,25 @@ interface HeroFloatingImagesProps {
118
152
  /**
119
153
  * HeroFloatingImages - A split-layout hero with flexible content and an interactive image gallery.
120
154
  *
121
- * Features a two-column layout: content on the left (fully customizable via children prop)
122
- * and a gallery on the right with a featured tall image and stacked secondary images.
155
+ * Features a two-column layout: named hero content on the left and a gallery on the right
156
+ * with a featured tall image and stacked secondary images.
123
157
  * Each image has a hover effect with zoom indicator and opens in a lightbox when clicked.
124
158
  *
125
- * The component uses the children prop pattern for maximum flexibility - the application
126
- * or AI builder can render any content structure without being constrained to specific
127
- * heading/description/badge props.
128
- *
129
159
  * @example
130
160
  * ```tsx
131
161
  * <HeroFloatingImages
162
+ * badge="Featured Work"
163
+ * heading="Your Headline Here"
164
+ * description="Your description..."
165
+ * actions={[{ label: "View Portfolio", href: "/portfolio", variant: "default" }]}
132
166
  * images={[
133
167
  * { src: "/featured.jpg", alt: "Featured work", featured: true },
134
168
  * { src: "/work-1.jpg", alt: "Project 1" },
135
169
  * { src: "/work-2.jpg", alt: "Project 2" },
136
170
  * ]}
137
- * >
138
- * <Badge className="mb-6 w-fit" variant="secondary">Featured Work</Badge>
139
- * <h1 className="mb-6 text-4xl font-bold">Your Headline Here</h1>
140
- * <p className="mb-8 text-lg text-muted-foreground">Your description...</p>
141
- * <div className="flex gap-4">
142
- * <Pressable href="/portfolio" variant="default" size="lg" asButton>
143
- * View Portfolio
144
- * </Pressable>
145
- * </div>
146
- * </HeroFloatingImages>
171
+ * />
147
172
  * ```
148
173
  */
149
- declare function HeroFloatingImages({ sectionId, children, images, imagesSlot, zoomIconName, enableLightbox, background, pattern, patternOpacity, className, gridClassName, contentClassName, galleryClassName, featuredImageClassName, secondaryImageClassName, imageClassName, zoomIndicatorClassName, optixFlowConfig, containerClassName, spacing, }: HeroFloatingImagesProps): React.JSX.Element;
174
+ declare function HeroFloatingImages({ sectionId, badge, badgeIcon, heading, description, actions, actionsSlot, images, imagesSlot, zoomIconName, enableLightbox, background, pattern, patternOpacity, className, gridClassName, contentClassName, badgeClassName, headingClassName, descriptionClassName, actionsClassName, galleryClassName, featuredImageClassName, secondaryImageClassName, imageClassName, zoomIndicatorClassName, optixFlowConfig, containerClassName, spacing, }: HeroFloatingImagesProps): React.JSX.Element;
150
175
 
151
176
  export { HeroFloatingImages, type HeroFloatingImagesProps };
@@ -7,6 +7,9 @@ import { Img } from '@page-speed/img';
7
7
  import { Lightbox } from '@page-speed/lightbox';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
  import { Icon } from '@page-speed/icon';
10
+ import { Slot } from '@radix-ui/react-slot';
11
+ import { cva } from 'class-variance-authority';
12
+ import { Pressable } from '@page-speed/pressable';
10
13
 
11
14
  // components/blocks/hero/hero-floating-images.tsx
12
15
  function cn(...inputs) {
@@ -401,9 +404,110 @@ var DynamicIcon = React.memo(function DynamicIcon2({
401
404
  return /* @__PURE__ */ jsx(Icon, { ...props, name, apiKey: apiKey ?? DEFAULT_ICON_API_KEY });
402
405
  });
403
406
  DynamicIcon.displayName = "DynamicIcon";
407
+ var badgeVariants = cva(
408
+ "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",
409
+ {
410
+ variants: {
411
+ variant: {
412
+ default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
413
+ secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
414
+ 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",
415
+ outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
416
+ }
417
+ },
418
+ defaultVariants: {
419
+ variant: "default"
420
+ }
421
+ }
422
+ );
423
+ function Badge({
424
+ className,
425
+ variant,
426
+ asChild = false,
427
+ ...props
428
+ }) {
429
+ const Comp = asChild ? Slot : "span";
430
+ return /* @__PURE__ */ jsx(
431
+ Comp,
432
+ {
433
+ "data-slot": "badge",
434
+ className: cn(badgeVariants({ variant }), className),
435
+ ...props
436
+ }
437
+ );
438
+ }
439
+ var MOBILE_CLASSES = {
440
+ "fit-left": "items-start md:items-center",
441
+ "fit-center": "items-center",
442
+ "fit-right": "items-end md:items-center",
443
+ "full-left": "items-stretch md:items-center",
444
+ "full-center": "items-stretch md:items-center",
445
+ "full-right": "items-stretch md:items-center"
446
+ };
447
+ function BlockActions({
448
+ mobileConfig,
449
+ actionsClassName,
450
+ verticalSpacing = "mt-4 md:mt-8",
451
+ actions,
452
+ actionsSlot
453
+ }) {
454
+ const width = mobileConfig?.width ?? "full";
455
+ const position = mobileConfig?.position ?? "center";
456
+ const mobileLayoutClass = MOBILE_CLASSES[`${width}-${position}`];
457
+ if (actionsSlot) {
458
+ return /* @__PURE__ */ jsx("div", { children: actionsSlot });
459
+ } else if (actions && actions?.length > 0) {
460
+ return /* @__PURE__ */ jsx(
461
+ "div",
462
+ {
463
+ className: cn(
464
+ "flex flex-col md:flex-row flex-wrap gap-4",
465
+ mobileLayoutClass,
466
+ actionsClassName,
467
+ verticalSpacing
468
+ ),
469
+ children: actions.map((action, index) => /* @__PURE__ */ jsx(ActionComponent, { action }, index))
470
+ }
471
+ );
472
+ } else {
473
+ return null;
474
+ }
475
+ }
476
+ function ActionComponent({ action }) {
477
+ const {
478
+ label,
479
+ icon,
480
+ iconAfter,
481
+ children,
482
+ href,
483
+ onClick,
484
+ className: actionClassName,
485
+ ...pressableProps
486
+ } = action;
487
+ return /* @__PURE__ */ jsx(
488
+ Pressable,
489
+ {
490
+ href,
491
+ onClick,
492
+ asButton: action.asButton ?? true,
493
+ className: actionClassName,
494
+ ...pressableProps,
495
+ children: children ?? /* @__PURE__ */ jsxs(Fragment, { children: [
496
+ icon,
497
+ label,
498
+ iconAfter
499
+ ] })
500
+ }
501
+ );
502
+ }
404
503
  function HeroFloatingImages({
405
504
  sectionId = "hero-floating-images",
406
- children,
505
+ badge,
506
+ badgeIcon,
507
+ heading,
508
+ description,
509
+ actions,
510
+ actionsSlot,
407
511
  images,
408
512
  imagesSlot,
409
513
  zoomIconName = "lucide/zoom-in",
@@ -414,6 +518,10 @@ function HeroFloatingImages({
414
518
  className,
415
519
  gridClassName,
416
520
  contentClassName,
521
+ badgeClassName,
522
+ headingClassName,
523
+ descriptionClassName,
524
+ actionsClassName,
417
525
  galleryClassName,
418
526
  featuredImageClassName,
419
527
  secondaryImageClassName,
@@ -589,8 +697,10 @@ function HeroFloatingImages({
589
697
  secondaryImagesContent
590
698
  ]);
591
699
  const hasContent = useMemo(() => {
592
- return children !== void 0 && children !== null;
593
- }, [children]);
700
+ return Boolean(
701
+ badge || badgeIcon || heading || description || actionsSlot || actions && actions.length > 0
702
+ );
703
+ }, [actions, actionsSlot, badge, badgeIcon, description, heading]);
594
704
  const hasGallery = useMemo(() => {
595
705
  return imagesSlot || images && images.length > 0;
596
706
  }, [imagesSlot, images]);
@@ -613,7 +723,48 @@ function HeroFloatingImages({
613
723
  gridClassName
614
724
  ),
615
725
  children: [
616
- hasContent ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col justify-center", contentClassName), children }) : null,
726
+ hasContent ? /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col justify-center", contentClassName), children: [
727
+ (badge || badgeIcon) && /* @__PURE__ */ jsxs(
728
+ Badge,
729
+ {
730
+ variant: "secondary",
731
+ className: cn("mb-6 w-fit", badgeClassName),
732
+ children: [
733
+ badge,
734
+ badgeIcon
735
+ ]
736
+ }
737
+ ),
738
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
739
+ "h1",
740
+ {
741
+ className: cn(
742
+ "mb-6 text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl",
743
+ headingClassName
744
+ ),
745
+ children: heading
746
+ }
747
+ ) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
748
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx(
749
+ "p",
750
+ {
751
+ className: cn(
752
+ "mb-8 max-w-lg text-lg text-muted-foreground",
753
+ descriptionClassName
754
+ ),
755
+ children: description
756
+ }
757
+ ) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description })),
758
+ /* @__PURE__ */ jsx(
759
+ BlockActions,
760
+ {
761
+ actions,
762
+ actionsSlot,
763
+ actionsClassName,
764
+ verticalSpacing: description ? "mt-0" : void 0
765
+ }
766
+ )
767
+ ] }) : null,
617
768
  hasGallery ? galleryContent : null
618
769
  ]
619
770
  }
package/dist/registry.cjs CHANGED
@@ -49597,7 +49597,12 @@ function HeroSplitIconCards({
49597
49597
  }
49598
49598
  function HeroFloatingImages({
49599
49599
  sectionId = "hero-floating-images",
49600
- children,
49600
+ badge,
49601
+ badgeIcon,
49602
+ heading,
49603
+ description,
49604
+ actions,
49605
+ actionsSlot,
49601
49606
  images,
49602
49607
  imagesSlot,
49603
49608
  zoomIconName = "lucide/zoom-in",
@@ -49608,6 +49613,10 @@ function HeroFloatingImages({
49608
49613
  className,
49609
49614
  gridClassName,
49610
49615
  contentClassName,
49616
+ badgeClassName,
49617
+ headingClassName,
49618
+ descriptionClassName,
49619
+ actionsClassName,
49611
49620
  galleryClassName,
49612
49621
  featuredImageClassName,
49613
49622
  secondaryImageClassName,
@@ -49783,8 +49792,10 @@ function HeroFloatingImages({
49783
49792
  secondaryImagesContent
49784
49793
  ]);
49785
49794
  const hasContent = React30.useMemo(() => {
49786
- return children !== void 0 && children !== null;
49787
- }, [children]);
49795
+ return Boolean(
49796
+ badge || badgeIcon || heading || description || actionsSlot || actions && actions.length > 0
49797
+ );
49798
+ }, [actions, actionsSlot, badge, badgeIcon, description, heading]);
49788
49799
  const hasGallery = React30.useMemo(() => {
49789
49800
  return imagesSlot || images && images.length > 0;
49790
49801
  }, [imagesSlot, images]);
@@ -49807,7 +49818,48 @@ function HeroFloatingImages({
49807
49818
  gridClassName
49808
49819
  ),
49809
49820
  children: [
49810
- hasContent ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col justify-center", contentClassName), children }) : null,
49821
+ hasContent ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col justify-center", contentClassName), children: [
49822
+ (badge || badgeIcon) && /* @__PURE__ */ jsxRuntime.jsxs(
49823
+ Badge,
49824
+ {
49825
+ variant: "secondary",
49826
+ className: cn("mb-6 w-fit", badgeClassName),
49827
+ children: [
49828
+ badge,
49829
+ badgeIcon
49830
+ ]
49831
+ }
49832
+ ),
49833
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
49834
+ "h1",
49835
+ {
49836
+ className: cn(
49837
+ "mb-6 text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl",
49838
+ headingClassName
49839
+ ),
49840
+ children: heading
49841
+ }
49842
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: headingClassName, children: heading })),
49843
+ description && (typeof description === "string" ? /* @__PURE__ */ jsxRuntime.jsx(
49844
+ "p",
49845
+ {
49846
+ className: cn(
49847
+ "mb-8 max-w-lg text-lg text-muted-foreground",
49848
+ descriptionClassName
49849
+ ),
49850
+ children: description
49851
+ }
49852
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: descriptionClassName, children: description })),
49853
+ /* @__PURE__ */ jsxRuntime.jsx(
49854
+ BlockActions,
49855
+ {
49856
+ actions,
49857
+ actionsSlot,
49858
+ actionsClassName,
49859
+ verticalSpacing: description ? "mt-0" : void 0
49860
+ }
49861
+ )
49862
+ ] }) : null,
49811
49863
  hasGallery ? galleryContent : null
49812
49864
  ]
49813
49865
  }
package/dist/registry.js CHANGED
@@ -49557,7 +49557,12 @@ function HeroSplitIconCards({
49557
49557
  }
49558
49558
  function HeroFloatingImages({
49559
49559
  sectionId = "hero-floating-images",
49560
- children,
49560
+ badge,
49561
+ badgeIcon,
49562
+ heading,
49563
+ description,
49564
+ actions,
49565
+ actionsSlot,
49561
49566
  images,
49562
49567
  imagesSlot,
49563
49568
  zoomIconName = "lucide/zoom-in",
@@ -49568,6 +49573,10 @@ function HeroFloatingImages({
49568
49573
  className,
49569
49574
  gridClassName,
49570
49575
  contentClassName,
49576
+ badgeClassName,
49577
+ headingClassName,
49578
+ descriptionClassName,
49579
+ actionsClassName,
49571
49580
  galleryClassName,
49572
49581
  featuredImageClassName,
49573
49582
  secondaryImageClassName,
@@ -49743,8 +49752,10 @@ function HeroFloatingImages({
49743
49752
  secondaryImagesContent
49744
49753
  ]);
49745
49754
  const hasContent = useMemo(() => {
49746
- return children !== void 0 && children !== null;
49747
- }, [children]);
49755
+ return Boolean(
49756
+ badge || badgeIcon || heading || description || actionsSlot || actions && actions.length > 0
49757
+ );
49758
+ }, [actions, actionsSlot, badge, badgeIcon, description, heading]);
49748
49759
  const hasGallery = useMemo(() => {
49749
49760
  return imagesSlot || images && images.length > 0;
49750
49761
  }, [imagesSlot, images]);
@@ -49767,7 +49778,48 @@ function HeroFloatingImages({
49767
49778
  gridClassName
49768
49779
  ),
49769
49780
  children: [
49770
- hasContent ? /* @__PURE__ */ jsx("div", { className: cn("flex flex-col justify-center", contentClassName), children }) : null,
49781
+ hasContent ? /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col justify-center", contentClassName), children: [
49782
+ (badge || badgeIcon) && /* @__PURE__ */ jsxs(
49783
+ Badge,
49784
+ {
49785
+ variant: "secondary",
49786
+ className: cn("mb-6 w-fit", badgeClassName),
49787
+ children: [
49788
+ badge,
49789
+ badgeIcon
49790
+ ]
49791
+ }
49792
+ ),
49793
+ heading && (typeof heading === "string" ? /* @__PURE__ */ jsx(
49794
+ "h1",
49795
+ {
49796
+ className: cn(
49797
+ "mb-6 text-4xl font-bold tracking-tight sm:text-5xl md:text-6xl",
49798
+ headingClassName
49799
+ ),
49800
+ children: heading
49801
+ }
49802
+ ) : /* @__PURE__ */ jsx("div", { className: headingClassName, children: heading })),
49803
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx(
49804
+ "p",
49805
+ {
49806
+ className: cn(
49807
+ "mb-8 max-w-lg text-lg text-muted-foreground",
49808
+ descriptionClassName
49809
+ ),
49810
+ children: description
49811
+ }
49812
+ ) : /* @__PURE__ */ jsx("div", { className: descriptionClassName, children: description })),
49813
+ /* @__PURE__ */ jsx(
49814
+ BlockActions,
49815
+ {
49816
+ actions,
49817
+ actionsSlot,
49818
+ actionsClassName,
49819
+ verticalSpacing: description ? "mt-0" : void 0
49820
+ }
49821
+ )
49822
+ ] }) : null,
49771
49823
  hasGallery ? galleryContent : null
49772
49824
  ]
49773
49825
  }
@@ -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<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement>>;
80
+ declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | 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<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement>>;
80
+ declare const SocialLinkIcon: React.ForwardRefExoticComponent<SocialLinkIconProps & React.RefAttributes<HTMLAnchorElement | HTMLButtonElement | HTMLSpanElement>>;
81
81
 
82
82
  export { SocialLinkIcon, type SocialLinkIconDynamicIconProps, type SocialLinkIconProps };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensite/ui",
3
- "version": "3.3.6",
3
+ "version": "3.3.7",
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",