{"version":3,"file":"CarouselWidget-DBvAGJ6v.mjs","names":["DOMPurify"],"sources":["../../widgets/src/widgets/CarouselWidget.tsx"],"sourcesContent":["import type { ComponentProps, CSSProperties } from \"react\";\nimport type React from \"react\";\nimport { useEffect, useState, useCallback } from \"react\";\nimport DOMPurify from \"dompurify\";\nimport {\n  MediaRenderer,\n  getMediaPropsFromWidgetSchema,\n} from \"../components/MediaRenderer\";\nimport type {\n  WidgetSchema,\n  BorderRadiusOptions,\n  BorderWidthOptions,\n  ColorOptions,\n  AlignOptions,\n  FontSizeOptions,\n  PaddingOptions,\n  ButtonSizeOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n  borderColorClasses,\n  borderWidthClasses,\n  getBorderColorField,\n  getBorderRadiusField,\n  getBorderWidthField,\n  getButtonSizeField,\n  getColorField,\n  getFontSizeField,\n  getHeightField,\n  getPaddingField,\n} from \"../core/fields\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport { useRepUser } from \"../contexts/RepUserContext\";\nimport { useWidgetRenderState } from \"../contexts/WidgetRenderStateContext\";\nimport { useInternalLinks } from \"../hooks/use-internal-link\";\nimport { buildItemInteractionProps } from \"./list-widget/helpers\";\nimport { getLinkTypeFields } from \"../lib/link-type-schema-fields\";\n\ntype CarouselSlide = {\n  id: string;\n  content: WidgetSchema;\n  title?: string;\n  description?: string;\n  // Editorial additions (all optional — existing configs keep working)\n  eyebrow?: string;\n  meta?: string;\n  tag?: string;\n  tagColor?: ColorOptions;\n  buttonEnabled?: boolean;\n  buttonText?: string;\n  buttonVariant?:\n    | \"default\"\n    | \"secondary\"\n    | \"outline\"\n    | \"destructive\"\n    | \"ghost\"\n    | \"link\";\n  buttonLink?: string;\n  secondaryButtonText?: string;\n  secondaryButtonLink?: string;\n  // Index signature lets data-source-driven slides carry extra fields\n  // (e.g. shareable_type, subscription_token) through to onItemClick,\n  // which routes based on them — matches ListWidget's ListItem shape.\n  [key: string]: unknown;\n};\n\ntype CarouselWidgetProps = ComponentProps<\"div\"> & {\n  slides?: CarouselSlide[];\n  autoScrollInterval?: number;\n  enableAutoScroll?: boolean;\n\n  // Layout\n  align?: AlignOptions;\n  // CSS-unit string (\"400px\", \"30rem\", \"50%\") — kept as string so saved\n  // configs from the previous schema continue to render. The schema field\n  // is `cssUnit` (via getHeightField), which produces a string with the\n  // unit baked in.\n  carouselHeight?: string;\n  borderRadius?: BorderRadiusOptions;\n  borderWidth?: BorderWidthOptions;\n  borderColor?: ColorOptions;\n  padding?: PaddingOptions;\n\n  // Text Styling\n  headerSize?: FontSizeOptions;\n  headerColor?: ColorOptions;\n  textSize?: FontSizeOptions;\n  textColor?: ColorOptions;\n  textWidth?: string;\n\n  // Button\n  showButton?: boolean;\n  buttonColor?: ColorOptions;\n  buttonSize?: ButtonSizeOptions;\n\n  // Overlay\n  overlayEnabled?: boolean;\n  overlayType?: \"solid\" | \"gradient\";\n  overlayIntensity?: number;\n\n  // Editorial frame (new — opt-out via `editorialFrame={false}`)\n  editorialFrame?: boolean;\n  frameColor?: ColorOptions;\n};\n\nconst VIDEO_CONTROLS_HEIGHT = 44;\n\nconst HEADER_SIZE_MAP: Record<FontSizeOptions, string> = {\n  xs: \"text-base sm:text-lg\",\n  sm: \"text-lg sm:text-xl\",\n  md: \"text-xl sm:text-2xl\",\n  lg: \"text-2xl sm:text-3xl\",\n  xl: \"text-3xl sm:text-[32px]\",\n  \"2xl\": \"text-[32px] sm:text-[40px]\",\n};\n\nconst BODY_SIZE_MAP: Record<FontSizeOptions, string> = {\n  xs: \"text-[12px]\",\n  sm: \"text-[13px]\",\n  md: \"text-[14px]\",\n  lg: \"text-[15px]\",\n  xl: \"text-[16px]\",\n  \"2xl\": \"text-[18px]\",\n};\n\nfunction useCarouselController({\n  slideCount,\n  enableAutoScroll,\n  autoScrollInterval,\n}: {\n  slideCount: number;\n  enableAutoScroll: boolean;\n  autoScrollInterval: number;\n}) {\n  const [currentIndex, setCurrentIndex] = useState(0);\n  // Track hover and keyboard focus separately — combining them in one boolean\n  // would let `onMouseLeave` clear the paused state even while a child button\n  // still has focus.\n  const [isHovered, setIsHovered] = useState(false);\n  const [isFocused, setIsFocused] = useState(false);\n  const hasSlides = slideCount > 0;\n  const isPaused = isHovered || isFocused;\n\n  const goToNext = useCallback(() => {\n    if (!hasSlides) return;\n    setCurrentIndex((prev) => (prev === slideCount - 1 ? 0 : prev + 1));\n  }, [hasSlides, slideCount]);\n\n  const goToPrevious = useCallback(() => {\n    if (!hasSlides) return;\n    setCurrentIndex((prev) => (prev === 0 ? slideCount - 1 : prev - 1));\n  }, [hasSlides, slideCount]);\n\n  const goToSlide = useCallback(\n    (index: number) => {\n      if (!hasSlides) return;\n      if (index >= 0 && index < slideCount) {\n        setCurrentIndex(index);\n      }\n    },\n    [hasSlides, slideCount],\n  );\n\n  useEffect(() => {\n    if (!enableAutoScroll || !hasSlides || isPaused) return;\n    const intervalId = setInterval(goToNext, autoScrollInterval);\n    return () => clearInterval(intervalId);\n  }, [enableAutoScroll, autoScrollInterval, hasSlides, isPaused, goToNext]);\n\n  useEffect(() => {\n    if (currentIndex >= slideCount && slideCount > 0) {\n      setCurrentIndex(0);\n    }\n  }, [slideCount, currentIndex]);\n\n  // Pause for a mouse or the keyboard, never for a touch. On iOS a tap fires\n  // mouseenter with no mouseleave after it, and it focuses the button too, so\n  // either one would leave the carousel stuck paused.\n  const handlePointerEnter = useCallback((e: React.PointerEvent) => {\n    if (e.pointerType === \"mouse\") setIsHovered(true);\n  }, []);\n  const handlePointerLeave = useCallback((e: React.PointerEvent) => {\n    if (e.pointerType === \"mouse\") setIsHovered(false);\n  }, []);\n  const handleFocus = useCallback((e: React.FocusEvent<HTMLElement>) => {\n    // Set it either way, or a click inside leaves it paused.\n    setIsFocused(\n      e.target instanceof Element && e.target.matches(\":focus-visible\"),\n    );\n  }, []);\n  const handleBlur = useCallback((e: React.FocusEvent<HTMLElement>) => {\n    // Only flip to unfocused when focus actually leaves the carousel.\n    // When focus moves between two children (e.g. tabbing from prev to next\n    // button), `relatedTarget` is the new focus target and is still contained.\n    if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {\n      setIsFocused(false);\n    }\n  }, []);\n\n  return {\n    currentIndex,\n    hasSlides,\n    isPaused,\n    goToNext,\n    goToPrevious,\n    goToSlide,\n    handlePointerEnter,\n    handlePointerLeave,\n    handleFocus,\n    handleBlur,\n  };\n}\n\nexport function CarouselWidget({\n  slides = [],\n  autoScrollInterval = 6500,\n  enableAutoScroll = false,\n  carouselHeight = \"400px\",\n  align = { vertical: \"bottom\", horizontal: \"left\" },\n  overlayIntensity = 70,\n  borderRadius = \"xl\",\n  borderWidth = \"none\",\n  borderColor = \"muted\",\n  padding = 8,\n  textWidth = \"620px\",\n  headerSize = \"xl\",\n  headerColor = \"background\",\n  textSize = \"md\",\n  textColor = \"background\",\n  showButton = true,\n  buttonColor = \"background\",\n  buttonSize = \"default\",\n  overlayEnabled = true,\n  overlayType = \"gradient\",\n  editorialFrame = true,\n  frameColor = \"foreground\",\n  className,\n  ...props\n}: CarouselWidgetProps): React.JSX.Element {\n  const totalSlides = slides.length;\n  const {\n    currentIndex,\n    hasSlides,\n    isPaused,\n    goToNext,\n    goToPrevious,\n    goToSlide,\n    handlePointerEnter,\n    handlePointerLeave,\n    handleFocus,\n    handleBlur,\n  } = useCarouselController({\n    slideCount: totalSlides,\n    enableAutoScroll,\n    autoScrollInterval,\n  });\n  const { onItemClick, onNavigate, buildHref, resolveInternalSlug } =\n    useWidgetInteraction();\n  const resolveInternalLink = useInternalLinks();\n  const publicId = useRepUser()?.publicId;\n  const { editMode } = useWidgetRenderState();\n  const verticalClass =\n    align.vertical === \"top\"\n      ? \"items-start\"\n      : align.vertical === \"center\"\n        ? \"items-center\"\n        : \"items-end\";\n\n  const horizontalClass =\n    align.horizontal === \"center\"\n      ? \"justify-center text-center mx-auto\"\n      : align.horizontal === \"right\"\n        ? \"justify-end ml-auto text-right\"\n        : \"justify-start text-left\";\n\n  // Themed dual-shadow (crisp + soft ambient) on the editorial frame —\n  // derived from the foreground token so the lift reads in both light\n  // and dark themes.\n  const frameShadowStyle: CSSProperties | undefined = editorialFrame\n    ? {\n        boxShadow: `0 1px 2px color-mix(in oklch, var(--color-foreground) 4%, transparent), 0 30px 60px -30px color-mix(in oklch, var(--color-foreground) 40%, transparent)`,\n      }\n    : undefined;\n\n  const frameBg = editorialFrame ? `bg-${frameColor}` : \"\";\n  const isActiveSlideVideo =\n    slides[currentIndex]?.content.type === \"VideoWidget\";\n\n  if (!hasSlides) {\n    return (\n      <div\n        className={`relative w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n        style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n        {...props}\n      >\n        <div\n          className=\"bg-muted/20 flex h-full w-full items-center justify-center\"\n          style={{ minHeight: carouselHeight }}\n        >\n          <div className=\"text-muted-foreground flex flex-col items-center gap-2\">\n            <div className=\"text-4xl\">🎠</div>\n            <p className=\"text-sm\">No slides added</p>\n            <p className=\"text-muted-foreground/70 text-xs\">\n              Add slides to create a carousel\n            </p>\n          </div>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div\n      className={`relative isolate w-full overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${frameBg} ${className ?? \"\"}`}\n      style={{ minHeight: carouselHeight, ...frameShadowStyle }}\n      onPointerEnter={handlePointerEnter}\n      onPointerLeave={handlePointerLeave}\n      onFocus={handleFocus}\n      onBlur={handleBlur}\n      {...props}\n    >\n      <div\n        className=\"relative w-full\"\n        style={{\n          minHeight: carouselHeight,\n          height: carouselHeight,\n        }}\n      >\n        {slides.map((slide, index) => {\n          const isActive = index === currentIndex;\n          const isVideoSlide = slide.content.type === \"VideoWidget\";\n          // Strip the optional \"%\" suffix, then parse. Use Number.isFinite +\n          // clamp so an explicit 0 isn't silently replaced by the 70 fallback\n          // (the previous `|| 70` treated 0 as falsy).\n          const parsedOverlayIntensity = Number(\n            String(overlayIntensity).replace(\"%\", \"\"),\n          );\n          const overlayOpacity =\n            (Number.isFinite(parsedOverlayIntensity)\n              ? Math.min(100, Math.max(0, parsedOverlayIntensity))\n              : 70) / 100;\n\n          // Slide-level tap: if the slide has an explicit linkType from\n          // itemConfigSchema, use it; otherwise fall back to onItemClick\n          // (which routes based on shareable_type, subscription_token, etc.).\n          const slideLinkProps =\n            isActive && !isVideoSlide\n              ? buildItemInteractionProps(slide, {\n                  onItemClick,\n                  onNavigate,\n                  buildHref,\n                  resolveInternalSlug,\n                  publicId,\n                  editMode,\n                })\n              : {};\n          const isInteractive = Object.keys(slideLinkProps).length > 0;\n\n          return (\n            <div\n              key={slide.id}\n              className={`absolute inset-0 transition-opacity duration-700 ease-out${isInteractive ? \" cursor-pointer focus-visible:ring-2 focus-visible:ring-white/60 focus-visible:outline-none focus-visible:ring-inset\" : \"\"}`}\n              style={{\n                opacity: isActive ? 1 : 0,\n                pointerEvents: isActive ? \"auto\" : \"none\",\n              }}\n              aria-hidden={!isActive}\n              {...slideLinkProps}\n            >\n              {isVideoSlide ? (\n                <div className=\"absolute inset-0 h-full w-full\">\n                  {isActive && (\n                    <MediaRenderer\n                      {...getMediaPropsFromWidgetSchema(slide.content)}\n                    />\n                  )}\n                </div>\n              ) : (\n                <>\n                  <div\n                    className=\"absolute inset-0 h-full w-full\"\n                    style={{\n                      transform: isActive ? \"scale(1)\" : \"scale(1.04)\",\n                      animation: isActive\n                        ? \"fluidCarouselKenBurns 900ms ease-out both\"\n                        : undefined,\n                    }}\n                  >\n                    <MediaRenderer\n                      {...getMediaPropsFromWidgetSchema(slide.content)}\n                    />\n                  </div>\n\n                  {overlayEnabled && editorialFrame && (\n                    <>\n                      <div\n                        className={`pointer-events-none absolute inset-0 bg-gradient-to-t from-${frameColor} via-${frameColor}/65 to-${frameColor}/10`}\n                        style={{ opacity: overlayOpacity }}\n                      />\n                      <div\n                        className={`pointer-events-none absolute inset-0 bg-gradient-to-r from-${frameColor}/80 via-transparent to-transparent`}\n                        style={{ opacity: Math.min(1, overlayOpacity + 0.1) }}\n                      />\n                    </>\n                  )}\n\n                  {overlayEnabled && !editorialFrame && (\n                    <div\n                      className={`pointer-events-none absolute inset-0 ${\n                        overlayType === \"gradient\"\n                          ? \"bg-gradient-to-t from-black to-transparent\"\n                          : \"bg-black\"\n                      }`}\n                      style={{ opacity: overlayOpacity }}\n                    />\n                  )}\n                </>\n              )}\n\n              <div\n                className={`pointer-events-none absolute inset-0 flex px-6 sm:px-10 ${verticalClass} ${\n                  align.horizontal === \"center\"\n                    ? \"justify-center\"\n                    : align.horizontal === \"right\"\n                      ? \"justify-end\"\n                      : \"justify-start\"\n                }`}\n                style={{\n                  paddingTop: padding * 4,\n                  paddingBottom:\n                    padding * 4 +\n                    (totalSlides > 1\n                      ? 24 + (isVideoSlide ? VIDEO_CONTROLS_HEIGHT : 0)\n                      : 0),\n                }}\n              >\n                <div\n                  key={`content-${currentIndex}`}\n                  className={`${isActive && !isVideoSlide ? \"pointer-events-auto\" : \"pointer-events-none\"} flex w-full flex-col gap-3 ${horizontalClass}`}\n                  style={{\n                    maxWidth: textWidth,\n                    animation: isActive\n                      ? \"fluidCarouselTextRise 450ms ease-out both\"\n                      : undefined,\n                    animationDelay: isActive ? \"120ms\" : undefined,\n                  }}\n                >\n                  {(slide.eyebrow || slide.tag || slide.meta) && (\n                    <div\n                      className={`flex flex-wrap items-center gap-2 ${\n                        align.horizontal === \"center\"\n                          ? \"justify-center\"\n                          : align.horizontal === \"right\"\n                            ? \"justify-end\"\n                            : \"justify-start\"\n                      }`}\n                    >\n                      {slide.tag && (\n                        <span\n                          className={`rounded-full bg-${slide.tagColor ?? \"background\"} text-${slide.tagColor ?? \"background\"}-foreground px-2.5 py-1 text-[10px] font-bold tracking-[0.14em] uppercase`}\n                          style={\n                            slide.tagColor === \"background\" ||\n                            slide.tagColor === \"foreground\" ||\n                            !slide.tagColor\n                              ? tagFallbackStyle(slide.tagColor, frameColor)\n                              : undefined\n                          }\n                        >\n                          {slide.tag}\n                        </span>\n                      )}\n                      {slide.eyebrow && (\n                        <span\n                          className={`text-${headerColor}/70 text-[10px] font-bold tracking-[0.16em] uppercase`}\n                        >\n                          {slide.eyebrow}\n                        </span>\n                      )}\n                      {slide.meta && (\n                        <span\n                          className={`text-${headerColor}/60 text-[10px] font-bold tracking-[0.16em] uppercase`}\n                        >\n                          {slide.meta}\n                        </span>\n                      )}\n                    </div>\n                  )}\n\n                  {slide.title && (\n                    <h2\n                      className={`text-${headerColor} font-bold ${HEADER_SIZE_MAP[headerSize]} leading-[1.12] tracking-[-0.018em]`}\n                    >\n                      {slide.title}\n                    </h2>\n                  )}\n\n                  {slide.description && (\n                    // Description supports inline HTML for emphasis / line\n                    // breaks / lists. Sanitized via DOMPurify with the same\n                    // allowlist as the previous implementation so saved\n                    // slides containing <strong>, <em>, <br>, <ul>, etc.\n                    // continue rendering as authored. Element is a <div>\n                    // (not <p>) to permit block-level allowed tags.\n                    <div\n                      className={`text-${textColor}/70 ${BODY_SIZE_MAP[textSize]} leading-[1.55]`}\n                      dangerouslySetInnerHTML={{\n                        __html: DOMPurify.sanitize(slide.description, {\n                          ALLOWED_TAGS: [\n                            \"br\",\n                            \"strong\",\n                            \"em\",\n                            \"b\",\n                            \"i\",\n                            \"ul\",\n                            \"ol\",\n                            \"li\",\n                            \"p\",\n                          ],\n                          ALLOWED_ATTR: [],\n                        }),\n                      }}\n                    />\n                  )}\n\n                  {(() => {\n                    const showPrimary =\n                      slide.buttonEnabled &&\n                      showButton &&\n                      Boolean(slide.buttonText) &&\n                      Boolean(slide.buttonLink);\n                    const showSecondary =\n                      Boolean(slide.secondaryButtonText) &&\n                      Boolean(slide.secondaryButtonLink);\n                    if (!showPrimary && !showSecondary) return null;\n\n                    const primaryLink = resolveInternalLink(slide.buttonLink);\n                    const secondaryLink = resolveInternalLink(\n                      slide.secondaryButtonLink,\n                    );\n\n                    return (\n                      <div\n                        className={`mt-3 flex flex-wrap items-center gap-3 ${\n                          align.horizontal === \"center\"\n                            ? \"justify-center\"\n                            : align.horizontal === \"right\"\n                              ? \"justify-end\"\n                              : \"justify-start\"\n                        }`}\n                      >\n                        {showPrimary && (\n                          <a\n                            href={slide.buttonLink}\n                            onClick={(e) => {\n                              e.stopPropagation();\n                              primaryLink.followInternally(e);\n                            }}\n                            className={`inline-flex items-center gap-1.5 rounded-full bg-${buttonColor} text-${buttonColor}-foreground px-5 py-2.5 text-[13px] font-bold transition-transform hover:scale-[1.02] ${buttonSizeClass(buttonSize)}`}\n                            style={{\n                              boxShadow: `0 8px 22px -8px color-mix(in oklch, var(--color-foreground) 35%, transparent)`,\n                            }}\n                          >\n                            {slide.buttonText}\n                            <span aria-hidden=\"true\" className=\"text-[14px]\">\n                              →\n                            </span>\n                          </a>\n                        )}\n                        {showSecondary && (\n                          <a\n                            href={slide.secondaryButtonLink}\n                            onClick={(e) => {\n                              e.stopPropagation();\n                              secondaryLink.followInternally(e);\n                            }}\n                            className={`inline-flex items-center gap-1 text-${headerColor}/80 hover:text-${headerColor} text-[12px] font-bold transition-colors`}\n                          >\n                            {slide.secondaryButtonText}\n                            <span aria-hidden=\"true\">→</span>\n                          </a>\n                        )}\n                      </div>\n                    );\n                  })()}\n                </div>\n              </div>\n            </div>\n          );\n        })}\n\n        {totalSlides > 1 && (\n          <div className=\"pointer-events-none absolute inset-0 z-20\">\n            <div className=\"pointer-events-auto absolute top-6 right-6 flex items-center gap-1.5\">\n              <button\n                type=\"button\"\n                onClick={goToPrevious}\n                aria-label=\"Previous slide\"\n                className={`flex size-10 items-center justify-center rounded-full bg-${headerColor}/10 text-${headerColor} ring-1 ring-${headerColor}/15 backdrop-blur-sm transition-colors hover:bg-${headerColor}/20`}\n              >\n                <ChevronLeftIcon />\n              </button>\n              <button\n                type=\"button\"\n                onClick={goToNext}\n                aria-label=\"Next slide\"\n                className={`flex size-10 items-center justify-center rounded-full bg-${headerColor} text-${headerColor}-foreground transition-transform hover:scale-[1.04]`}\n                style={{\n                  // Themed lift shadow (was hardcoded white) so the active\n                  // nav button reads on both light and dark frames.\n                  boxShadow: `0 4px 14px -4px color-mix(in oklch, var(--color-${headerColor}) 45%, transparent)`,\n                  ...nextButtonFallbackStyle(headerColor, frameColor),\n                }}\n              >\n                <ChevronRightIcon />\n              </button>\n            </div>\n\n            <div\n              className={`pointer-events-auto absolute inset-x-0 flex items-center gap-1 px-6 pb-2 sm:px-10`}\n              style={{\n                bottom: isActiveSlideVideo ? VIDEO_CONTROLS_HEIGHT : 0,\n                transition: \"bottom 200ms ease-out\",\n              }}\n            >\n              {slides.map((_, i) => {\n                const state =\n                  i < currentIndex\n                    ? \"done\"\n                    : i === currentIndex\n                      ? \"active\"\n                      : \"upcoming\";\n                return (\n                  <button\n                    key={`progress-${i}`}\n                    type=\"button\"\n                    onClick={() => goToSlide(i)}\n                    aria-label={`Go to slide ${i + 1}`}\n                    aria-current={state === \"active\" ? \"true\" : \"false\"}\n                    className=\"group flex-1 py-2\"\n                  >\n                    <span\n                      className={`block h-[2px] w-full overflow-hidden rounded-full bg-${headerColor}/20`}\n                    >\n                      <span\n                        key={`fill-${i}-${currentIndex}`}\n                        className={`block h-full rounded-full bg-${headerColor}`}\n                        style={progressFillStyle(\n                          state,\n                          enableAutoScroll,\n                          autoScrollInterval,\n                          isPaused,\n                        )}\n                      />\n                    </span>\n                  </button>\n                );\n              })}\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\nfunction progressFillStyle(\n  state: \"done\" | \"active\" | \"upcoming\",\n  autoScroll: boolean,\n  duration: number,\n  paused: boolean,\n): CSSProperties {\n  if (state === \"upcoming\") return { width: \"0%\" };\n  if (!autoScroll) {\n    // Nothing is counting down, so only the current bar fills. Otherwise the\n    // last slide has every bar full and you can't tell which one you're on.\n    return { width: state === \"active\" ? \"100%\" : \"0%\" };\n  }\n  if (state === \"done\") return { width: \"100%\" };\n  return {\n    width: \"0%\",\n    animation: `fluidCarouselProgressFill ${duration}ms linear forwards`,\n    animationPlayState: paused ? \"paused\" : \"running\",\n  };\n}\n\nfunction tagFallbackStyle(\n  tagColor: ColorOptions | undefined,\n  frameColor: ColorOptions,\n): CSSProperties | undefined {\n  // bg-background/foreground don't emit -foreground utilities by default;\n  // fall back to contrast-safe inline colors so tag chips always read.\n  if (!tagColor || tagColor === \"background\") {\n    return { color: `var(--color-${frameColor})` };\n  }\n  if (tagColor === \"foreground\") {\n    return { color: `var(--color-background)` };\n  }\n  return undefined;\n}\n\nfunction nextButtonFallbackStyle(\n  headerColor: ColorOptions,\n  frameColor: ColorOptions,\n): CSSProperties | undefined {\n  // Same contrast fix as tags — ensure icon color reads on the active button.\n  if (headerColor === \"background\") {\n    return { color: `var(--color-${frameColor})` };\n  }\n  if (headerColor === \"foreground\") {\n    return { color: `var(--color-background)` };\n  }\n  return undefined;\n}\n\nfunction buttonSizeClass(size: ButtonSizeOptions): string {\n  if (size === \"sm\") return \"px-4 py-1.5 text-[12px]\";\n  if (size === \"lg\") return \"px-6 py-3 text-[14px]\";\n  if (size === \"xl\") return \"px-7 py-3.5 text-[15px]\";\n  return \"\";\n}\n\nfunction ChevronLeftIcon() {\n  return (\n    <svg\n      width=\"16\"\n      height=\"16\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      <path d=\"M15 18l-6-6 6-6\" />\n    </svg>\n  );\n}\n\nfunction ChevronRightIcon() {\n  return (\n    <svg\n      width=\"16\"\n      height=\"16\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      aria-hidden=\"true\"\n    >\n      <path d=\"M9 18l6-6-6-6\" />\n    </svg>\n  );\n}\n\nexport const carouselWidgetPropertySchema: WidgetPropertySchema = {\n  widgetType: \"CarouselWidget\",\n  displayName: \"Carousel\",\n  tabsConfig: [\n    { id: \"styling\", label: \"Styling\" },\n    { id: \"behavior\", label: \"Behavior\" },\n    { id: \"data\", label: \"Data\" },\n  ],\n  dataSourceTargetProps: [\"slides\"],\n  fields: [\n    // Styling tab — Frame group (new)\n    {\n      key: \"editorialFrame\",\n      label: \"Editorial Frame\",\n      type: \"boolean\",\n      description:\n        \"Premium dark canvas with layered shadow and gradient stack. Turn off for a classic transparent carousel.\",\n      defaultValue: true,\n      tab: \"styling\",\n      group: \"Frame\",\n    },\n    getColorField({\n      defaultValue: \"foreground\",\n      key: \"frameColor\",\n      label: \"Frame Color\",\n      description:\n        \"Surface color of the carousel canvas. Drives the frame and gradient overlay.\",\n      tab: \"styling\",\n      group: \"Frame\",\n      requiresKeyToBeTrue: \"editorialFrame\",\n    }),\n\n    // Text Styling group\n    getFontSizeField({\n      defaultValue: \"xl\",\n      key: \"headerSize\",\n      label: \"Header Font Size\",\n      description: \"Font size for the slide header\",\n      tab: \"styling\",\n      group: \"Text Styling\",\n    }),\n    getColorField({\n      defaultValue: \"background\",\n      key: \"headerColor\",\n      label: \"Header Color\",\n      description:\n        \"Headline color. Also drives eyebrow, controls and progress bar.\",\n      tab: \"styling\",\n      group: \"Text Styling\",\n    }),\n    {\n      key: \"separator\",\n      type: \"separator\",\n      label: \"Separator\",\n      tab: \"styling\",\n      group: \"Text Styling\",\n    },\n    getFontSizeField({\n      defaultValue: \"md\",\n      key: \"textSize\",\n      label: \"Text Font Size\",\n      description: \"Font size for the slide text\",\n      tab: \"styling\",\n      group: \"Text Styling\",\n    }),\n    getColorField({\n      defaultValue: \"background\",\n      key: \"textColor\",\n      label: \"Text Color\",\n      description: \"Color variant for the slide text\",\n      tab: \"styling\",\n      group: \"Text Styling\",\n    }),\n\n    // Layout group\n    {\n      key: \"align\",\n      label: \"Alignment\",\n      type: \"alignment\",\n      description: \"Alignment of the carousel content\",\n      defaultValue: { vertical: \"bottom\", horizontal: \"left\" },\n      options: {\n        verticalEnabled: true,\n        horizontalEnabled: true,\n      },\n      tab: \"styling\",\n      group: \"Layout\",\n    },\n    {\n      key: \"textWidth\",\n      label: \"Content Width\",\n      type: \"cssUnit\",\n      description: \"Maximum width for slide content\",\n      defaultValue: \"620px\",\n      allowedUnits: [\"px\", \"rem\", \"%\"],\n      defaultUnit: \"px\",\n      minByUnit: { px: 50, rem: 3, \"%\": 10 },\n      maxByUnit: { px: 1200, rem: 75, \"%\": 100 },\n      stepByUnit: { px: 10, rem: 1, \"%\": 1 },\n      tab: \"styling\",\n      group: \"Layout\",\n    },\n\n    // Design group\n    getHeightField({\n      key: \"carouselHeight\",\n      label: \"Carousel Height\",\n      description: \"Height of the carousel\",\n      defaultValue: \"400px\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    {\n      key: \"separator2\",\n      type: \"separator\",\n      label: \"Separator\",\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    getBorderRadiusField({\n      defaultValue: \"xl\",\n      key: \"borderRadius\",\n      label: \"Border Radius\",\n      description: \"Rounded corners for the carousel\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getBorderWidthField({\n      key: \"borderWidth\",\n      label: \"Border Width\",\n      description: \"Border width for the carousel container\",\n      defaultValue: \"none\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getBorderColorField({\n      key: \"borderColor\",\n      label: \"Border Color\",\n      description: \"Border color for the carousel container\",\n      defaultValue: \"muted\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getPaddingField({\n      defaultValue: 8,\n      key: \"padding\",\n      label: \"Padding\",\n      description: \"Inner padding around slide content\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    {\n      key: \"overlayEnabled\",\n      label: \"Enable Overlay\",\n      type: \"boolean\",\n      description: \"Add background overlay to slide content\",\n      defaultValue: true,\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    {\n      key: \"overlayType\",\n      label: \"Overlay Type\",\n      type: \"buttonGroup\",\n      description: \"Overlay style (only applies when editorial frame is off)\",\n      defaultValue: \"gradient\",\n      options: [\n        { label: \"Solid\", value: \"solid\" },\n        { label: \"Gradient\", value: \"gradient\" },\n      ],\n      tab: \"styling\",\n      group: \"Design\",\n      requiresKeyToBeTrue: \"overlayEnabled\",\n    },\n    {\n      key: \"overlayIntensity\",\n      label: \"Overlay Intensity\",\n      type: \"slider\",\n      description: \"Opacity of the overlay (0-100)\",\n      min: 0,\n      max: 100,\n      step: 5,\n      defaultValue: 70,\n      unit: \"%\",\n      tab: \"styling\",\n      group: \"Design\",\n      requiresKeyToBeTrue: \"overlayEnabled\",\n    },\n    {\n      key: \"showButton\",\n      label: \"Show Primary Button\",\n      type: \"boolean\",\n      description:\n        \"Global show/hide for all slide CTAs. Per-slide button content is set on each item under the Data tab (custom sources only).\",\n      defaultValue: true,\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    getColorField({\n      defaultValue: \"background\",\n      key: \"buttonColor\",\n      label: \"Button Color\",\n      description: \"Color variant for the slide button\",\n      tab: \"styling\",\n      group: \"Design\",\n      requiresKeyToBeTrue: \"showButton\",\n    }),\n    getButtonSizeField({\n      defaultValue: \"default\",\n      key: \"buttonSize\",\n      label: \"Button Size\",\n      description: \"Size of the slide button\",\n      tab: \"styling\",\n      group: \"Design\",\n      requiresKeyToBeTrue: \"showButton\",\n    }),\n\n    // Behavior tab\n    {\n      key: \"enableAutoScroll\",\n      label: \"Enable Auto-Scroll\",\n      type: \"boolean\",\n      description:\n        \"Automatically advance to the next slide. Progress bar fills at this rate and pauses on hover.\",\n      defaultValue: false,\n      tab: \"behavior\",\n      group: \"Auto-Scroll\",\n    },\n    {\n      key: \"autoScrollInterval\",\n      label: \"Auto-Scroll Interval (ms)\",\n      type: \"number\",\n      description: \"Time between automatic slide transitions\",\n      min: 1000,\n      max: 15000,\n      step: 500,\n      defaultValue: 6500,\n      tab: \"behavior\",\n      group: \"Auto-Scroll\",\n      requiresKeyToBeTrue: \"enableAutoScroll\",\n    },\n\n    // Data tab\n    {\n      key: \"dataSource\",\n      label: \"Data Source\",\n      type: \"dataSource\",\n      description: \"Configure the slides rendered by the carousel.\",\n      targetProps: [\n        {\n          key: \"slides\",\n          description:\n            \"Slides rendered by the carousel, usually supplied by a data source.\",\n        },\n      ],\n      tab: \"data\",\n      group: \"Data Configuration\",\n    },\n  ],\n  itemConfigSchema: {\n    description: \"Configure settings for this slide\",\n    fields: [\n      {\n        key: \"eyebrow\",\n        label: \"Eyebrow\",\n        type: \"text\",\n        description:\n          \"Short label above the title (e.g. 'From Fluid · Newsroom')\",\n      },\n      {\n        key: \"tag\",\n        label: \"Tag / Category\",\n        type: \"text\",\n        description: \"Short pill label (e.g. 'Policy', 'New release')\",\n      },\n      {\n        key: \"tagColor\",\n        label: \"Tag Color\",\n        type: \"colorSelect\",\n        description: \"Background color of the tag pill\",\n        defaultValue: \"background\",\n      },\n      {\n        key: \"meta\",\n        label: \"Meta\",\n        type: \"text\",\n        description: \"Meta line (e.g. 'Apr 12 · 4 min read')\",\n      },\n      {\n        key: \"separator_slide_1\",\n        type: \"separator\",\n        label: \"Separator\",\n      },\n      {\n        key: \"title\",\n        label: \"Title\",\n        type: \"text\",\n        description: \"Override the item's title for this slide\",\n      },\n      {\n        key: \"description\",\n        label: \"Description\",\n        type: \"textarea\",\n        description: \"Override the item's description for this slide\",\n        rows: 3,\n      },\n      {\n        key: \"separator_slide_2\",\n        type: \"separator\",\n        label: \"Separator\",\n      },\n      {\n        key: \"buttonEnabled\",\n        label: \"Show Primary Button\",\n        type: \"boolean\",\n        description: \"Show the primary CTA on this slide\",\n        defaultValue: false,\n      },\n      {\n        key: \"buttonText\",\n        label: \"Button Text\",\n        type: \"text\",\n        description: \"Text for the primary button\",\n        requiresKeyToBeTrue: \"buttonEnabled\",\n      },\n      {\n        key: \"buttonLink\",\n        label: \"Button Link\",\n        type: \"text\",\n        description: \"URL for the primary button\",\n        requiresKeyToBeTrue: \"buttonEnabled\",\n      },\n      {\n        key: \"secondaryButtonText\",\n        label: \"Secondary Link Text\",\n        type: \"text\",\n        description:\n          \"Optional text-only secondary link (renders with an arrow)\",\n      },\n      {\n        key: \"secondaryButtonLink\",\n        label: \"Secondary Link URL\",\n        type: \"text\",\n        description: \"URL for the secondary link\",\n      },\n      { key: \"separator_link\", type: \"separator\", label: \"Separator\" },\n      ...getLinkTypeFields(),\n    ],\n  },\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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K;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,MAAM;GACN,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD,cAAc;GACZ,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EACF,mBAAmB;GACjB,cAAc;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB;EAGD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,aAAa,CACX;IACE,KAAK;IACL,aACE;IACH,CACF;GACD,KAAK;GACL,OAAO;GACR;EACF;CACD,kBAAkB;EAChB,aAAa;EACb,QAAQ;GACN;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,MAAM;IACP;GACD;IACE,KAAK;IACL,MAAM;IACN,OAAO;IACR;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,cAAc;IACf;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACb,qBAAqB;IACtB;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aACE;IACH;GACD;IACE,KAAK;IACL,OAAO;IACP,MAAM;IACN,aAAa;IACd;GACD;IAAE,KAAK;IAAkB,MAAM;IAAa,OAAO;IAAa;GAChE,GAAG,mBAAmB;GACvB;EACF;CACF"}