@allxsmith/bestax-bulma 5.40.0 → 5.42.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.
Files changed (40) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Carousel.js +282 -103
  4. package/dist/esm/components/Carousel.js.map +1 -1
  5. package/dist/esm/components/Menu.js +77 -2
  6. package/dist/esm/components/Menu.js.map +1 -1
  7. package/dist/esm/components/Modal.js +3 -3
  8. package/dist/esm/components/Modal.js.map +1 -1
  9. package/dist/esm/components/Popover.js +2 -2
  10. package/dist/esm/components/Popover.js.map +1 -1
  11. package/dist/esm/components/Sidebar.js +2 -2
  12. package/dist/esm/components/Sidebar.js.map +1 -1
  13. package/dist/esm/elements/Image.js +4 -12
  14. package/dist/esm/elements/Image.js.map +1 -1
  15. package/dist/esm/helpers/useFocusTrap.js +60 -41
  16. package/dist/esm/helpers/useFocusTrap.js.map +1 -1
  17. package/dist/extras.css +1 -1
  18. package/dist/extras.css.map +1 -1
  19. package/dist/index.cjs +442 -181
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.esm.js +1 -1
  22. package/dist/types/components/Carousel.d.ts +96 -8
  23. package/dist/types/components/Menu.d.ts +49 -0
  24. package/dist/types/elements/Image.d.ts +6 -1
  25. package/dist/types/helpers/useFocusTrap.d.ts +16 -8
  26. package/dist/types-cjs/components/Carousel.d.ts +96 -8
  27. package/dist/types-cjs/components/Menu.d.ts +49 -0
  28. package/dist/types-cjs/elements/Image.d.ts +6 -1
  29. package/dist/types-cjs/helpers/useFocusTrap.d.ts +16 -8
  30. package/dist/versions/bestax-no-dark-mode.css +1 -1
  31. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  32. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  33. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  34. package/dist/versions/bestax-no-helpers.css +1 -1
  35. package/dist/versions/bestax-no-helpers.css.map +1 -1
  36. package/dist/versions/bestax-prefixed.css +1 -1
  37. package/dist/versions/bestax-prefixed.css.map +1 -1
  38. package/package.json +6 -6
  39. package/src/scss/components/_carousel.scss +77 -24
  40. package/src/scss/components/_menu.scss +130 -3
@@ -1 +1 @@
1
- {"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n Children,\n isValidElement,\n cloneElement,\n} from 'react';\nimport {\n classNames,\n prefixedClassNames,\n usePrefixedClassNames,\n} from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useClassPrefix } from '../helpers/Config';\nimport { getActiveElementInTree } from '../helpers/shadowDom';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { Icon } from '../elements/Icon';\nimport { Button } from '../elements/Button';\n\n/**\n * Props for the CarouselItem component.\n */\nexport interface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Whether this item is active (set automatically). */\n active?: boolean;\n}\n\n/**\n * Individual carousel item/slide.\n *\n * @function\n * @param {CarouselItemProps} props - Props for the CarouselItem component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the carousel item element.\n * @returns {JSX.Element} The rendered carousel item.\n */\nexport const CarouselItem = forwardRef<HTMLDivElement, CarouselItemProps>(\n ({ active, className, children, ...props }, ref) => {\n const itemClasses = classNames(\n usePrefixedClassNames('carousel-item', { 'is-active': active }),\n className\n );\n\n return (\n <div ref={ref} className={itemClasses} {...props}>\n {children}\n </div>\n );\n }\n);\n\nCarouselItem.displayName = 'CarouselItem';\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Default SVG icon for the previous arrow button.\n *\n * @function\n * @returns {JSX.Element} The rendered SVG chevron-left icon.\n */\nconst DefaultPrevIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n);\n\n/**\n * Default SVG icon for the next arrow button.\n *\n * @function\n * @returns {JSX.Element} The rendered SVG chevron-right icon.\n */\nconst DefaultNextIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\n/**\n * Props for the Carousel component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the carousel element.\n */\nexport interface CarouselProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'>,\n BulmaClassesProps {\n /**\n * Current active slide index (controlled).\n * @defaultValue 0\n */\n value?: number;\n /** Enable auto-play. */\n autoplay?: boolean;\n /** Auto-play interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Pause auto-play on hover. Default: true. */\n pauseOnHover?: boolean;\n /** Loop back to first slide after last. Default: true. */\n repeat?: boolean;\n /** Enable drag/swipe navigation. Default: true. */\n hasDrag?: boolean;\n /**\n * Show navigation arrows. Default: true. They render `type=\"button\"`, so a\n * carousel inside a form is not submitted by moving between slides.\n */\n arrow?: boolean;\n /** Only show arrows on hover. */\n arrowHover?: boolean;\n /**\n * Show slide indicators. Default: true. They render `type=\"button\"`, so a\n * carousel inside a form is not submitted by picking a slide.\n */\n indicator?: boolean;\n /** Position indicators inside carousel. */\n indicatorInside?: boolean;\n /** Indicator position. Default: 'bottom'. */\n indicatorPosition?: 'bottom' | 'top';\n /** Indicator style. Default: 'dots'. */\n indicatorStyle?: 'circles' | 'dots' | 'lines' | 'bars';\n /** Icon name for the previous arrow button. */\n iconPrev?: string;\n /** Icon name for the next arrow button. */\n iconNext?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Icon size modifier. */\n iconSize?: 'small' | 'medium' | 'large';\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Show semi-transparent background on arrow buttons. Set to `false` for icon-only arrows. */\n arrowBackground?: boolean;\n /** Color theme for navigation arrows. */\n arrowColor?: 'light' | 'dark';\n /** Accessible label for the carousel region. Default: 'Image carousel'. */\n ariaLabel?: string;\n /** Callback when slide changes. */\n onChange?: (value: number) => void;\n /** CarouselItem children. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Carousel` component provides an image/content slider with navigation arrows and indicators.\n *\n * @function\n * @param {CarouselProps} props - Props for the Carousel component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the carousel element.\n * @returns {JSX.Element} The rendered carousel component.\n *\n * @example\n * // Basic carousel\n * <Carousel>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * <CarouselItem>Slide 3</CarouselItem>\n * </Carousel>\n *\n * @example\n * // Auto-playing carousel\n * <Carousel autoplay interval={3000}>\n * <CarouselItem>\n * <img src=\"image1.jpg\" alt=\"Slide 1\" />\n * </CarouselItem>\n * <CarouselItem>\n * <img src=\"image2.jpg\" alt=\"Slide 2\" />\n * </CarouselItem>\n * </Carousel>\n */\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(\n (\n {\n value: controlledValue,\n autoplay = false,\n interval = 5000,\n pauseOnHover = true,\n repeat = true,\n hasDrag = true,\n arrow = true,\n arrowHover = false,\n indicator = true,\n indicatorInside = false,\n indicatorPosition = 'bottom',\n indicatorStyle = 'dots',\n iconPrev,\n iconNext,\n iconLibrary,\n iconVariant,\n iconSize,\n iconFeatures,\n arrowBackground = true,\n arrowColor,\n ariaLabel = 'Image carousel',\n onChange,\n className,\n children,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const carouselRef = useRef<HTMLDivElement>(null);\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n\n const [internalValue, setInternalValue] = useState(0);\n const [isPaused, setIsPaused] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState(0);\n const [dragOffset, setDragOffset] = useState(0);\n const [isWrapping, setIsWrapping] = useState(false);\n const [displayIndex, setDisplayIndex] = useState(0);\n const [skipTransition, setSkipTransition] = useState(false);\n\n // Get valid children\n const items = Children.toArray(children).filter(isValidElement);\n const itemCount = items.length;\n\n // Use controlled or internal value\n const activeIndex =\n controlledValue !== undefined ? controlledValue : internalValue;\n\n // Sync displayIndex when controlled value changes externally. Intentional\n // external-prop sync that must not run mid-wrap animation; covered by tests\n // and certified in-browser.\n useEffect(() => {\n if (controlledValue !== undefined && !isWrapping) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop\n setDisplayIndex(controlledValue);\n }\n }, [controlledValue, isWrapping]);\n\n // Update active index\n const setActiveIndex = useCallback(\n (index: number, syncDisplay = true) => {\n let newIndex = index;\n\n if (repeat) {\n if (index < 0) {\n newIndex = itemCount - 1;\n } else if (index >= itemCount) {\n newIndex = 0;\n }\n } else {\n newIndex = Math.max(0, Math.min(index, itemCount - 1));\n }\n\n if (controlledValue === undefined) {\n setInternalValue(newIndex);\n }\n if (syncDisplay) {\n setDisplayIndex(newIndex);\n }\n onChange?.(newIndex);\n },\n [controlledValue, itemCount, repeat, onChange]\n );\n\n // Navigation handlers\n const goToPrev = useCallback(() => {\n if (activeIndex === 0 && repeat && itemCount > 1) {\n // Animate to clone of last slide (position -1)\n setDisplayIndex(-1);\n setIsWrapping(true);\n } else {\n setActiveIndex(activeIndex - 1);\n }\n }, [activeIndex, repeat, itemCount, setActiveIndex]);\n\n const goToNext = useCallback(() => {\n if (activeIndex === itemCount - 1 && repeat && itemCount > 1) {\n // Animate to clone of first slide (position itemCount)\n setDisplayIndex(itemCount);\n setIsWrapping(true);\n } else {\n setActiveIndex(activeIndex + 1);\n }\n }, [activeIndex, itemCount, repeat, setActiveIndex]);\n\n const goToSlide = useCallback(\n (index: number) => {\n setIsWrapping(false);\n setActiveIndex(index);\n },\n [setActiveIndex]\n );\n\n // Read when the timer fires or an arrow key arrives, so neither the\n // timer nor the key listener starts over while `onChange` changes\n // identity, as an inline one does on every render of the parent.\n const goToPrevRef = useLatestRef(goToPrev);\n const goToNextRef = useLatestRef(goToNext);\n\n // Auto-play. Each slide gets the whole interval, so a slide change,\n // autoplay's own or the user's, starts the timer over. A render that\n // leaves the slide where it is doesn't.\n useEffect(() => {\n if (!autoplay || isPaused || itemCount <= 1) return undefined;\n\n const timer = setInterval(() => {\n goToNextRef.current();\n }, interval);\n\n return () => clearInterval(timer);\n }, [autoplay, isPaused, interval, itemCount, activeIndex, goToNextRef]);\n\n // Pause on hover\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Drag handlers\n const handleDragStart = useCallback(\n (clientX: number) => {\n if (!hasDrag) return;\n setIsDragging(true);\n setDragStart(clientX);\n setDragOffset(0);\n },\n [hasDrag]\n );\n\n const handleDragMove = useCallback(\n (clientX: number) => {\n if (!isDragging) return;\n setDragOffset(clientX - dragStart);\n },\n [isDragging, dragStart]\n );\n\n const handleDragEnd = useCallback(() => {\n if (!isDragging) return;\n setIsDragging(false);\n\n const threshold = 50;\n if (dragOffset < -threshold) {\n goToNext();\n } else if (dragOffset > threshold) {\n goToPrev();\n }\n\n setDragOffset(0);\n }, [isDragging, dragOffset, goToNext, goToPrev]);\n\n // Mouse events\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n handleDragStart(e.clientX);\n },\n [handleDragStart]\n );\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n handleDragMove(e.clientX);\n },\n [handleDragMove]\n );\n\n const handleMouseUp = useCallback(() => {\n handleDragEnd();\n }, [handleDragEnd]);\n\n // Touch events\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n handleDragStart(e.touches[0].clientX);\n },\n [handleDragStart]\n );\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n handleDragMove(e.touches[0].clientX);\n },\n [handleDragMove]\n );\n\n const handleTouchEnd = useCallback(() => {\n handleDragEnd();\n }, [handleDragEnd]);\n\n // Keyboard navigation\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n const node = carouselRef.current;\n if (!node?.contains(getActiveElementInTree(node))) return;\n\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n goToPrevRef.current();\n break;\n case 'ArrowRight':\n e.preventDefault();\n goToNextRef.current();\n break;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [goToPrevRef, goToNextRef]);\n\n // Handle wrap-around transition end\n const handleTransitionEnd = useCallback(() => {\n if (isWrapping) {\n // Skip transition for the instant snap\n setSkipTransition(true);\n setIsWrapping(false);\n\n if (displayIndex === itemCount) {\n // Was at clone of first slide, snap to real first slide\n setActiveIndex(0, false);\n setDisplayIndex(0);\n } else if (displayIndex === -1) {\n // Was at clone of last slide, snap to real last slide\n setActiveIndex(itemCount - 1, false);\n setDisplayIndex(itemCount - 1);\n }\n\n // Re-enable transition after the snap\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setSkipTransition(false);\n });\n });\n }\n }, [isWrapping, displayIndex, itemCount, setActiveIndex]);\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n (carouselRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Toast`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n // Can navigate\n const canGoPrev = repeat || activeIndex > 0;\n const canGoNext = repeat || activeIndex < itemCount - 1;\n\n // Generate classes\n const carouselClasses = usePrefixedClassNames('carousel', {\n 'is-overlay': indicatorInside,\n 'has-arrow-hover': arrowHover,\n [`is-indicator-${indicatorStyle}`]: indicatorStyle !== 'dots',\n [`is-arrow-${arrowColor}`]: !!arrowColor,\n });\n const classPrefix = useClassPrefix();\n const carouselContainerClass = usePrefixedClassNames('carousel-container');\n const carouselSlidesClass = usePrefixedClassNames('carousel-slides');\n const carouselArrowPrevClass = usePrefixedClassNames(\n 'carousel-arrow',\n 'is-prev',\n { 'is-transparent': !arrowBackground }\n );\n const carouselArrowNextClass = usePrefixedClassNames(\n 'carousel-arrow',\n 'is-next',\n { 'is-transparent': !arrowBackground }\n );\n const carouselIndicatorClass = usePrefixedClassNames('carousel-indicator', {\n 'is-inside': indicatorInside,\n 'is-top': indicatorPosition === 'top',\n });\n\n const combinedClasses = classNames(\n carouselClasses,\n bulmaHelperClasses,\n className\n );\n\n // Render slides with active state (includes clones for infinite loop)\n const renderSlides = () => {\n const slides = items.map((item, index) => {\n if (isValidElement<CarouselItemProps>(item)) {\n return cloneElement(item, {\n key: index,\n active: index === activeIndex,\n });\n }\n return item;\n });\n\n // Add clones for seamless infinite loop when repeat is enabled\n if (repeat && itemCount > 1) {\n const lastItem = items[itemCount - 1];\n const firstItem = items[0];\n\n const lastClone = isValidElement<CarouselItemProps>(lastItem)\n ? cloneElement(lastItem as React.ReactElement<CarouselItemProps>, {\n key: 'clone-last',\n active: false,\n })\n : null;\n\n const firstClone = isValidElement<CarouselItemProps>(firstItem)\n ? cloneElement(firstItem as React.ReactElement<CarouselItemProps>, {\n key: 'clone-first',\n active: false,\n })\n : null;\n\n return [lastClone, ...slides, firstClone];\n }\n\n return slides;\n };\n\n return (\n <div\n ref={combinedRef}\n className={combinedClasses}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label={ariaLabel}\n {...rest}\n >\n <div\n ref={containerRef}\n className={carouselContainerClass}\n onMouseDown={hasDrag ? handleMouseDown : undefined}\n onMouseMove={hasDrag && isDragging ? handleMouseMove : undefined}\n onMouseUp={hasDrag ? handleMouseUp : undefined}\n onMouseLeave={hasDrag ? handleMouseUp : undefined}\n onTouchStart={hasDrag ? handleTouchStart : undefined}\n onTouchMove={hasDrag ? handleTouchMove : undefined}\n onTouchEnd={hasDrag ? handleTouchEnd : undefined}\n style={{\n transform: isDragging ? `translateX(${dragOffset}px)` : undefined,\n cursor: hasDrag ? (isDragging ? 'grabbing' : 'grab') : undefined,\n }}\n >\n <div\n className={carouselSlidesClass}\n style={{\n // When repeat is enabled, account for the prepended clone (+1 offset)\n transform: `translateX(-${(repeat && itemCount > 1 ? displayIndex + 1 : displayIndex) * 100}%)`,\n // Disable transition during drag or instant snap after wrap-around\n transition:\n isDragging || skipTransition\n ? 'none'\n : 'transform 0.3s ease-in-out',\n }}\n onTransitionEnd={handleTransitionEnd}\n >\n {renderSlides()}\n </div>\n {arrow && itemCount > 1 && (\n <>\n <Button\n type=\"button\"\n className={carouselArrowPrevClass}\n onClick={goToPrev}\n isDisabled={!canGoPrev}\n aria-label=\"Previous slide\"\n >\n {iconPrev ? (\n <Icon\n name={iconPrev}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n ) : (\n <DefaultPrevIcon />\n )}\n </Button>\n <Button\n type=\"button\"\n className={carouselArrowNextClass}\n onClick={goToNext}\n isDisabled={!canGoNext}\n aria-label=\"Next slide\"\n >\n {iconNext ? (\n <Icon\n name={iconNext}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n ) : (\n <DefaultNextIcon />\n )}\n </Button>\n </>\n )}\n </div>\n\n {indicator && itemCount > 1 && (\n <div className={carouselIndicatorClass} role=\"tablist\">\n {items.map((_, index) => (\n <Button\n key={index}\n type=\"button\"\n className={prefixedClassNames(classPrefix, 'indicator-item', {\n 'is-active': index === activeIndex,\n })}\n onClick={() => goToSlide(index)}\n role=\"tab\"\n aria-selected={index === activeIndex}\n aria-label={`Go to slide ${index + 1}`}\n />\n ))}\n </div>\n )}\n </div>\n );\n }\n);\n\nCarousel.displayName = 'Carousel';\n\nexport default Carousel;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Carousel.js","sources":["../../../src/components/Carousel.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useState,\n useRef,\n useEffect,\n useCallback,\n Children,\n isValidElement,\n cloneElement,\n} from 'react';\nimport {\n classNames,\n prefixedClassNames,\n usePrefixedClassNames,\n} from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { useClassPrefix } from '../helpers/Config';\nimport { getActiveElementInTree } from '../helpers/shadowDom';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport { inertProps } from '../helpers/inertProps';\nimport { Icon } from '../elements/Icon';\nimport { Button } from '../elements/Button';\n\n/**\n * Props for the CarouselItem component.\n */\nexport interface CarouselItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Whether this item is in view. `Carousel` sets it on every item in view,\n * so with several in view several are active.\n */\n active?: boolean;\n}\n\n/**\n * Individual carousel item/slide.\n *\n * @function\n * @param {CarouselItemProps} props - Props for the CarouselItem component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the carousel item element.\n * @returns {JSX.Element} The rendered carousel item.\n */\nexport const CarouselItem = forwardRef<HTMLDivElement, CarouselItemProps>(\n ({ active, className, children, ...props }, ref) => {\n const itemClasses = classNames(\n usePrefixedClassNames('carousel-item', { 'is-active': active }),\n className\n );\n\n return (\n <div ref={ref} className={itemClasses} {...props}>\n {children}\n </div>\n );\n }\n);\n\nCarouselItem.displayName = 'CarouselItem';\n\ntype IconLibrary = 'fa' | 'mdi' | 'ion' | 'material-icons' | 'material-symbols';\n\n/**\n * Default SVG icon for the previous arrow button.\n *\n * @function\n * @returns {JSX.Element} The rendered SVG chevron-left icon.\n */\nconst DefaultPrevIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"15 18 9 12 15 6\" />\n </svg>\n);\n\n/**\n * Default SVG icon for the next arrow button.\n *\n * @function\n * @returns {JSX.Element} The rendered SVG chevron-right icon.\n */\nconst DefaultNextIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n);\n\n/**\n * The media queries Bulma's `fullhd`, `widescreen`, `desktop` and `tablet`\n * mixins open with, widest first, at Bulma's default breakpoints. The\n * stylesheet picks the count in view with those mixins; these tell the\n * script which count that is. Narrower than the last one is `mobile`.\n */\nconst VIEWPORT_QUERIES = [\n 'screen and (min-width: 1408px)',\n 'screen and (min-width: 1216px)',\n 'screen and (min-width: 1024px)',\n 'screen and (min-width: 769px), print',\n];\n\n/** `useBulmaViewport`'s answer below the tablet breakpoint. */\nconst MOBILE = VIEWPORT_QUERIES.length;\n\n/**\n * The `--bulma-carousel-items-to-show*` variable each count prop writes, in\n * the order the component lists them: the viewports as above, mobile, and\n * last `itemsToShow` itself.\n */\nconst COUNT_SUFFIXES = [\n '-fullhd',\n '-widescreen',\n '-desktop',\n '-tablet',\n '-mobile',\n '',\n];\n\n/**\n * Which of Bulma's viewports the window is in: the index of the widest\n * `VIEWPORT_QUERIES` entry that matches, `MOBILE` below them all, or `-1`\n * when that isn't known (on the server, before the first layout effect, and\n * whenever `enabled` is off, so a carousel with one count everywhere\n * subscribes to nothing).\n *\n * @function\n * @param {boolean} enabled - Whether any viewport-specific count is set.\n * @returns {number} The viewport, as described above.\n */\nfunction useBulmaViewport(enabled: boolean): number {\n const [viewport, setViewport] = useState(-1);\n\n useClientLayoutEffect(() => {\n if (!enabled || typeof window.matchMedia !== 'function') return undefined;\n const lists = VIEWPORT_QUERIES.map(query => window.matchMedia(query));\n const update = () => {\n const index = lists.findIndex(list => list.matches);\n setViewport(index < 0 ? MOBILE : index);\n };\n update();\n lists.forEach(list => list.addEventListener('change', update));\n return () =>\n lists.forEach(list => list.removeEventListener('change', update));\n }, [enabled]);\n\n return enabled ? viewport : -1;\n}\n\n/**\n * A count prop as the whole number the carousel works with: rounded down,\n * and never below 1, so a zero or a stray `NaN` can't divide by nothing.\n *\n * @function\n * @param {number | undefined} count - The prop as given.\n * @returns {number | undefined} The count, or `undefined` when unset.\n */\nconst wholeCount = (count: number | undefined) =>\n count === undefined ? undefined : Math.max(1, Math.floor(count) || 1);\n\n/**\n * Props for the Carousel component.\n * @extraProp {string} [className] - Additional CSS classes.\n * @extraProp {React.Ref<HTMLElement>} [ref] - Ref forwarded to the carousel element.\n */\nexport interface CarouselProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'>,\n BulmaClassesProps {\n /**\n * Index of the first item in view (controlled); with one item in view, the\n * slide shown. A value between two of the positions a step lands on (see\n * `itemsToScroll`) is shown as given, and the next step goes on from it.\n * With `repeat`, a value past either end wraps around; without it, one\n * that would leave empty space after the last item shows the last full\n * view. Neither correction calls `onChange`. A value that takes the item\n * holding focus out of view moves focus to the first item in view, as a\n * swipe or a change of width does.\n * @defaultValue 0\n */\n value?: number;\n /**\n * Enable auto-play: one step (`itemsToScroll` items) per `interval`.\n * Without `repeat` it stops at the last position. It waits while the\n * pointer is over the carousel (see `pauseOnHover`) and while focus is\n * inside one of its items, so an item being read or used never moves out\n * of view.\n */\n autoplay?: boolean;\n /** Auto-play interval in milliseconds. Default: 5000. */\n interval?: number;\n /** Pause auto-play on hover. Default: true. */\n pauseOnHover?: boolean;\n /**\n * Loop back to the first position after the last. Default: true. With\n * several items in view, the view runs on past the last item into the\n * first ones, so it can show the end and the start side by side. Only\n * loops when some item is out of view.\n */\n repeat?: boolean;\n /**\n * Enable drag/swipe navigation. Default: true. A swipe moves one step,\n * however far it travels.\n */\n hasDrag?: boolean;\n /**\n * How many items are in view at once, at every width no\n * `itemsToShow<Viewport>` prop covers. Those props read the way a\n * `Column`'s `size<Viewport>` props do: `itemsToShowMobile` applies below\n * Bulma's tablet breakpoint, each of the others from its own breakpoint\n * up, and where several apply the widest one wins. A whole number, rounded\n * down and at least 1. The widths come from the stylesheet, so they are\n * right on the first paint; the arrows, indicators and steps use the\n * count for the window's width once the page has hydrated, and this one\n * until then. With this many children or fewer, every item keeps its\n * share of the width, nothing moves, and no arrows or indicators render.\n * @defaultValue 1\n */\n itemsToShow?: number;\n /**\n * Items in view at any width below Bulma's tablet breakpoint (769px),\n * fractional ones included. Falls back to `itemsToShow`.\n */\n itemsToShowMobile?: number;\n /**\n * Items in view from Bulma's tablet breakpoint (769px) up, until a wider\n * viewport's prop takes over. Falls back to `itemsToShow`.\n */\n itemsToShowTablet?: number;\n /**\n * Items in view from Bulma's desktop breakpoint (1024px) up, until a wider\n * viewport's prop takes over. Falls back to `itemsToShowTablet`, then\n * `itemsToShow`.\n */\n itemsToShowDesktop?: number;\n /**\n * Items in view from Bulma's widescreen breakpoint (1216px) up, until\n * `itemsToShowFullhd` takes over. Falls back to `itemsToShowDesktop`, and\n * on down to `itemsToShow`.\n */\n itemsToShowWidescreen?: number;\n /**\n * Items in view from Bulma's fullhd breakpoint (1408px) up. Falls back to\n * `itemsToShowWidescreen`, and on down to `itemsToShow`.\n */\n itemsToShowFullhd?: number;\n /**\n * How many items one step moves, for an arrow, an arrow key, a swipe or an\n * autoplay tick. A whole number, capped at the count in view so a step\n * never skips an item. Without `repeat`, the last step stops at the last\n * full view, so it can be shorter; with `repeat`, the step after the last\n * position goes on to the first one. The indicators mark these positions,\n * one per step rather than one per item. When the count in view changes\n * with the window's width, the first item in view stays in view.\n * @defaultValue 1\n */\n itemsToScroll?: number;\n /**\n * Show navigation arrows. Default: true. They render `type=\"button\"`, so a\n * carousel inside a form is not submitted by moving between slides.\n */\n arrow?: boolean;\n /** Only show arrows on hover. */\n arrowHover?: boolean;\n /**\n * Show slide indicators. Default: true. There is one for each position a\n * step can land on (see `itemsToScroll`). They render `type=\"button\"`, so\n * a carousel inside a form is not submitted by picking a slide.\n */\n indicator?: boolean;\n /** Position indicators inside carousel. */\n indicatorInside?: boolean;\n /** Indicator position. Default: 'bottom'. */\n indicatorPosition?: 'bottom' | 'top';\n /** Indicator style. Default: 'dots'. */\n indicatorStyle?: 'circles' | 'dots' | 'lines' | 'bars';\n /** Icon name for the previous arrow button. */\n iconPrev?: string;\n /** Icon name for the next arrow button. */\n iconNext?: string;\n /** Icon library to use. */\n iconLibrary?: IconLibrary;\n /** Icon style variant (e.g., 'solid', 'outlined'). */\n iconVariant?: string;\n /** Icon size modifier. */\n iconSize?: 'small' | 'medium' | 'large';\n /** Additional icon modifiers. */\n iconFeatures?: string | string[];\n /** Show semi-transparent background on arrow buttons. Set to `false` for icon-only arrows. */\n arrowBackground?: boolean;\n /** Color theme for navigation arrows. */\n arrowColor?: 'light' | 'dark';\n /** Accessible label for the carousel region. Default: 'Image carousel'. */\n ariaLabel?: string;\n /**\n * Called with the index of the first item in view when an arrow, an arrow\n * key, an indicator, a swipe or autoplay moves the carousel.\n */\n onChange?: (value: number) => void;\n /** CarouselItem children. */\n children?: React.ReactNode;\n}\n\n/**\n * The `Carousel` component provides an image/content slider with navigation arrows and indicators.\n *\n * @function\n * @param {CarouselProps} props - Props for the Carousel component.\n * @param {React.Ref<HTMLDivElement>} ref - Forwarded ref to the carousel element.\n * @returns {JSX.Element} The rendered carousel component.\n *\n * @example\n * // Basic carousel\n * <Carousel>\n * <CarouselItem>Slide 1</CarouselItem>\n * <CarouselItem>Slide 2</CarouselItem>\n * <CarouselItem>Slide 3</CarouselItem>\n * </Carousel>\n *\n * @example\n * // Auto-playing carousel\n * <Carousel autoplay interval={3000}>\n * <CarouselItem>\n * <img src=\"image1.jpg\" alt=\"Slide 1\" />\n * </CarouselItem>\n * <CarouselItem>\n * <img src=\"image2.jpg\" alt=\"Slide 2\" />\n * </CarouselItem>\n * </Carousel>\n *\n * @example\n * // Three cards in view on desktop, two on tablet, one on mobile\n * <Carousel itemsToShow={1} itemsToShowTablet={2} itemsToShowDesktop={3}>\n * {cards.map(card => (\n * <CarouselItem key={card.id}>{card.body}</CarouselItem>\n * ))}\n * </Carousel>\n */\nexport const Carousel = forwardRef<HTMLDivElement, CarouselProps>(\n (\n {\n value: controlledValue,\n autoplay = false,\n interval = 5000,\n pauseOnHover = true,\n repeat = true,\n hasDrag = true,\n itemsToShow,\n itemsToShowMobile,\n itemsToShowTablet,\n itemsToShowDesktop,\n itemsToShowWidescreen,\n itemsToShowFullhd,\n itemsToScroll,\n arrow = true,\n arrowHover = false,\n indicator = true,\n indicatorInside = false,\n indicatorPosition = 'bottom',\n indicatorStyle = 'dots',\n iconPrev,\n iconNext,\n iconLibrary,\n iconVariant,\n iconSize,\n iconFeatures,\n arrowBackground = true,\n arrowColor,\n ariaLabel = 'Image carousel',\n onChange,\n className,\n style,\n children,\n ...props\n },\n ref\n ) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const carouselRef = useRef<HTMLDivElement>(null);\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const slidesRef = useRef<HTMLDivElement>(null);\n // The item (a child of the track) that holds focus, until focus leaves\n // the items for somewhere else\n const focusedItemRef = useRef<Element | undefined>(undefined);\n\n const [internalValue, setInternalValue] = useState(0);\n const [isPaused, setIsPaused] = useState(false);\n const [isFocusInside, setIsFocusInside] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n const [dragStart, setDragStart] = useState(0);\n const [dragOffset, setDragOffset] = useState(0);\n const [isWrapping, setIsWrapping] = useState(false);\n const [displayIndex, setDisplayIndex] = useState(0);\n const [skipTransition, setSkipTransition] = useState(false);\n\n // Get valid children\n const items = Children.toArray(children).filter(\n isValidElement\n ) as React.ReactElement<CarouselItemProps>[];\n const itemCount = items.length;\n\n // The count in view. The viewport props come widest first, in the order\n // of VIEWPORT_QUERIES, then mobile; each min-width viewport falls back to\n // the narrower ones, and every viewport to `itemsToShow`, the cascade the\n // stylesheet's `--bulma-carousel-items-to-show-*` defaults spell out.\n const counts = [\n itemsToShowFullhd,\n itemsToShowWidescreen,\n itemsToShowDesktop,\n itemsToShowTablet,\n itemsToShowMobile,\n ].map(wholeCount);\n const baseCount = wholeCount(itemsToShow);\n const viewport = useBulmaViewport(counts.some(c => c !== undefined));\n const inView =\n (viewport === MOBILE\n ? counts[MOBILE]\n : viewport >= 0\n ? counts.slice(viewport, MOBILE).find(c => c !== undefined)\n : undefined) ??\n baseCount ??\n 1;\n // The props as the stylesheet reads them, so the widths are right from\n // the first paint, on the server too.\n const countStyle: Record<string, number> = {};\n [...counts, baseCount].forEach((count, i) => {\n if (count !== undefined) {\n countStyle[`--bulma-carousel-items-to-show${COUNT_SUFFIXES[i]}`] =\n count;\n }\n });\n\n const scroll = Math.min(wholeCount(itemsToScroll) ?? 1, inView);\n const looping = repeat && itemCount > inView;\n const lastStart = Math.max(0, itemCount - inView);\n // Where the view can start: every `scroll` items from the first, and\n // without a loop the last full view as well, which is what keeps the\n // end of the track from showing empty space.\n const positions: number[] = [];\n for (let p = 0; p < (looping ? itemCount : lastStart); p += scroll) {\n positions.push(p);\n }\n if (!looping) positions.push(lastStart);\n const lastPosition = positions[positions.length - 1];\n const canMove = positions.length > 1;\n\n const wrap = (index: number) =>\n ((index % itemCount) + itemCount) % itemCount;\n const fit = (index: number) =>\n looping ? wrap(index) : Math.min(Math.max(index, 0), lastStart);\n\n // Use controlled or internal value, as a start the view can show\n const activeIndex = fit(controlledValue ?? internalValue);\n // The indicator for the last position at or before the first item in view\n const activePosition = positions.reduce(\n (found, position, index) => (position <= activeIndex ? index : found),\n 0\n );\n const nextIndex = positions[activePosition + 1];\n // From between two positions, the previous step is the one just behind\n const prevIndex =\n activeIndex > positions[activePosition]\n ? positions[activePosition]\n : positions[activePosition - 1];\n\n // Sync displayIndex when the value changes externally, or when the count\n // in view moves the start it fits to. Intentional external-prop sync that\n // must not run mid-wrap animation; covered by tests and certified\n // in-browser. Uncontrolled, the fitted start becomes the value too, so a\n // later change of count keeps what was first in view in view.\n useEffect(() => {\n if (!isWrapping) {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- syncing to controlled prop\n setDisplayIndex(activeIndex);\n if (controlledValue === undefined) setInternalValue(activeIndex);\n }\n }, [activeIndex, isWrapping, controlledValue]);\n\n // Update active index\n const setActiveIndex = useCallback(\n (index: number) => {\n if (controlledValue === undefined) {\n setInternalValue(index);\n }\n setDisplayIndex(index);\n setIsWrapping(false);\n onChange?.(index);\n },\n [controlledValue, onChange]\n );\n\n // Navigation handlers\n const goToPrev = useCallback(() => {\n if (prevIndex !== undefined) {\n setActiveIndex(prevIndex);\n } else if (looping) {\n // Animate to the clones before the first item, which show the last\n // position, and snap to the real one when the transition ends\n setDisplayIndex(lastPosition - itemCount);\n setIsWrapping(true);\n }\n }, [prevIndex, looping, lastPosition, itemCount, setActiveIndex]);\n\n const goToNext = useCallback(() => {\n if (nextIndex !== undefined) {\n setActiveIndex(nextIndex);\n } else if (looping) {\n // Animate to the clones after the last item, which show the first\n // position, and snap to the real one when the transition ends\n setDisplayIndex(itemCount);\n setIsWrapping(true);\n }\n }, [nextIndex, looping, itemCount, setActiveIndex]);\n\n // Read when the timer fires or an arrow key arrives, so neither the\n // timer nor the key listener starts over while `onChange` changes\n // identity, as an inline one does on every render of the parent.\n const goToPrevRef = useLatestRef(goToPrev);\n const goToNextRef = useLatestRef(goToNext);\n\n // Auto-play. Each slide gets the whole interval, so a slide change,\n // autoplay's own or the user's, starts the timer over. A render that\n // leaves the slide where it is doesn't. It waits while focus is inside\n // an item, so what someone is reading or using doesn't move away. The\n // timer reads where focus is when it fires, rather than trusting the\n // last focus event alone: a browser moving focus off an element that\n // went inert need not fire one, and the pause would never end. A focus\n // change still starts the timer over, so an item gets the whole\n // interval once focus leaves it.\n const isPlaying =\n autoplay && (looping || nextIndex !== undefined) && !isPaused;\n const isRotating = isPlaying && !isFocusInside;\n\n useEffect(() => {\n if (!isPlaying) return undefined;\n\n const timer = setInterval(() => {\n const track = slidesRef.current;\n if (track?.contains(getActiveElementInTree(track))) return;\n if (isFocusInside) setIsFocusInside(false);\n goToNextRef.current();\n }, interval);\n\n return () => clearInterval(timer);\n }, [isPlaying, isFocusInside, interval, activeIndex, goToNextRef]);\n\n // Pause on hover\n const handleMouseEnter = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(true);\n }\n }, [pauseOnHover]);\n\n const handleMouseLeave = useCallback(() => {\n if (pauseOnHover) {\n setIsPaused(false);\n }\n }, [pauseOnHover]);\n\n // Drag handlers\n const handleDragStart = useCallback(\n (clientX: number) => {\n if (!hasDrag) return;\n setIsDragging(true);\n setDragStart(clientX);\n setDragOffset(0);\n },\n [hasDrag]\n );\n\n const handleDragMove = useCallback(\n (clientX: number) => {\n if (!isDragging) return;\n setDragOffset(clientX - dragStart);\n },\n [isDragging, dragStart]\n );\n\n const handleDragEnd = useCallback(() => {\n if (!isDragging) return;\n setIsDragging(false);\n\n const threshold = 50;\n if (dragOffset < -threshold) {\n goToNext();\n } else if (dragOffset > threshold) {\n goToPrev();\n }\n\n setDragOffset(0);\n }, [isDragging, dragOffset, goToNext, goToPrev]);\n\n // Mouse events\n const handleMouseDown = useCallback(\n (e: React.MouseEvent) => {\n e.preventDefault();\n handleDragStart(e.clientX);\n },\n [handleDragStart]\n );\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent) => {\n handleDragMove(e.clientX);\n },\n [handleDragMove]\n );\n\n const handleMouseUp = useCallback(() => {\n handleDragEnd();\n }, [handleDragEnd]);\n\n // Touch events\n const handleTouchStart = useCallback(\n (e: React.TouchEvent) => {\n handleDragStart(e.touches[0].clientX);\n },\n [handleDragStart]\n );\n\n const handleTouchMove = useCallback(\n (e: React.TouchEvent) => {\n handleDragMove(e.touches[0].clientX);\n },\n [handleDragMove]\n );\n\n const handleTouchEnd = useCallback(() => {\n handleDragEnd();\n }, [handleDragEnd]);\n\n // Keyboard navigation, from the carousel's own controls. Inside an item\n // the keys are its content's (a field's caret, a slider), and a step\n // from there could take the focused item out of view.\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n const node = carouselRef.current;\n const active = getActiveElementInTree(node);\n if (!node?.contains(active) || slidesRef.current?.contains(active)) {\n return;\n }\n\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n goToPrevRef.current();\n break;\n case 'ArrowRight':\n e.preventDefault();\n goToNextRef.current();\n break;\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [goToPrevRef, goToNextRef]);\n\n // Handle wrap-around transition end: the track's own, since an item's\n // content can end a transition of its own that bubbles up to here\n const handleTransitionEnd = useCallback(\n (e: React.TransitionEvent<HTMLDivElement>) => {\n if (isWrapping && e.target === e.currentTarget) {\n // Skip transition for the instant snap from the clones to the\n // real items they copy\n setSkipTransition(true);\n setActiveIndex(((displayIndex % itemCount) + itemCount) % itemCount);\n\n // Re-enable transition after the snap\n requestAnimationFrame(() => {\n requestAnimationFrame(() => {\n setSkipTransition(false);\n });\n });\n }\n },\n [isWrapping, displayIndex, itemCount, setActiveIndex]\n );\n\n // Combined ref\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n (carouselRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches by\n // running it instead of calling the ref with `null`; React 18 discards the\n // return value entirely. Returning it from here would be a React-19-only\n // contract, so we hold the cleanup and run it ourselves on detach — the\n // same shape as `Dropdown`, `Modal`, `Dialog`, `Sidebar` and `Toast`.\n // The form controls that merge a forwarded ref still discard the cleanup\n // and detach with `ref(null)`, so this is not yet library-wide — grep\n // `typeof ref === 'function'` for the current split.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n\n // Can navigate\n const canGoPrev = looping || prevIndex !== undefined;\n const canGoNext = looping || nextIndex !== undefined;\n\n // Generate classes\n const carouselClasses = usePrefixedClassNames('carousel', {\n 'is-overlay': indicatorInside,\n 'has-arrow-hover': arrowHover,\n [`is-indicator-${indicatorStyle}`]: indicatorStyle !== 'dots',\n [`is-arrow-${arrowColor}`]: !!arrowColor,\n });\n const classPrefix = useClassPrefix();\n const carouselContainerClass = usePrefixedClassNames('carousel-container');\n const carouselSlidesClass = usePrefixedClassNames('carousel-slides');\n const carouselArrowPrevClass = usePrefixedClassNames(\n 'carousel-arrow',\n 'is-prev',\n { 'is-transparent': !arrowBackground }\n );\n const carouselArrowNextClass = usePrefixedClassNames(\n 'carousel-arrow',\n 'is-next',\n { 'is-transparent': !arrowBackground }\n );\n const carouselIndicatorClass = usePrefixedClassNames('carousel-indicator', {\n 'is-inside': indicatorInside,\n 'is-top': indicatorPosition === 'top',\n });\n\n const combinedClasses = classNames(\n carouselClasses,\n bulmaHelperClasses,\n className\n );\n\n // Where the track is drawn from: mid-wrap the clones, otherwise a start\n // the view can show, so a change in the count in view never paints\n // empty space while the sync above catches up.\n const shownIndex = isWrapping ? displayIndex : fit(displayIndex);\n // Enough clones on each side to fill the widest view any viewport sets,\n // since the stylesheet, not this count, sizes what's on screen\n const cloneCount = looping\n ? Math.min(\n itemCount,\n Math.max(baseCount ?? 1, ...counts.map(c => c ?? 1))\n )\n : 0;\n // The track: a full view's worth of clones of the last items, the items,\n // and clones of the first ones, for a seamless loop. Each entry is the\n // item it shows and its key.\n const slots: [number, React.Key][] = items.map((_, index) => [\n index,\n index,\n ]);\n for (let k = 0; k < cloneCount; k++) {\n slots.splice(k, 0, [itemCount - cloneCount + k, `clone-before-${k}`]);\n slots.push([k, `clone-after-${k}`]);\n }\n\n // Render slides with active state (includes clones for infinite loop).\n // What's in view is a run of slots, so where a looping view runs past\n // the last item, the clones on screen are the live copies and the items\n // they copy, off screen, are the hidden ones: no item is exposed twice,\n // and the copy exposed is the one in view.\n const renderSlides = () =>\n slots.map(([index, key], slot) => {\n const item = items[index];\n const own = item.props;\n const isShown =\n slot >= shownIndex + cloneCount &&\n slot < shownIndex + cloneCount + inView;\n return cloneElement(item, {\n key,\n active: isShown,\n role: own.role ?? 'group',\n 'aria-roledescription': own['aria-roledescription'] ?? 'slide',\n ...(own['aria-label'] || own['aria-labelledby']\n ? {}\n : { 'aria-label': `${index + 1} of ${itemCount}` }),\n // Out of view: hidden from assistive tech, and inert, so nothing\n // in it takes focus or a click\n ...(isShown ? {} : { 'aria-hidden': true, ...inertProps(true) }),\n });\n });\n\n // Hand focus on when the item holding it leaves the view. An item out\n // of view is inert, and a browser drops focus from an inert element to\n // the page, so a swipe, a change of count with the window's width, a new\n // controlled value or the item's removal would leave a keyboard or\n // screen reader user nowhere. Focus goes to the first item in view,\n // given `tabindex=\"-1\"` for it unless it has a tabindex of its own. A\n // layout effect runs before the browser gets to drop the focus; the\n // focused item's removal drops it at once, so focus on the page itself\n // still counts as the item's.\n useClientLayoutEffect(() => {\n const held = focusedItemRef.current;\n if (!held) return;\n const track = slidesRef.current as HTMLDivElement;\n const start = shownIndex + cloneCount;\n const slot = Array.prototype.indexOf.call(track.children, held);\n if (slot >= start && slot < start + inView) return;\n const active = getActiveElementInTree(track);\n if (active !== held.ownerDocument.body && !held.contains(active)) {\n return;\n }\n focusedItemRef.current = undefined;\n const first = track.children[start] as HTMLElement | undefined;\n if (!first) return;\n if (!first.hasAttribute('tabindex')) first.tabIndex = -1;\n first.focus({ preventScroll: true });\n }, [shownIndex, cloneCount, inView, itemCount]);\n\n return (\n <div\n ref={combinedRef}\n className={combinedClasses}\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label={ariaLabel}\n style={{ ...countStyle, ...style }}\n {...rest}\n >\n <div\n ref={containerRef}\n className={carouselContainerClass}\n onMouseDown={hasDrag ? handleMouseDown : undefined}\n onMouseMove={hasDrag && isDragging ? handleMouseMove : undefined}\n onMouseUp={hasDrag ? handleMouseUp : undefined}\n onMouseLeave={hasDrag ? handleMouseUp : undefined}\n onTouchStart={hasDrag ? handleTouchStart : undefined}\n onTouchMove={hasDrag ? handleTouchMove : undefined}\n onTouchEnd={hasDrag ? handleTouchEnd : undefined}\n style={{\n transform: isDragging ? `translateX(${dragOffset}px)` : undefined,\n cursor: hasDrag ? (isDragging ? 'grabbing' : 'grab') : undefined,\n }}\n >\n <div\n ref={slidesRef}\n className={carouselSlidesClass}\n style={{\n // One item is the track's width plus a gap, over the count the\n // stylesheet has in view; account for the prepended clones\n transform: `translateX(calc(${-(shownIndex + cloneCount)} * (100% + var(--bulma-carousel-item-gap, 0px)) / var(--bulma-carousel-items-in-view, 1)))`,\n // Disable transition during drag or instant snap after wrap-around\n transition:\n isDragging || skipTransition\n ? 'none'\n : 'transform 0.3s ease-in-out',\n }}\n // Announce what comes into view, except while autoplay turns it\n aria-live={isRotating ? 'off' : 'polite'}\n onFocus={e => {\n setIsFocusInside(true);\n focusedItemRef.current = Array.from(\n e.currentTarget.children\n ).find(item => item.contains(e.target));\n }}\n onBlur={e => {\n const inside = e.currentTarget.contains(e.relatedTarget);\n setIsFocusInside(inside);\n if (!inside) focusedItemRef.current = undefined;\n }}\n onTransitionEnd={handleTransitionEnd}\n >\n {renderSlides()}\n </div>\n {arrow && canMove && (\n <>\n <Button\n type=\"button\"\n className={carouselArrowPrevClass}\n onClick={goToPrev}\n isDisabled={!canGoPrev}\n aria-label=\"Previous slide\"\n >\n {iconPrev ? (\n <Icon\n name={iconPrev}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n ) : (\n <DefaultPrevIcon />\n )}\n </Button>\n <Button\n type=\"button\"\n className={carouselArrowNextClass}\n onClick={goToNext}\n isDisabled={!canGoNext}\n aria-label=\"Next slide\"\n >\n {iconNext ? (\n <Icon\n name={iconNext}\n library={iconLibrary}\n variant={iconVariant}\n size={iconSize}\n features={iconFeatures}\n />\n ) : (\n <DefaultNextIcon />\n )}\n </Button>\n </>\n )}\n </div>\n\n {indicator && canMove && (\n <div className={carouselIndicatorClass} role=\"tablist\">\n {positions.map((position, index) => (\n <Button\n key={position}\n type=\"button\"\n className={prefixedClassNames(classPrefix, 'indicator-item', {\n 'is-active': index === activePosition,\n })}\n onClick={() => setActiveIndex(position)}\n role=\"tab\"\n aria-selected={index === activePosition}\n aria-label={`Go to slide ${position + 1}`}\n />\n ))}\n </div>\n )}\n </div>\n );\n }\n);\n\nCarousel.displayName = 'Carousel';\n\nexport default Carousel;\n"],"names":["_jsx","_jsxs","_Fragment"],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  /* @allxsmith/bestax-bulma — AI agents: see AGENTS.md in the package root, or https://bestax.io/llms.txt */
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
- import React, { createContext, forwardRef, useContext } from 'react';
3
+ import React, { createContext, forwardRef, useContext, useId, useRef, useState } from 'react';
4
4
  import { classNames, usePrefixedClassNames } from '../helpers/classNames.js';
5
5
  import { useBulmaClasses } from '../helpers/useBulmaClasses.js';
6
6
  import { withSubComponents } from '../helpers/withSubComponents.js';
7
7
  import { omitAttrs } from '../helpers/anchorAttrs.js';
8
8
  import { buttonType } from '../helpers/buttonType.js';
9
+ import { inertProps } from '../helpers/inertProps.js';
10
+ import { getActiveElementInTree } from '../helpers/shadowDom.js';
11
+ import { useClientLayoutEffect } from '../helpers/useClientLayoutEffect.js';
9
12
  import { isCustomElement } from '../helpers/polymorphic.js';
10
13
 
11
14
  // Context to track MenuList nesting level
@@ -117,12 +120,84 @@ const MenuItem = forwardRef(function MenuItem(itemProps, ref) {
117
120
  : {}), children: labelChildren }), nestedMenuLists] }));
118
121
  });
119
122
  MenuItem.displayName = 'MenuItem';
123
+ /**
124
+ * A section of the menu that opens and closes: its heading is a button drawn like `Menu.Label`, and its `Menu.List` of links shows while it's open.
125
+ *
126
+ * It's APG's disclosure navigation, for a sidebar of link groups: the links
127
+ * stay ordinary links, each its own tab stop, and a closed section's list is
128
+ * `hidden` and `inert`, so Tab and assistive tech skip it. It goes directly in
129
+ * `Menu`, holding a `Menu.List`. Closing it while focus is on one of its links
130
+ * moves focus to its heading.
131
+ *
132
+ * @function
133
+ * @param {MenuSectionProps} props - Props for the MenuSection component.
134
+ * @returns {JSX.Element} The rendered menu section.
135
+ * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/ | APG Disclosure Navigation Menu example}
136
+ *
137
+ * @example
138
+ * <Menu>
139
+ * <Menu.Section label="Components" defaultOpen>
140
+ * <Menu.List>
141
+ * <Menu.Item href="/button" active>Button</Menu.Item>
142
+ * <Menu.Item href="/card">Card</Menu.Item>
143
+ * </Menu.List>
144
+ * </Menu.Section>
145
+ * </Menu>
146
+ */
147
+ const MenuSection = ({ className, label, children, open: controlledOpen, defaultOpen = false, onOpenChange, ...props }) => {
148
+ const { bulmaHelperClasses, rest } = useBulmaClasses(props);
149
+ const sectionClass = usePrefixedClassNames('menu-section');
150
+ const toggleClass = usePrefixedClassNames('menu-section-toggle');
151
+ const labelClass = usePrefixedClassNames('menu-section-label');
152
+ const chevronClass = usePrefixedClassNames('menu-section-chevron');
153
+ const listId = useId();
154
+ const toggleRef = useRef(null);
155
+ const listRef = useRef(null);
156
+ // The caller owns the state when `open` is set, and the section does
157
+ // otherwise, as with Collapse. The button reports in both modes.
158
+ const isControlled = controlledOpen !== undefined;
159
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
160
+ const isOpen = controlledOpen ?? internalOpen;
161
+ const handleClick = () => {
162
+ const next = !isOpen;
163
+ onOpenChange?.(next);
164
+ if (!isControlled)
165
+ setInternalOpen(next);
166
+ };
167
+ // An app holding `open` can close a section while focus is on one of its
168
+ // links, as a sidebar that keeps only the current route's section open
169
+ // does after a link is followed. The browser then drops focus to <body>
170
+ // a frame later, and the next Tab starts from the top of the page. The
171
+ // heading is where the reader was, so focus goes there. A layout effect,
172
+ // because it runs in the same task as the commit that hid the list, while
173
+ // the link still has focus. A close from the button itself finds focus on
174
+ // the button and leaves it.
175
+ useClientLayoutEffect(() => {
176
+ if (isOpen)
177
+ return;
178
+ const list = listRef.current;
179
+ if (list.contains(getActiveElementInTree(list))) {
180
+ toggleRef.current.focus();
181
+ }
182
+ }, [isOpen]);
183
+ // A real button, so Enter and Space work with no key handler, and
184
+ // `type="button"`, so a menu inside a form isn't submitted by it.
185
+ //
186
+ // A closed list is `hidden`, so it isn't drawn and find-in-page doesn't
187
+ // reach it, and `inert`, so its links stay out of Tab and assistive tech
188
+ // even if a stylesheet sets `display` on it and shows it anyway. The markup
189
+ // is the same from the server and on both React majors, which `inertProps`
190
+ // sees to. It stays mounted, so `aria-controls` always names an element
191
+ // that exists.
192
+ return (jsxs("div", { className: classNames(sectionClass, bulmaHelperClasses, className), ...rest, children: [jsxs("button", { ref: toggleRef, type: "button", className: toggleClass, "aria-expanded": isOpen, "aria-controls": listId, onClick: handleClick, children: [jsx("span", { className: labelClass, children: label }), jsx("span", { className: chevronClass, "aria-hidden": "true" })] }), jsx("div", { ref: listRef, id: listId, hidden: !isOpen, ...inertProps(!isOpen), children: children })] }));
193
+ };
120
194
  // Attach static subcomponents
121
195
  const Menu = withSubComponents(MenuComponent, {
122
196
  Label: MenuLabel,
123
197
  List: MenuList,
124
198
  Item: MenuItem,
199
+ Section: MenuSection,
125
200
  }, 'Menu');
126
201
 
127
- export { Menu, MenuItem, MenuLabel, MenuList };
202
+ export { Menu, MenuItem, MenuLabel, MenuList, MenuSection };
128
203
  //# sourceMappingURL=Menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","sources":["../../../src/components/Menu.tsx"],"sourcesContent":["import React, { createContext, forwardRef, useContext } from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { omitAttrs } from '../helpers/anchorAttrs';\nimport { buttonType } from '../helpers/buttonType';\nimport {\n isCustomElement,\n type PolymorphicComponent,\n} from '../helpers/polymorphic';\n\n// Context to track MenuList nesting level\nconst MenuListLevelContext = createContext(0);\n\n/**\n * Props for the Menu component.\n */\nexport interface MenuProps\n extends\n Omit<React.HTMLAttributes<HTMLElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** Menu content (labels, lists, items, etc). */\n children: React.ReactNode;\n}\n\n/**\n * The `Menu` component provides Bulma's vertical navigation menu: a simple, accessible sidebar or section menu for your Bulma React UI.\n *\n * @function\n * @param {MenuProps} props - Props for the Menu component.\n * @returns {JSX.Element} The rendered menu.\n * @see {@link https://bulma.io/documentation/components/menu/ | Bulma Menu documentation}\n */\nconst MenuComponent: React.FC<MenuProps> = ({\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('menu');\n\n return (\n <aside\n className={classNames(bulmaClasses, bulmaHelperClasses, className)}\n {...rest}\n >\n {children}\n </aside>\n );\n};\n\n/**\n * Props for the MenuLabel component.\n */\nexport interface MenuLabelProps\n extends\n Omit<React.HTMLAttributes<HTMLParagraphElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** Label content. */\n children: React.ReactNode;\n}\n\n/**\n * Bulma Menu label component.\n *\n * @function\n * @param {MenuLabelProps} props - Props for the MenuLabel component.\n * @returns {JSX.Element} The rendered menu label.\n */\nexport const MenuLabel: React.FC<MenuLabelProps> = ({\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n return (\n <p\n className={classNames(\n usePrefixedClassNames('menu-label'),\n className,\n bulmaHelperClasses\n )}\n {...rest}\n >\n {children}\n </p>\n );\n};\n\n/**\n * Props for the MenuList component.\n * @extraProp {React.AriaRole} [role] - Ignored: every level renders `role=\"list\"` in its place, so a menu or tree role can't go here.\n */\nexport interface MenuListProps\n extends\n Omit<React.HTMLAttributes<HTMLUListElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** List items. */\n children: React.ReactNode;\n}\n\n/**\n * MenuList applies `menu-list` class only at the top level (not for nested lists).\n *\n * Every level renders `role=\"list\"`, which Safari needs: WebKit stops\n * exposing a `<ul>` as a list once its markers are hidden, and Bulma's reset\n * hides them.\n *\n * @function\n * @param {MenuListProps} props - Props for the MenuList component.\n * @returns {JSX.Element} The rendered menu list.\n */\nexport const MenuList: React.FC<MenuListProps> = ({\n className,\n children,\n ...props\n}) => {\n const level = useContext(MenuListLevelContext);\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n const ulClass = classNames(className, bulmaHelperClasses, {\n [usePrefixedClassNames('menu-list')]: level === 0,\n });\n\n // Increment level for nested MenuLists. role=\"list\" restates the <ul>'s\n // own role, for Safari: WebKit stops exposing a list as one once its\n // markers are hidden, as Bulma's reset hides them, unless the role is set\n // explicitly. After the spread, so a caller's role can't take it away.\n return (\n <MenuListLevelContext.Provider value={level + 1}>\n <ul className={ulClass || undefined} {...rest} role=\"list\">\n {children}\n </ul>\n </MenuListLevelContext.Provider>\n );\n};\n\n/**\n * The MenuItem component's own props.\n *\n * A menu item is two elements: a wrapping `<li>` and, inside it, the element\n * `as` names. The props here are the ones the `<li>` consumes; everything else\n * follows `as` onto the inner element.\n */\nexport interface MenuItemOwnProps extends BulmaClassesProps {\n /** Additional CSS classes for the wrapping `<li>`. */\n className?: string;\n /** Item content and optional nested MenuList. */\n children: React.ReactNode;\n /**\n * Marks the item as the current one. It adds Bulma's `is-active` class, and\n * `aria-current=\"page\"` on the element `as` renders, so assistive tech can\n * tell which item is current too. An `aria-current` you pass wins, even\n * `undefined`: use it to say something else (`\"location\"` for a section of\n * one page, say), or `aria-current={false}` to turn it off. A menu should\n * mark one page, so when the section above the current page is `active` too,\n * give it `aria-current=\"location\"`, and give an `active` item that isn't\n * navigation, such as an `as=\"button\"` filter, `aria-current={false}`.\n */\n active?: boolean;\n /** Inline styles for the wrapping `<li>`. */\n style?: React.CSSProperties;\n /** `id` for the wrapping `<li>`. */\n id?: string;\n /** `title` for the wrapping `<li>`. */\n title?: string;\n /** ARIA role for the wrapping `<li>`. */\n role?: React.AriaRole;\n /** Tab index for the wrapping `<li>`. */\n tabIndex?: number;\n /** Test id for the wrapping `<li>`. */\n 'data-testid'?: string;\n}\n\n/**\n * Props for the MenuItem component. Everything the `<li>` does not consume\n * follows `as` onto the inner element: with the default `'a'` that means `href`\n * and the other anchor attributes, and with `as={Link}` it means that\n * component's own props.\n *\n * @extraProp {PolymorphicRef<React.ElementType>} [ref] - Ref forwarded to the inner element `as` renders, not the wrapping `<li>`, typed from `as`: the DOM node for an intrinsic tag, or whatever handle a custom component exposes.\n */\nexport type MenuItemProps<T extends React.ElementType = 'a'> =\n MenuItemOwnProps &\n Omit<React.ComponentPropsWithoutRef<T>, keyof MenuItemOwnProps | 'as'> & {\n /**\n * Custom link component (e.g. `Link` from router).\n *\n * `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so\n * an item inside a form does not submit it.\n */\n as?: T;\n };\n\n/**\n * `href` alone — annotated so a typo is a compile error rather than a silent\n * no-op, the way both siblings' sets are.\n */\nconst STRIP_FROM_NON_LINK: Readonly<Record<'href', true>> = { href: true };\n\n/**\n * The shape the implementation destructures. The public contract is the generic\n * `MenuItemProps<T>` above — the body cannot see through `T`.\n */\ntype MenuItemImplProps = MenuItemOwnProps & {\n as?: React.ElementType;\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n};\n\n/**\n * MenuItem supports `as` prop for custom link components, e.g., react-router-dom Link.\n *\n * Give each item an `href`, a router link through `as`, or `as=\"button\"`, so\n * the keyboard can reach it: an `<a>` with no `href` isn't a link, and Tab\n * skips it.\n *\n * @function\n * @param {MenuItemProps} props - Props for the MenuItem component.\n * @param {React.Ref} ref - Forwarded ref to the inner element `as` renders.\n * @returns {JSX.Element} The rendered menu item.\n */\nexport const MenuItem = forwardRef(function MenuItem(\n itemProps: MenuItemProps,\n ref: React.Ref<HTMLElement>\n) {\n const {\n className,\n children,\n active,\n as: Component = 'a',\n 'data-testid': testId,\n style,\n id,\n title,\n role,\n tabIndex,\n ...rest\n } = itemProps as MenuItemImplProps;\n const { bulmaHelperClasses, rest: forwarded } = useBulmaClasses(rest);\n // `href` reaches an anchor or a custom component (which owns its own prop\n // contract), but not another intrinsic tag — `<span href>` is invalid HTML.\n // The same rule Avatar applies through `isLinkLike` and Button through its\n // intrinsic-only strip. Before #641 `href` was an own prop re-applied only\n // for `as=\"a\"`; deriving it from `as` must not quietly widen that.\n const isLinkLike =\n Component === 'a' ||\n typeof Component !== 'string' ||\n isCustomElement(Component);\n // `href` ALONE. `Dropdown.Item` strips every anchor-only attribute except\n // `type`; `Level.Item` strips all of them, plus `rel`.\n //\n // Not because nothing else can arrive: `as` here is an open `React.ElementType`,\n // and a non-fresh spread skips excess-property checking, so a typed caller\n // CAN deliver `target` or `download` and they are forwarded. The set stays at\n // `href` because widening it would be wrong for an open `as` — `referrerPolicy`\n // on `as=\"img\"`, `target` on `as=\"form\"` and `media` on `as=\"source\"` are all\n // legal, and a flat strip would delete them. Getting that right needs a\n // per-attribute-per-element rule, which `bestax-migrate` already models in\n // `LINK_ATTR_ELEMENTS`.\n const linkProps = isLinkLike\n ? forwarded\n : omitAttrs(forwarded, STRIP_FROM_NON_LINK);\n const itemClass = classNames(\n { [usePrefixedClassNames('is-active')]: active },\n bulmaHelperClasses\n );\n\n // Split children into label and nested MenuList(s)\n const labelChildren: React.ReactNode[] = [];\n const nestedMenuLists: React.ReactNode[] = [];\n React.Children.forEach(children, child => {\n if (React.isValidElement(child) && child.type === MenuList) {\n nestedMenuLists.push(child);\n } else {\n labelChildren.push(child);\n }\n });\n\n return (\n <li\n className={className}\n data-testid={testId}\n style={style}\n id={id}\n title={title}\n role={role}\n tabIndex={tabIndex}\n >\n <Component\n ref={ref}\n className={itemClass || undefined}\n // The active item is the current page, the way Pagination marks its\n // page. Before the spread, so an `aria-current` the caller passes\n // decides, `false` and `undefined` included. bestax-migrate converts\n // `is-active` to `active` only beside an `aria-current` of the\n // element's own, and relies on that to render the same markup.\n aria-current={active ? 'page' : undefined}\n {...linkProps}\n // A menu item inside a form must not submit it, and `<button>` defaults\n // to type=\"submit\". A sidebar menu sitting in a form is ordinary. A\n // caller's `submit` or `reset` still wins. Anything else becomes\n // `button`, since HTML reads a value it does not define for a button as\n // submit too; `buttonType` says more.\n //\n // After `linkProps`, reading through it rather than before it: React\n // treats `type={undefined}` as \"remove the attribute\", and a spread\n // carrying the key with no value is how that arrives, so a default\n // spread first would be erased by it. `Dropdown.Item` and `Avatar`\n // apply their button type after the spread too.\n {...(Component === 'button'\n ? { type: buttonType(linkProps.type) }\n : {})}\n >\n {labelChildren}\n </Component>\n {nestedMenuLists}\n </li>\n );\n}) as PolymorphicComponent<MenuItemOwnProps, 'a'>;\n\nMenuItem.displayName = 'MenuItem';\n\n// Attach static subcomponents\nexport const Menu = withSubComponents(\n MenuComponent,\n {\n Label: MenuLabel,\n List: MenuList,\n Item: MenuItem,\n },\n 'Menu'\n);\n\nexport default Menu;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Menu.js","sources":["../../../src/components/Menu.tsx"],"sourcesContent":["import React, {\n createContext,\n forwardRef,\n useContext,\n useId,\n useRef,\n useState,\n} from 'react';\nimport { classNames, usePrefixedClassNames } from '../helpers/classNames';\nimport { useBulmaClasses, BulmaClassesProps } from '../helpers/useBulmaClasses';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { omitAttrs } from '../helpers/anchorAttrs';\nimport { buttonType } from '../helpers/buttonType';\nimport { inertProps } from '../helpers/inertProps';\nimport { getActiveElementInTree } from '../helpers/shadowDom';\nimport { useClientLayoutEffect } from '../helpers/useClientLayoutEffect';\nimport {\n isCustomElement,\n type PolymorphicComponent,\n} from '../helpers/polymorphic';\n\n// Context to track MenuList nesting level\nconst MenuListLevelContext = createContext(0);\n\n/**\n * Props for the Menu component.\n */\nexport interface MenuProps\n extends\n Omit<React.HTMLAttributes<HTMLElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** Menu content (labels, lists, items, etc). */\n children: React.ReactNode;\n}\n\n/**\n * The `Menu` component provides Bulma's vertical navigation menu: a simple, accessible sidebar or section menu for your Bulma React UI.\n *\n * @function\n * @param {MenuProps} props - Props for the Menu component.\n * @returns {JSX.Element} The rendered menu.\n * @see {@link https://bulma.io/documentation/components/menu/ | Bulma Menu documentation}\n */\nconst MenuComponent: React.FC<MenuProps> = ({\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('menu');\n\n return (\n <aside\n className={classNames(bulmaClasses, bulmaHelperClasses, className)}\n {...rest}\n >\n {children}\n </aside>\n );\n};\n\n/**\n * Props for the MenuLabel component.\n */\nexport interface MenuLabelProps\n extends\n Omit<React.HTMLAttributes<HTMLParagraphElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** Label content. */\n children: React.ReactNode;\n}\n\n/**\n * Bulma Menu label component.\n *\n * @function\n * @param {MenuLabelProps} props - Props for the MenuLabel component.\n * @returns {JSX.Element} The rendered menu label.\n */\nexport const MenuLabel: React.FC<MenuLabelProps> = ({\n className,\n children,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n return (\n <p\n className={classNames(\n usePrefixedClassNames('menu-label'),\n className,\n bulmaHelperClasses\n )}\n {...rest}\n >\n {children}\n </p>\n );\n};\n\n/**\n * Props for the MenuList component.\n * @extraProp {React.AriaRole} [role] - Ignored: every level renders `role=\"list\"` in its place, so a menu or tree role can't go here.\n */\nexport interface MenuListProps\n extends\n Omit<React.HTMLAttributes<HTMLUListElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes. */\n className?: string;\n /** List items. */\n children: React.ReactNode;\n}\n\n/**\n * MenuList applies `menu-list` class only at the top level (not for nested lists).\n *\n * Every level renders `role=\"list\"`, which Safari needs: WebKit stops\n * exposing a `<ul>` as a list once its markers are hidden, and Bulma's reset\n * hides them.\n *\n * @function\n * @param {MenuListProps} props - Props for the MenuList component.\n * @returns {JSX.Element} The rendered menu list.\n */\nexport const MenuList: React.FC<MenuListProps> = ({\n className,\n children,\n ...props\n}) => {\n const level = useContext(MenuListLevelContext);\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n\n const ulClass = classNames(className, bulmaHelperClasses, {\n [usePrefixedClassNames('menu-list')]: level === 0,\n });\n\n // Increment level for nested MenuLists. role=\"list\" restates the <ul>'s\n // own role, for Safari: WebKit stops exposing a list as one once its\n // markers are hidden, as Bulma's reset hides them, unless the role is set\n // explicitly. After the spread, so a caller's role can't take it away.\n return (\n <MenuListLevelContext.Provider value={level + 1}>\n <ul className={ulClass || undefined} {...rest} role=\"list\">\n {children}\n </ul>\n </MenuListLevelContext.Provider>\n );\n};\n\n/**\n * The MenuItem component's own props.\n *\n * A menu item is two elements: a wrapping `<li>` and, inside it, the element\n * `as` names. The props here are the ones the `<li>` consumes; everything else\n * follows `as` onto the inner element.\n */\nexport interface MenuItemOwnProps extends BulmaClassesProps {\n /** Additional CSS classes for the wrapping `<li>`. */\n className?: string;\n /** Item content and optional nested MenuList. */\n children: React.ReactNode;\n /**\n * Marks the item as the current one. It adds Bulma's `is-active` class, and\n * `aria-current=\"page\"` on the element `as` renders, so assistive tech can\n * tell which item is current too. An `aria-current` you pass wins, even\n * `undefined`: use it to say something else (`\"location\"` for a section of\n * one page, say), or `aria-current={false}` to turn it off. A menu should\n * mark one page, so when the section above the current page is `active` too,\n * give it `aria-current=\"location\"`, and give an `active` item that isn't\n * navigation, such as an `as=\"button\"` filter, `aria-current={false}`.\n */\n active?: boolean;\n /** Inline styles for the wrapping `<li>`. */\n style?: React.CSSProperties;\n /** `id` for the wrapping `<li>`. */\n id?: string;\n /** `title` for the wrapping `<li>`. */\n title?: string;\n /** ARIA role for the wrapping `<li>`. */\n role?: React.AriaRole;\n /** Tab index for the wrapping `<li>`. */\n tabIndex?: number;\n /** Test id for the wrapping `<li>`. */\n 'data-testid'?: string;\n}\n\n/**\n * Props for the MenuItem component. Everything the `<li>` does not consume\n * follows `as` onto the inner element: with the default `'a'` that means `href`\n * and the other anchor attributes, and with `as={Link}` it means that\n * component's own props.\n *\n * @extraProp {PolymorphicRef<React.ElementType>} [ref] - Ref forwarded to the inner element `as` renders, not the wrapping `<li>`, typed from `as`: the DOM node for an intrinsic tag, or whatever handle a custom component exposes.\n */\nexport type MenuItemProps<T extends React.ElementType = 'a'> =\n MenuItemOwnProps &\n Omit<React.ComponentPropsWithoutRef<T>, keyof MenuItemOwnProps | 'as'> & {\n /**\n * Custom link component (e.g. `Link` from router).\n *\n * `'button'` renders `type=\"button\"` unless you pass `type=\"submit\"` or `type=\"reset\"`, so\n * an item inside a form does not submit it.\n */\n as?: T;\n };\n\n/**\n * `href` alone — annotated so a typo is a compile error rather than a silent\n * no-op, the way both siblings' sets are.\n */\nconst STRIP_FROM_NON_LINK: Readonly<Record<'href', true>> = { href: true };\n\n/**\n * The shape the implementation destructures. The public contract is the generic\n * `MenuItemProps<T>` above — the body cannot see through `T`.\n */\ntype MenuItemImplProps = MenuItemOwnProps & {\n as?: React.ElementType;\n type?: React.ButtonHTMLAttributes<HTMLButtonElement>['type'];\n};\n\n/**\n * MenuItem supports `as` prop for custom link components, e.g., react-router-dom Link.\n *\n * Give each item an `href`, a router link through `as`, or `as=\"button\"`, so\n * the keyboard can reach it: an `<a>` with no `href` isn't a link, and Tab\n * skips it.\n *\n * @function\n * @param {MenuItemProps} props - Props for the MenuItem component.\n * @param {React.Ref} ref - Forwarded ref to the inner element `as` renders.\n * @returns {JSX.Element} The rendered menu item.\n */\nexport const MenuItem = forwardRef(function MenuItem(\n itemProps: MenuItemProps,\n ref: React.Ref<HTMLElement>\n) {\n const {\n className,\n children,\n active,\n as: Component = 'a',\n 'data-testid': testId,\n style,\n id,\n title,\n role,\n tabIndex,\n ...rest\n } = itemProps as MenuItemImplProps;\n const { bulmaHelperClasses, rest: forwarded } = useBulmaClasses(rest);\n // `href` reaches an anchor or a custom component (which owns its own prop\n // contract), but not another intrinsic tag — `<span href>` is invalid HTML.\n // The same rule Avatar applies through `isLinkLike` and Button through its\n // intrinsic-only strip. Before #641 `href` was an own prop re-applied only\n // for `as=\"a\"`; deriving it from `as` must not quietly widen that.\n const isLinkLike =\n Component === 'a' ||\n typeof Component !== 'string' ||\n isCustomElement(Component);\n // `href` ALONE. `Dropdown.Item` strips every anchor-only attribute except\n // `type`; `Level.Item` strips all of them, plus `rel`.\n //\n // Not because nothing else can arrive: `as` here is an open `React.ElementType`,\n // and a non-fresh spread skips excess-property checking, so a typed caller\n // CAN deliver `target` or `download` and they are forwarded. The set stays at\n // `href` because widening it would be wrong for an open `as` — `referrerPolicy`\n // on `as=\"img\"`, `target` on `as=\"form\"` and `media` on `as=\"source\"` are all\n // legal, and a flat strip would delete them. Getting that right needs a\n // per-attribute-per-element rule, which `bestax-migrate` already models in\n // `LINK_ATTR_ELEMENTS`.\n const linkProps = isLinkLike\n ? forwarded\n : omitAttrs(forwarded, STRIP_FROM_NON_LINK);\n const itemClass = classNames(\n { [usePrefixedClassNames('is-active')]: active },\n bulmaHelperClasses\n );\n\n // Split children into label and nested MenuList(s)\n const labelChildren: React.ReactNode[] = [];\n const nestedMenuLists: React.ReactNode[] = [];\n React.Children.forEach(children, child => {\n if (React.isValidElement(child) && child.type === MenuList) {\n nestedMenuLists.push(child);\n } else {\n labelChildren.push(child);\n }\n });\n\n return (\n <li\n className={className}\n data-testid={testId}\n style={style}\n id={id}\n title={title}\n role={role}\n tabIndex={tabIndex}\n >\n <Component\n ref={ref}\n className={itemClass || undefined}\n // The active item is the current page, the way Pagination marks its\n // page. Before the spread, so an `aria-current` the caller passes\n // decides, `false` and `undefined` included. bestax-migrate converts\n // `is-active` to `active` only beside an `aria-current` of the\n // element's own, and relies on that to render the same markup.\n aria-current={active ? 'page' : undefined}\n {...linkProps}\n // A menu item inside a form must not submit it, and `<button>` defaults\n // to type=\"submit\". A sidebar menu sitting in a form is ordinary. A\n // caller's `submit` or `reset` still wins. Anything else becomes\n // `button`, since HTML reads a value it does not define for a button as\n // submit too; `buttonType` says more.\n //\n // After `linkProps`, reading through it rather than before it: React\n // treats `type={undefined}` as \"remove the attribute\", and a spread\n // carrying the key with no value is how that arrives, so a default\n // spread first would be erased by it. `Dropdown.Item` and `Avatar`\n // apply their button type after the spread too.\n {...(Component === 'button'\n ? { type: buttonType(linkProps.type) }\n : {})}\n >\n {labelChildren}\n </Component>\n {nestedMenuLists}\n </li>\n );\n}) as PolymorphicComponent<MenuItemOwnProps, 'a'>;\n\nMenuItem.displayName = 'MenuItem';\n\n/**\n * Props for the MenuSection component. The helper props and the other\n * attributes land on the wrapping `<div>`.\n */\nexport interface MenuSectionProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, keyof BulmaClassesProps>,\n BulmaClassesProps {\n /** Additional CSS classes for the wrapping `<div>`. */\n className?: string;\n /** **Required.** The section's heading, drawn like `Menu.Label` inside the button that opens and closes it. Keep links and buttons out of it, since it's inside one. */\n label: React.ReactNode;\n /**\n * The `Menu.List` of links the section shows while it's open. The section\n * itself goes directly in `Menu`, beside its labels and lists: inside a\n * `Menu.Item` it would render inside the item's link, and inside a\n * `Menu.List` it wouldn't be a list item.\n */\n children: React.ReactNode;\n /** Controlled open state. If provided, the section is controlled, and its button only reports through `onOpenChange`. */\n open?: boolean;\n /** Initial open state for uncontrolled usage. Open the section that holds the current page, so the reader sees where they are. */\n defaultOpen?: boolean;\n /** Called with the state the button asks for (`true` to open) each time it is clicked or activated with Enter or Space, in every mode. Pair it with `open` to let the button drive a controlled section. */\n onOpenChange?: (open: boolean) => void;\n}\n\n/**\n * A section of the menu that opens and closes: its heading is a button drawn like `Menu.Label`, and its `Menu.List` of links shows while it's open.\n *\n * It's APG's disclosure navigation, for a sidebar of link groups: the links\n * stay ordinary links, each its own tab stop, and a closed section's list is\n * `hidden` and `inert`, so Tab and assistive tech skip it. It goes directly in\n * `Menu`, holding a `Menu.List`. Closing it while focus is on one of its links\n * moves focus to its heading.\n *\n * @function\n * @param {MenuSectionProps} props - Props for the MenuSection component.\n * @returns {JSX.Element} The rendered menu section.\n * @see {@link https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/ | APG Disclosure Navigation Menu example}\n *\n * @example\n * <Menu>\n * <Menu.Section label=\"Components\" defaultOpen>\n * <Menu.List>\n * <Menu.Item href=\"/button\" active>Button</Menu.Item>\n * <Menu.Item href=\"/card\">Card</Menu.Item>\n * </Menu.List>\n * </Menu.Section>\n * </Menu>\n */\nexport const MenuSection: React.FC<MenuSectionProps> = ({\n className,\n label,\n children,\n open: controlledOpen,\n defaultOpen = false,\n onOpenChange,\n ...props\n}) => {\n const { bulmaHelperClasses, rest } = useBulmaClasses(props);\n const sectionClass = usePrefixedClassNames('menu-section');\n const toggleClass = usePrefixedClassNames('menu-section-toggle');\n const labelClass = usePrefixedClassNames('menu-section-label');\n const chevronClass = usePrefixedClassNames('menu-section-chevron');\n const listId = useId();\n const toggleRef = useRef<HTMLButtonElement>(null);\n const listRef = useRef<HTMLDivElement>(null);\n\n // The caller owns the state when `open` is set, and the section does\n // otherwise, as with Collapse. The button reports in both modes.\n const isControlled = controlledOpen !== undefined;\n const [internalOpen, setInternalOpen] = useState(defaultOpen);\n const isOpen = controlledOpen ?? internalOpen;\n\n const handleClick = () => {\n const next = !isOpen;\n onOpenChange?.(next);\n if (!isControlled) setInternalOpen(next);\n };\n\n // An app holding `open` can close a section while focus is on one of its\n // links, as a sidebar that keeps only the current route's section open\n // does after a link is followed. The browser then drops focus to <body>\n // a frame later, and the next Tab starts from the top of the page. The\n // heading is where the reader was, so focus goes there. A layout effect,\n // because it runs in the same task as the commit that hid the list, while\n // the link still has focus. A close from the button itself finds focus on\n // the button and leaves it.\n useClientLayoutEffect(() => {\n if (isOpen) return;\n const list = listRef.current!;\n if (list.contains(getActiveElementInTree(list))) {\n toggleRef.current!.focus();\n }\n }, [isOpen]);\n\n // A real button, so Enter and Space work with no key handler, and\n // `type=\"button\"`, so a menu inside a form isn't submitted by it.\n //\n // A closed list is `hidden`, so it isn't drawn and find-in-page doesn't\n // reach it, and `inert`, so its links stay out of Tab and assistive tech\n // even if a stylesheet sets `display` on it and shows it anyway. The markup\n // is the same from the server and on both React majors, which `inertProps`\n // sees to. It stays mounted, so `aria-controls` always names an element\n // that exists.\n return (\n <div\n className={classNames(sectionClass, bulmaHelperClasses, className)}\n {...rest}\n >\n <button\n ref={toggleRef}\n type=\"button\"\n className={toggleClass}\n aria-expanded={isOpen}\n aria-controls={listId}\n onClick={handleClick}\n >\n <span className={labelClass}>{label}</span>\n <span className={chevronClass} aria-hidden=\"true\" />\n </button>\n <div ref={listRef} id={listId} hidden={!isOpen} {...inertProps(!isOpen)}>\n {children}\n </div>\n </div>\n );\n};\n\n// Attach static subcomponents\nexport const Menu = withSubComponents(\n MenuComponent,\n {\n Label: MenuLabel,\n List: MenuList,\n Item: MenuItem,\n Section: MenuSection,\n },\n 'Menu'\n);\n\nexport default Menu;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
@@ -13,7 +13,7 @@ import { usePortalContainer } from '../helpers/portal.js';
13
13
  import { useIsHydrated } from '../helpers/useIsHydrated.js';
14
14
  import { useLatestRef } from '../helpers/useLatestRef.js';
15
15
  import { useOverlayStack } from '../helpers/overlayStack.js';
16
- import { trapTab, firstTabStop } from '../helpers/useFocusTrap.js';
16
+ import { trapTab, focusTabStop } from '../helpers/useFocusTrap.js';
17
17
 
18
18
  /**
19
19
  * Modal.Background - Renders the modal background overlay.
@@ -260,8 +260,8 @@ const ModalRoot = forwardRef(function ModalRoot({ active, isActive, onClose, cla
260
260
  previouslyFocusedRef.current =
261
261
  getDeepestActiveElement();
262
262
  const node = modalRootRef.current;
263
- const focusable = node ? firstTabStop(node) : null;
264
- (focusable ?? node)?.focus();
263
+ if (node)
264
+ focusTabStop(node);
265
265
  return () => {
266
266
  // Only hand focus back if this modal still owns it: closing a background
267
267
  // modal must not pull focus out of one that is still open on top. A
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sources":["../../../src/components/Modal.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { buttonType } from '../helpers/buttonType';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useConfig } from '../helpers/Config';\nimport { useScrollLock } from '../helpers/scrollLock';\nimport {\n getActiveElementInTree,\n getDeepestActiveElement,\n} from '../helpers/shadowDom';\nimport { usePortalContainer } from '../helpers/portal';\nimport { useIsHydrated } from '../helpers/useIsHydrated';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\nimport { firstTabStop, trapTab } from '../helpers/useFocusTrap';\n\n/**\n * Props for the Modal component.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root `.modal` element.\n */\nexport interface ModalProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Whether the modal is open/visible. */\n active?: boolean;\n /** Alias for `active`. Whether the modal is open/visible. */\n isActive?: boolean; // Alias for active\n /** Callback invoked to request modal close (background or close button). */\n onClose?: () => void;\n /** Additional CSS classes for the modal. */\n className?: string;\n /** Text color for modal content. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color for modal content. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Title/header for modal-card variant. (Legacy API only) */\n modalCardTitle?: React.ReactNode;\n /** Footer for modal-card variant. (Legacy API only) */\n modalCardFoot?: React.ReactNode;\n /**\n * Modal style: `'card'` for modal-card, `'content'` for modal-content. (Legacy API only)\n * @defaultValue auto\n */\n type?: 'card' | 'content';\n /** Modal body/content or compound components. */\n children?: React.ReactNode;\n /**\n * Close the modal when the Escape key is pressed (calls `onClose`). Only the\n * topmost open overlay responds, whichever Modal, Dialog, Sidebar or\n * full-page Loading opened last, so Escape closes one layer at a time. The\n * modal marks the Escape it closes on as used with `preventDefault()`, and\n * a Toast waits until no overlay is open. Turned off, a modal on top still\n * keeps Escape from the layers under it. A popup inside it, such as a\n * Dropdown's menu or a date picker's calendar, takes its own Escape first,\n * and so does content that calls `preventDefault()` on it.\n * @defaultValue true\n */\n closeOnEscape?: boolean;\n /**\n * Lock body scroll while the modal is active. Ref-counted and shared with\n * `Dialog`, `Sidebar` and `Loading`, so whichever overlay closes first does\n * not unlock the page underneath one that is still open.\n * @defaultValue true\n */\n lockScroll?: boolean;\n /**\n * Renders the modal into a portal target instead of inline, so it isn't\n * clipped by an ancestor with `overflow: hidden`, `filter` or `transform`.\n * `true` portals to the `portalContainer` a `ConfigProvider` sets,\n * `document.body` by default; a string is used as a\n * `document.querySelector` selector; an element is used directly. Renders\n * inline on the server and while hydrating, moving into the portal once the\n * client takes over, so hydration matches.\n * @defaultValue false\n */\n portal?: boolean | string | HTMLElement;\n}\n\n/**\n * Props for Modal.Background component.\n */\nexport interface ModalBackgroundProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Content component.\n */\nexport interface ModalContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card component.\n */\nexport interface ModalCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Head component.\n */\nexport interface ModalCardHeadProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Title component.\n */\nexport interface ModalCardTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Body component.\n */\nexport interface ModalCardBodyProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Foot component.\n */\nexport interface ModalCardFootProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Close component.\n * @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a close button inside a form does not submit it. Pass `'submit'` or `'reset'` and yours is used; any other value, or a spread carrying `type: undefined`, renders `'button'`.\n * @extraProp {string} [aria-label='close'] - Accessible name. Pass your own to replace it. An empty one, or a spread carrying `'aria-label': undefined`, keeps the default rather than leaving the button unnamed.\n */\nexport interface ModalCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Additional CSS classes. */\n className?: string;\n /** Size of the close button (only applies to 'floating' variant). */\n size?: 'small' | 'medium' | 'large';\n /** Button variant. 'delete' (default) for modal card headers, 'floating' for overlay close button. */\n variant?: 'delete' | 'floating';\n}\n\n/**\n * Modal.Background - Renders the modal background overlay.\n *\n * @function\n * @param {ModalBackgroundProps} props - Component props.\n * @returns {JSX.Element} Modal background element.\n */\nconst ModalBackground: React.FC<ModalBackgroundProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-background'),\n className\n );\n return <div className={classes} {...props} />;\n};\n\n/**\n * Modal.Content - Renders modal content wrapper for custom content.\n *\n * @function\n * @param {ModalContentProps} props - Component props.\n * @returns {JSX.Element} Modal content element.\n */\nconst ModalContent: React.FC<ModalContentProps> = ({ className, ...props }) => {\n const classes = classNames(usePrefixedClassNames('modal-content'), className);\n return <div className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Head - Renders modal card header section.\n *\n * @function\n * @param {ModalCardHeadProps} props - Component props.\n * @returns {JSX.Element} Modal card header element.\n */\nconst ModalCardHead: React.FC<ModalCardHeadProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-head'),\n className\n );\n return <header className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Title - Renders modal card title.\n *\n * @function\n * @param {ModalCardTitleProps} props - Component props.\n * @returns {JSX.Element} Modal card title element.\n */\nconst ModalCardTitle: React.FC<ModalCardTitleProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-title'),\n className\n );\n return <p className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Body - Renders modal card body section.\n *\n * @function\n * @param {ModalCardBodyProps} props - Component props.\n * @returns {JSX.Element} Modal card body element.\n */\nconst ModalCardBody: React.FC<ModalCardBodyProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-body'),\n className\n );\n return <section className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Foot - Renders modal card footer section.\n *\n * @function\n * @param {ModalCardFootProps} props - Component props.\n * @returns {JSX.Element} Modal card footer element.\n */\nconst ModalCardFoot: React.FC<ModalCardFootProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-foot'),\n className\n );\n return <footer className={classes} {...props} />;\n};\n\n/**\n * Modal.Card - Renders modal card wrapper with compound components.\n * Use with Modal.Card.Head, Modal.Card.Title, Modal.Card.Body, and Modal.Card.Foot.\n *\n * @function\n * @param {ModalCardProps} props - Component props.\n * @returns {JSX.Element} Modal card element.\n */\nconst ModalCardComponent: React.FC<ModalCardProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(usePrefixedClassNames('modal-card'), className);\n return <div className={classes} {...props} />;\n};\n\nconst ModalCard = withSubComponents(ModalCardComponent, {\n Head: ModalCardHead,\n Title: ModalCardTitle,\n Body: ModalCardBody,\n Foot: ModalCardFoot,\n});\n\n/**\n * Modal.Close - Renders modal close button with two variant styles.\n *\n * @function\n * @param {ModalCloseProps} props - Component props.\n * @returns {JSX.Element} Close button element.\n *\n * @remarks\n * Supports two variants:\n * - 'delete' (default): For use in modal card headers, renders with 'delete' class\n * - 'floating': For floating overlay close button, renders with 'modal-close' class\n *\n * The size prop only applies to the 'floating' variant.\n */\nconst ModalClose: React.FC<ModalCloseProps> = ({\n className,\n size = 'large',\n variant = 'delete',\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames(\n variant === 'delete' ? 'delete' : 'modal-close',\n variant === 'floating' && size && { [`is-${size}`]: true }\n ),\n className\n );\n return (\n <button\n className={classes}\n {...props}\n // After the spread, reading through it: a key the spread carries with no\n // value would otherwise erase the default, leaving a nameless button\n // that submits the form around it. An empty label falls back too: the\n // button is drawn as an icon, so `''` would leave it unnamed. A caller's\n // own value still wins; `buttonType` says more.\n aria-label={props['aria-label'] || 'close'}\n type={buttonType(props.type)}\n />\n );\n};\n\n/**\n * The `Modal` component provides an empty, accessible overlay for arbitrary content — for a ready-made confirm or alert, reach for `Dialog` instead.\n *\n * @function\n * @param {ModalProps} props - Props for the Modal component.\n * @returns {JSX.Element} The rendered modal.\n *\n * @example\n * // Legacy API\n * <Modal active={isOpen} onClose={handleClose} modalCardTitle=\"Title\">\n * Content\n * </Modal>\n *\n * @example\n * // Compound Component API\n * <Modal isActive={isOpen}>\n * <Modal.Background onClick={handleClose} />\n * <Modal.Card>\n * <Modal.Card.Head>\n * <Modal.Card.Title>Title</Modal.Card.Title>\n * <Modal.Close onClick={handleClose} />\n * </Modal.Card.Head>\n * <Modal.Card.Body>Content</Modal.Card.Body>\n * </Modal.Card>\n * </Modal>\n *\n * @see {@link https://bulma.io/documentation/components/modal/ | Bulma Modal documentation}\n */\nconst ModalRoot = forwardRef<HTMLDivElement, ModalProps>(function ModalRoot(\n {\n active,\n isActive,\n onClose,\n className,\n textColor,\n bgColor,\n modalCardTitle,\n modalCardFoot,\n type,\n children,\n closeOnEscape = true,\n lockScroll = true,\n portal = false,\n role,\n 'aria-modal': ariaModalProp,\n ...props\n },\n ref\n) {\n const { classPrefix, portalContainer } = useConfig();\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n // Support both active and isActive props\n const isModalActive = active ?? isActive ?? false;\n\n const modalRootRef = useRef<HTMLDivElement>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n\n // The forwarded ref and the internal one must both see the node: focus\n // management and the Tab trap read `modalRootRef`, while consumers expect\n // their own ref to resolve.\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n (modalRootRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches\n // by running it instead of calling the ref with `null`; React 18\n // discards the return value entirely. Returning it from here would be\n // a React-19-only contract, so instead we hold the cleanup and run it\n // ourselves on detach — a consumer's cleanup ref then behaves the same\n // on both majors of the CI matrix. Same shape as `Dropdown`.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n const previouslyFocusedRef = useRef<HTMLElement | null>(null);\n const generatedTitleId = useId();\n // A portal has no server-rendered counterpart, so the server render and the\n // hydrating render have to stay inline and only move into the portal once\n // we're past hydration.\n const onClient = useIsHydrated();\n const resolveContainer = usePortalContainer();\n // Moving into the portal, or from one portal target to another, remounts\n // the modal's subtree, so any effect holding a DOM node from before the move\n // is holding a detached one. Effects that touch the modal's nodes key on\n // this, on `portal` and on `defaultTarget`, so they re-run against the new\n // tree.\n const isPortaled = Boolean(portal) && onClient;\n // The configured `portalContainer` only places a modal portaled with\n // `portal` set to `true`. In place, or with a target of its own, a change\n // to it moves nothing, so it mustn't re-run the effects either.\n const defaultTarget =\n isPortaled && portal === true ? portalContainer : undefined;\n\n useScrollLock(isModalActive && lockScroll);\n\n // Read when Escape arrives, so the key listener stays put while `onClose`\n // changes identity, as an inline one does on every render of the parent.\n const onCloseRef = useLatestRef(onClose);\n\n // Joins the stack of open overlays, so the keyboard handling below only\n // applies while this modal is on top.\n const isTopmost = useOverlayStack(isModalActive);\n\n // Escape closes, only for the topmost overlay. The listener is on\n // `window`, where a keydown arrives last, so everything inside the modal\n // has had the key first: React's handlers, and `document` listeners added\n // after this one, such as a date picker's.\n useEffect(() => {\n if (!isModalActive) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || !isTopmost()) return;\n // Something inside already used this Escape, such as a popup that\n // closed on it, so the modal waits for the next one. One the modal\n // closes on is marked used, so nothing under it acts on it as well.\n if (closeOnEscape && onCloseRef.current && !e.defaultPrevented) {\n e.preventDefault();\n onCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isModalActive, closeOnEscape, onCloseRef, isTopmost]);\n\n // Keep Tab within the modal: `aria-modal` hides the rest of the page from\n // assistive technology, so the keyboard order has to agree. Only while\n // it's the topmost modal overlay, so an overlay that isn't modal, such as\n // a Sidebar without an overlay, takes Escape from it but leaves it Tab.\n // It's the trap `useFocusTrap` sets, so it wraps at the stops Tab really\n // visits, skipping hidden, inert and closed content, and sends back a Tab\n // the browser still takes out. On `window` for the same reason as Escape:\n // a trap inside, such as a portaled popup's, has had the Tab first, and\n // one it used is left where it put focus. It reads the modal's node as\n // each key arrives, so a portal move that remounts the node, including one\n // to a selector that only starts matching while the modal is open, keeps\n // it trapped.\n useEffect(() => {\n if (!isModalActive) return undefined;\n return trapTab(\n () => modalRootRef.current,\n window,\n () => isTopmost('modal')\n );\n }, [isModalActive, isTopmost]);\n\n // Move focus into the modal on open, restore it on close\n useEffect(() => {\n if (!isModalActive) return undefined;\n\n // The element that had focus, wherever it sits: a portaled modal renders\n // under `document.body` while its opener can be inside a shadow root.\n previouslyFocusedRef.current =\n getDeepestActiveElement() as HTMLElement | null;\n const node = modalRootRef.current;\n const focusable = node ? firstTabStop(node) : null;\n (focusable ?? node)?.focus();\n\n return () => {\n // Only hand focus back if this modal still owns it: closing a background\n // modal must not pull focus out of one that is still open on top. A\n // removed subtree leaves focus on <body>, which still counts as ours.\n const activeElement = getActiveElementInTree(node);\n if (\n activeElement &&\n activeElement !== document.body &&\n !node?.contains(activeElement)\n ) {\n return;\n }\n previouslyFocusedRef.current?.focus?.();\n };\n // `isPortaled` flips once when a hydrated portal modal moves out of the\n // inline tree, and `portal` or `defaultTarget` changing moves a portaled\n // one to another target; re-running rebinds focus onto the remounted\n // nodes. The cleanup above restores focus to the pre-open element first\n // (the detached subtree has left focus on <body>), so the re-run re-records\n // the same element and restore-on-close still lands in the right place.\n }, [isModalActive, isPortaled, portal, defaultTarget]);\n\n // Check if children contain compound components\n const hasCompoundComponents = React.Children.toArray(children).some(\n child =>\n React.isValidElement(child) &&\n (child.type === ModalBackground ||\n child.type === ModalContent ||\n child.type === ModalCard ||\n child.type === ModalClose)\n );\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('modal', {\n 'is-active': isModalActive,\n });\n const deleteClass = usePrefixedClassNames('delete');\n\n const modalClasses = classNames(bulmaClasses, bulmaHelperClasses, className);\n\n const resolvedRole = role ?? (isModalActive ? 'dialog' : undefined);\n const resolvedAriaModal =\n ariaModalProp ??\n (isModalActive && resolvedRole !== 'presentation' ? 'true' : undefined);\n // A dialog needs an accessible name: the legacy card title is wired up\n // automatically, compound users pass their own aria-label/aria-labelledby\n // (both arrive in `rest`, which is spread last and so wins).\n const titleId = modalCardTitle ? generatedTitleId : undefined;\n\n let modalElement: React.ReactElement;\n\n // If using compound components, render children as-is\n if (hasCompoundComponents) {\n modalElement = (\n <div\n className={modalClasses}\n ref={combinedRef}\n role={resolvedRole}\n aria-modal={resolvedAriaModal}\n tabIndex={-1}\n {...rest}\n data-testid=\"modal\"\n >\n {children}\n </div>\n );\n } else {\n // Legacy API: EXPLICIT type wins; fallback to auto detection if not provided\n let isModalCard: boolean;\n if (type === 'card') isModalCard = true;\n else if (type === 'content') isModalCard = false;\n else isModalCard = !!modalCardTitle || !!modalCardFoot;\n\n modalElement = (\n <div\n className={modalClasses}\n ref={combinedRef}\n role={resolvedRole}\n aria-modal={resolvedAriaModal}\n aria-labelledby={titleId}\n tabIndex={-1}\n {...rest}\n data-testid=\"modal\"\n >\n <div\n className={prefixedClassNames(classPrefix, 'modal-background')}\n onClick={onClose}\n data-testid=\"modal-background\"\n />\n {isModalCard ? (\n <div className={prefixedClassNames(classPrefix, 'modal-card')}>\n {modalCardTitle && (\n <header\n className={prefixedClassNames(classPrefix, 'modal-card-head')}\n >\n <p\n id={titleId}\n className={prefixedClassNames(\n classPrefix,\n 'modal-card-title'\n )}\n >\n {modalCardTitle}\n </p>\n {onClose && (\n <button\n className={deleteClass}\n aria-label=\"close\"\n onClick={onClose}\n type=\"button\"\n data-testid=\"modal-close\"\n />\n )}\n </header>\n )}\n <section\n className={prefixedClassNames(classPrefix, 'modal-card-body')}\n data-testid=\"modal-body\"\n >\n {children}\n </section>\n {modalCardFoot && (\n <footer\n className={prefixedClassNames(classPrefix, 'modal-card-foot')}\n >\n {modalCardFoot}\n </footer>\n )}\n </div>\n ) : (\n <div\n className={prefixedClassNames(classPrefix, 'modal-content')}\n data-testid=\"modal-content\"\n >\n {children}\n </div>\n )}\n {/* Show floating close button for modal-content, or for modal-card when no header */}\n {(!isModalCard || (!modalCardTitle && onClose)) && onClose && (\n <button\n className={prefixedClassNames(\n classPrefix,\n 'modal-close',\n 'is-large'\n )}\n aria-label=\"close\"\n onClick={onClose}\n type=\"button\"\n data-testid=\"modal-close-float\"\n />\n )}\n </div>\n );\n }\n\n if (isPortaled) {\n const target = resolveContainer(\n typeof portal === 'boolean' ? undefined : portal\n );\n return createPortal(modalElement, target);\n }\n\n return modalElement;\n});\n\nexport const Modal = withSubComponents(\n ModalRoot,\n {\n Background: ModalBackground,\n Content: ModalContent,\n Card: ModalCard,\n Close: ModalClose,\n },\n 'Modal'\n);\nexport default Modal;\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;;;;;;;;;AAqKA;;;;;;AAMG;AACH,MAAM,eAAe,GAAmC,CAAC,EACvD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CAAC,kBAAkB,CAAC,EACzC,SAAS,CACV;AACD,IAAA,OAAOA,aAAK,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAC/C,CAAC;AAED;;;;;;AAMG;AACH,MAAM,YAAY,GAAgC,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,KAAI;IAC5E,MAAM,OAAO,GAAG,UAAU,CAAC,qBAAqB,CAAC,eAAe,CAAC,EAAE,SAAS,CAAC;AAC7E,IAAA,OAAOA,aAAK,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAC/C,CAAC;AAED;;;;;;AAMG;AACH,MAAM,aAAa,GAAiC,CAAC,EACnD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CAAC,iBAAiB,CAAC,EACxC,SAAS,CACV;AACD,IAAA,OAAOA,gBAAQ,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAClD,CAAC;AAED;;;;;;AAMG;AACH,MAAM,cAAc,GAAkC,CAAC,EACrD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CAAC,kBAAkB,CAAC,EACzC,SAAS,CACV;AACD,IAAA,OAAOA,WAAG,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAC7C,CAAC;AAED;;;;;;AAMG;AACH,MAAM,aAAa,GAAiC,CAAC,EACnD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CAAC,iBAAiB,CAAC,EACxC,SAAS,CACV;AACD,IAAA,OAAOA,iBAAS,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AACnD,CAAC;AAED;;;;;;AAMG;AACH,MAAM,aAAa,GAAiC,CAAC,EACnD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CAAC,iBAAiB,CAAC,EACxC,SAAS,CACV;AACD,IAAA,OAAOA,gBAAQ,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAClD,CAAC;AAED;;;;;;;AAOG;AACH,MAAM,kBAAkB,GAA6B,CAAC,EACpD,SAAS,EACT,GAAG,KAAK,EACT,KAAI;IACH,MAAM,OAAO,GAAG,UAAU,CAAC,qBAAqB,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC;AAC1E,IAAA,OAAOA,aAAK,SAAS,EAAE,OAAO,EAAA,GAAM,KAAK,GAAI;AAC/C,CAAC;AAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,kBAAkB,EAAE;AACtD,IAAA,IAAI,EAAE,aAAa;AACnB,IAAA,KAAK,EAAE,cAAc;AACrB,IAAA,IAAI,EAAE,aAAa;AACnB,IAAA,IAAI,EAAE,aAAa;AACpB,CAAA,CAAC;AAEF;;;;;;;;;;;;;AAaG;AACH,MAAM,UAAU,GAA8B,CAAC,EAC7C,SAAS,EACT,IAAI,GAAG,OAAO,EACd,OAAO,GAAG,QAAQ,EAClB,GAAG,KAAK,EACT,KAAI;AACH,IAAA,MAAM,OAAO,GAAG,UAAU,CACxB,qBAAqB,CACnB,OAAO,KAAK,QAAQ,GAAG,QAAQ,GAAG,aAAa,EAC/C,OAAO,KAAK,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,CAAA,GAAA,EAAM,IAAI,CAAA,CAAE,GAAG,IAAI,EAAE,CAC3D,EACD,SAAS,CACV;IACD,QACEA,GAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAE,OAAO,KACd,KAAK,EAAA,YAAA,EAMG,KAAK,CAAC,YAAY,CAAC,IAAI,OAAO,EAC1C,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAA,CAC5B;AAEN,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACH,MAAM,SAAS,GAAG,UAAU,CAA6B,SAAS,SAAS,CACzE,EACE,MAAM,EACN,QAAQ,EACR,OAAO,EACP,SAAS,EACT,SAAS,EACT,OAAO,EACP,cAAc,EACd,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,aAAa,GAAG,IAAI,EACpB,UAAU,GAAG,IAAI,EACjB,MAAM,GAAG,KAAK,EACd,IAAI,EACJ,YAAY,EAAE,aAAa,EAC3B,GAAG,KAAK,EACT,EACD,GAAG,EAAA;IAEH,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE;AACpD,IAAA,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,eAAe,CAAC;AACnD,QAAA,KAAK,EAAE,SAAS;AAChB,QAAA,eAAe,EAAE,OAAO;AACxB,QAAA,GAAG,KAAK;AACT,KAAA,CAAC;;AAGF,IAAA,MAAM,aAAa,GAAG,MAAM,IAAI,QAAQ,IAAI,KAAK;AAEjD,IAAA,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC;;AAGjD,IAAA,MAAM,kBAAkB,GAAG,MAAM,CAAsB,IAAI,CAAC;;;;AAK5D,IAAA,MAAM,WAAW,GAAG,WAAW,CAC7B,CAAC,IAA2B,KAAI;AAC7B,QAAA,YAA8D,CAAC,OAAO;AACrE,YAAA,IAAI;AACN,QAAA,IAAI,OAAO,GAAG,KAAK,UAAU,EAAE;;;;;;;AAO7B,YAAA,IAAI,IAAI,KAAK,IAAI,EAAE;AACjB,gBAAA,MAAM,eAAe,GAAG,kBAAkB,CAAC,OAAO;AAClD,gBAAA,kBAAkB,CAAC,OAAO,GAAG,IAAI;gBACjC,IAAI,eAAe,EAAE;AACnB,oBAAA,eAAe,EAAE;gBACnB;qBAAO;oBACL,GAAG,CAAC,IAAI,CAAC;gBACX;gBACA;YACF;AACA,YAAA,MAAM,OAAO,GAAY,GAAG,CAAC,IAAI,CAAC;AAClC,YAAA,kBAAkB,CAAC,OAAO;gBACxB,OAAO,OAAO,KAAK,UAAU,GAAI,OAAsB,GAAG,IAAI;QAClE;aAAO,IAAI,GAAG,EAAE;AACb,YAAA,GAAqD,CAAC,OAAO,GAAG,IAAI;QACvE;AACF,IAAA,CAAC,EACD,CAAC,GAAG,CAAC,CACN;AACD,IAAA,MAAM,oBAAoB,GAAG,MAAM,CAAqB,IAAI,CAAC;AAC7D,IAAA,MAAM,gBAAgB,GAAG,KAAK,EAAE;;;;AAIhC,IAAA,MAAM,QAAQ,GAAG,aAAa,EAAE;AAChC,IAAA,MAAM,gBAAgB,GAAG,kBAAkB,EAAE;;;;;;IAM7C,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,QAAQ;;;;AAI9C,IAAA,MAAM,aAAa,GACjB,UAAU,IAAI,MAAM,KAAK,IAAI,GAAG,eAAe,GAAG,SAAS;AAE7D,IAAA,aAAa,CAAC,aAAa,IAAI,UAAU,CAAC;;;AAI1C,IAAA,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;;;AAIxC,IAAA,MAAM,SAAS,GAAG,eAAe,CAAC,aAAa,CAAC;;;;;IAMhD,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,SAAS;AAEpC,QAAA,MAAM,aAAa,GAAG,CAAC,CAAgB,KAAI;YACzC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,SAAS,EAAE;gBAAE;;;;YAIxC,IAAI,aAAa,IAAI,UAAU,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,gBAAgB,EAAE;gBAC9D,CAAC,CAAC,cAAc,EAAE;gBAClB,UAAU,CAAC,OAAO,EAAE;YACtB;AACF,QAAA,CAAC;AAED,QAAA,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC;QACjD,OAAO,MAAM,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC;IACnE,CAAC,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;;;;;;;;;;;;;IAczD,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,SAAS;AACpC,QAAA,OAAO,OAAO,CACZ,MAAM,YAAY,CAAC,OAAO,EAC1B,MAAM,EACN,MAAM,SAAS,CAAC,OAAO,CAAC,CACzB;AACH,IAAA,CAAC,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;;IAG9B,SAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,aAAa;AAAE,YAAA,OAAO,SAAS;;;AAIpC,QAAA,oBAAoB,CAAC,OAAO;AAC1B,YAAA,uBAAuB,EAAwB;AACjD,QAAA,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO;AACjC,QAAA,MAAM,SAAS,GAAG,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI;AAClD,QAAA,CAAC,SAAS,IAAI,IAAI,GAAG,KAAK,EAAE;AAE5B,QAAA,OAAO,MAAK;;;;AAIV,YAAA,MAAM,aAAa,GAAG,sBAAsB,CAAC,IAAI,CAAC;AAClD,YAAA,IACE,aAAa;gBACb,aAAa,KAAK,QAAQ,CAAC,IAAI;AAC/B,gBAAA,CAAC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC9B;gBACA;YACF;AACA,YAAA,oBAAoB,CAAC,OAAO,EAAE,KAAK,IAAI;AACzC,QAAA,CAAC;;;;;;;IAOH,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;;IAGtD,MAAM,qBAAqB,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CACjE,KAAK,IACH,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC;AAC3B,SAAC,KAAK,CAAC,IAAI,KAAK,eAAe;YAC7B,KAAK,CAAC,IAAI,KAAK,YAAY;YAC3B,KAAK,CAAC,IAAI,KAAK,SAAS;AACxB,YAAA,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAC/B;;AAGD,IAAA,MAAM,YAAY,GAAG,qBAAqB,CAAC,OAAO,EAAE;AAClD,QAAA,WAAW,EAAE,aAAa;AAC3B,KAAA,CAAC;AACF,IAAA,MAAM,WAAW,GAAG,qBAAqB,CAAC,QAAQ,CAAC;IAEnD,MAAM,YAAY,GAAG,UAAU,CAAC,YAAY,EAAE,kBAAkB,EAAE,SAAS,CAAC;AAE5E,IAAA,MAAM,YAAY,GAAG,IAAI,KAAK,aAAa,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnE,MAAM,iBAAiB,GACrB,aAAa;AACb,SAAC,aAAa,IAAI,YAAY,KAAK,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;;;;IAIzE,MAAM,OAAO,GAAG,cAAc,GAAG,gBAAgB,GAAG,SAAS;AAE7D,IAAA,IAAI,YAAgC;;IAGpC,IAAI,qBAAqB,EAAE;AACzB,QAAA,YAAY,IACVA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,YAAY,EAAA,YAAA,EACN,iBAAiB,EAC7B,QAAQ,EAAE,EAAE,EAAA,GACR,IAAI,EAAA,aAAA,EACI,OAAO,EAAA,QAAA,EAElB,QAAQ,EAAA,CACL,CACP;IACH;SAAO;;AAEL,QAAA,IAAI,WAAoB;QACxB,IAAI,IAAI,KAAK,MAAM;YAAE,WAAW,GAAG,IAAI;aAClC,IAAI,IAAI,KAAK,SAAS;YAAE,WAAW,GAAG,KAAK;;YAC3C,WAAW,GAAG,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,aAAa;QAEtD,YAAY,IACVC,IAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,YAAY,EACvB,GAAG,EAAE,WAAW,EAChB,IAAI,EAAE,YAAY,gBACN,iBAAiB,EAAA,iBAAA,EACZ,OAAO,EACxB,QAAQ,EAAE,EAAE,EAAA,GACR,IAAI,EAAA,aAAA,EACI,OAAO,aAEnBD,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,kBAAkB,CAAC,EAC9D,OAAO,EAAE,OAAO,EAAA,aAAA,EACJ,kBAAkB,EAAA,CAC9B,EACD,WAAW,IACVC,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,YAAY,CAAC,EAAA,QAAA,EAAA,CAC1D,cAAc,KACbA,IAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAA,QAAA,EAAA,CAE7DD,GAAA,CAAA,GAAA,EAAA,EACE,EAAE,EAAE,OAAO,EACX,SAAS,EAAE,kBAAkB,CAC3B,WAAW,EACX,kBAAkB,CACnB,EAAA,QAAA,EAEA,cAAc,EAAA,CACb,EACH,OAAO,KACNA,GAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAE,WAAW,gBACX,OAAO,EAClB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAC,QAAQ,iBACD,aAAa,EAAA,CACzB,CACH,CAAA,EAAA,CACM,CACV,EACDA,GAAA,CAAA,SAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,iBAAiB,CAAC,iBACjD,YAAY,EAAA,QAAA,EAEvB,QAAQ,EAAA,CACD,EACT,aAAa,KACZA,GAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAA,QAAA,EAE5D,aAAa,GACP,CACV,CAAA,EAAA,CACG,KAENA,GAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAAC,WAAW,EAAE,eAAe,CAAC,iBAC/C,eAAe,EAAA,QAAA,EAE1B,QAAQ,EAAA,CACL,CACP,EAEA,CAAC,CAAC,WAAW,KAAK,CAAC,cAAc,IAAI,OAAO,CAAC,KAAK,OAAO,KACxDA,GAAA,CAAA,QAAA,EAAA,EACE,SAAS,EAAE,kBAAkB,CAC3B,WAAW,EACX,aAAa,EACb,UAAU,CACX,EAAA,YAAA,EACU,OAAO,EAClB,OAAO,EAAE,OAAO,EAChB,IAAI,EAAC,QAAQ,EAAA,aAAA,EACD,mBAAmB,EAAA,CAC/B,CACH,CAAA,EAAA,CACG,CACP;IACH;IAEA,IAAI,UAAU,EAAE;AACd,QAAA,MAAM,MAAM,GAAG,gBAAgB,CAC7B,OAAO,MAAM,KAAK,SAAS,GAAG,SAAS,GAAG,MAAM,CACjD;AACD,QAAA,OAAO,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC;IAC3C;AAEA,IAAA,OAAO,YAAY;AACrB,CAAC,CAAC;AAEK,MAAM,KAAK,GAAG,iBAAiB,CACpC,SAAS,EACT;AACE,IAAA,UAAU,EAAE,eAAe;AAC3B,IAAA,OAAO,EAAE,YAAY;AACrB,IAAA,IAAI,EAAE,SAAS;AACf,IAAA,KAAK,EAAE,UAAU;CAClB,EACD,OAAO;;"}
1
+ {"version":3,"file":"Modal.js","sources":["../../../src/components/Modal.tsx"],"sourcesContent":["import React, {\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n classNames,\n usePrefixedClassNames,\n prefixedClassNames,\n} from '../helpers/classNames';\nimport { withSubComponents } from '../helpers/withSubComponents';\nimport { buttonType } from '../helpers/buttonType';\nimport {\n useBulmaClasses,\n BulmaClassesProps,\n validColors,\n} from '../helpers/useBulmaClasses';\nimport { useConfig } from '../helpers/Config';\nimport { useScrollLock } from '../helpers/scrollLock';\nimport {\n getActiveElementInTree,\n getDeepestActiveElement,\n} from '../helpers/shadowDom';\nimport { usePortalContainer } from '../helpers/portal';\nimport { useIsHydrated } from '../helpers/useIsHydrated';\nimport { useLatestRef } from '../helpers/useLatestRef';\nimport { useOverlayStack } from '../helpers/overlayStack';\nimport { focusTabStop, trapTab } from '../helpers/useFocusTrap';\n\n/**\n * Props for the Modal component.\n * @extraProp {React.Ref<HTMLDivElement>} [ref] - Ref forwarded to the root `.modal` element.\n */\nexport interface ModalProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'title'>,\n Omit<BulmaClassesProps, 'color' | 'backgroundColor'> {\n /** Whether the modal is open/visible. */\n active?: boolean;\n /** Alias for `active`. Whether the modal is open/visible. */\n isActive?: boolean; // Alias for active\n /** Callback invoked to request modal close (background or close button). */\n onClose?: () => void;\n /** Additional CSS classes for the modal. */\n className?: string;\n /** Text color for modal content. */\n textColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Background color for modal content. */\n bgColor?: (typeof validColors)[number] | 'inherit' | 'current';\n /** Title/header for modal-card variant. (Legacy API only) */\n modalCardTitle?: React.ReactNode;\n /** Footer for modal-card variant. (Legacy API only) */\n modalCardFoot?: React.ReactNode;\n /**\n * Modal style: `'card'` for modal-card, `'content'` for modal-content. (Legacy API only)\n * @defaultValue auto\n */\n type?: 'card' | 'content';\n /** Modal body/content or compound components. */\n children?: React.ReactNode;\n /**\n * Close the modal when the Escape key is pressed (calls `onClose`). Only the\n * topmost open overlay responds, whichever Modal, Dialog, Sidebar or\n * full-page Loading opened last, so Escape closes one layer at a time. The\n * modal marks the Escape it closes on as used with `preventDefault()`, and\n * a Toast waits until no overlay is open. Turned off, a modal on top still\n * keeps Escape from the layers under it. A popup inside it, such as a\n * Dropdown's menu or a date picker's calendar, takes its own Escape first,\n * and so does content that calls `preventDefault()` on it.\n * @defaultValue true\n */\n closeOnEscape?: boolean;\n /**\n * Lock body scroll while the modal is active. Ref-counted and shared with\n * `Dialog`, `Sidebar` and `Loading`, so whichever overlay closes first does\n * not unlock the page underneath one that is still open.\n * @defaultValue true\n */\n lockScroll?: boolean;\n /**\n * Renders the modal into a portal target instead of inline, so it isn't\n * clipped by an ancestor with `overflow: hidden`, `filter` or `transform`.\n * `true` portals to the `portalContainer` a `ConfigProvider` sets,\n * `document.body` by default; a string is used as a\n * `document.querySelector` selector; an element is used directly. Renders\n * inline on the server and while hydrating, moving into the portal once the\n * client takes over, so hydration matches.\n * @defaultValue false\n */\n portal?: boolean | string | HTMLElement;\n}\n\n/**\n * Props for Modal.Background component.\n */\nexport interface ModalBackgroundProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Content component.\n */\nexport interface ModalContentProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card component.\n */\nexport interface ModalCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Head component.\n */\nexport interface ModalCardHeadProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Title component.\n */\nexport interface ModalCardTitleProps extends React.HTMLAttributes<HTMLParagraphElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Body component.\n */\nexport interface ModalCardBodyProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Card.Foot component.\n */\nexport interface ModalCardFootProps extends React.HTMLAttributes<HTMLElement> {\n /** Additional CSS classes. */\n className?: string;\n}\n\n/**\n * Props for Modal.Close component.\n * @extraProp {'button' | 'submit' | 'reset'} [type='button'] - Button type. Defaults to `'button'`, so a close button inside a form does not submit it. Pass `'submit'` or `'reset'` and yours is used; any other value, or a spread carrying `type: undefined`, renders `'button'`.\n * @extraProp {string} [aria-label='close'] - Accessible name. Pass your own to replace it. An empty one, or a spread carrying `'aria-label': undefined`, keeps the default rather than leaving the button unnamed.\n */\nexport interface ModalCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Additional CSS classes. */\n className?: string;\n /** Size of the close button (only applies to 'floating' variant). */\n size?: 'small' | 'medium' | 'large';\n /** Button variant. 'delete' (default) for modal card headers, 'floating' for overlay close button. */\n variant?: 'delete' | 'floating';\n}\n\n/**\n * Modal.Background - Renders the modal background overlay.\n *\n * @function\n * @param {ModalBackgroundProps} props - Component props.\n * @returns {JSX.Element} Modal background element.\n */\nconst ModalBackground: React.FC<ModalBackgroundProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-background'),\n className\n );\n return <div className={classes} {...props} />;\n};\n\n/**\n * Modal.Content - Renders modal content wrapper for custom content.\n *\n * @function\n * @param {ModalContentProps} props - Component props.\n * @returns {JSX.Element} Modal content element.\n */\nconst ModalContent: React.FC<ModalContentProps> = ({ className, ...props }) => {\n const classes = classNames(usePrefixedClassNames('modal-content'), className);\n return <div className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Head - Renders modal card header section.\n *\n * @function\n * @param {ModalCardHeadProps} props - Component props.\n * @returns {JSX.Element} Modal card header element.\n */\nconst ModalCardHead: React.FC<ModalCardHeadProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-head'),\n className\n );\n return <header className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Title - Renders modal card title.\n *\n * @function\n * @param {ModalCardTitleProps} props - Component props.\n * @returns {JSX.Element} Modal card title element.\n */\nconst ModalCardTitle: React.FC<ModalCardTitleProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-title'),\n className\n );\n return <p className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Body - Renders modal card body section.\n *\n * @function\n * @param {ModalCardBodyProps} props - Component props.\n * @returns {JSX.Element} Modal card body element.\n */\nconst ModalCardBody: React.FC<ModalCardBodyProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-body'),\n className\n );\n return <section className={classes} {...props} />;\n};\n\n/**\n * Modal.Card.Foot - Renders modal card footer section.\n *\n * @function\n * @param {ModalCardFootProps} props - Component props.\n * @returns {JSX.Element} Modal card footer element.\n */\nconst ModalCardFoot: React.FC<ModalCardFootProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames('modal-card-foot'),\n className\n );\n return <footer className={classes} {...props} />;\n};\n\n/**\n * Modal.Card - Renders modal card wrapper with compound components.\n * Use with Modal.Card.Head, Modal.Card.Title, Modal.Card.Body, and Modal.Card.Foot.\n *\n * @function\n * @param {ModalCardProps} props - Component props.\n * @returns {JSX.Element} Modal card element.\n */\nconst ModalCardComponent: React.FC<ModalCardProps> = ({\n className,\n ...props\n}) => {\n const classes = classNames(usePrefixedClassNames('modal-card'), className);\n return <div className={classes} {...props} />;\n};\n\nconst ModalCard = withSubComponents(ModalCardComponent, {\n Head: ModalCardHead,\n Title: ModalCardTitle,\n Body: ModalCardBody,\n Foot: ModalCardFoot,\n});\n\n/**\n * Modal.Close - Renders modal close button with two variant styles.\n *\n * @function\n * @param {ModalCloseProps} props - Component props.\n * @returns {JSX.Element} Close button element.\n *\n * @remarks\n * Supports two variants:\n * - 'delete' (default): For use in modal card headers, renders with 'delete' class\n * - 'floating': For floating overlay close button, renders with 'modal-close' class\n *\n * The size prop only applies to the 'floating' variant.\n */\nconst ModalClose: React.FC<ModalCloseProps> = ({\n className,\n size = 'large',\n variant = 'delete',\n ...props\n}) => {\n const classes = classNames(\n usePrefixedClassNames(\n variant === 'delete' ? 'delete' : 'modal-close',\n variant === 'floating' && size && { [`is-${size}`]: true }\n ),\n className\n );\n return (\n <button\n className={classes}\n {...props}\n // After the spread, reading through it: a key the spread carries with no\n // value would otherwise erase the default, leaving a nameless button\n // that submits the form around it. An empty label falls back too: the\n // button is drawn as an icon, so `''` would leave it unnamed. A caller's\n // own value still wins; `buttonType` says more.\n aria-label={props['aria-label'] || 'close'}\n type={buttonType(props.type)}\n />\n );\n};\n\n/**\n * The `Modal` component provides an empty, accessible overlay for arbitrary content — for a ready-made confirm or alert, reach for `Dialog` instead.\n *\n * @function\n * @param {ModalProps} props - Props for the Modal component.\n * @returns {JSX.Element} The rendered modal.\n *\n * @example\n * // Legacy API\n * <Modal active={isOpen} onClose={handleClose} modalCardTitle=\"Title\">\n * Content\n * </Modal>\n *\n * @example\n * // Compound Component API\n * <Modal isActive={isOpen}>\n * <Modal.Background onClick={handleClose} />\n * <Modal.Card>\n * <Modal.Card.Head>\n * <Modal.Card.Title>Title</Modal.Card.Title>\n * <Modal.Close onClick={handleClose} />\n * </Modal.Card.Head>\n * <Modal.Card.Body>Content</Modal.Card.Body>\n * </Modal.Card>\n * </Modal>\n *\n * @see {@link https://bulma.io/documentation/components/modal/ | Bulma Modal documentation}\n */\nconst ModalRoot = forwardRef<HTMLDivElement, ModalProps>(function ModalRoot(\n {\n active,\n isActive,\n onClose,\n className,\n textColor,\n bgColor,\n modalCardTitle,\n modalCardFoot,\n type,\n children,\n closeOnEscape = true,\n lockScroll = true,\n portal = false,\n role,\n 'aria-modal': ariaModalProp,\n ...props\n },\n ref\n) {\n const { classPrefix, portalContainer } = useConfig();\n const { bulmaHelperClasses, rest } = useBulmaClasses({\n color: textColor,\n backgroundColor: bgColor,\n ...props,\n });\n\n // Support both active and isActive props\n const isModalActive = active ?? isActive ?? false;\n\n const modalRootRef = useRef<HTMLDivElement>(null);\n\n // Cleanup returned by a consumer's callback ref on attach, held until detach.\n const consumerCleanupRef = useRef<(() => void) | null>(null);\n\n // The forwarded ref and the internal one must both see the node: focus\n // management and the Tab trap read `modalRootRef`, while consumers expect\n // their own ref to resolve.\n const combinedRef = useCallback(\n (node: HTMLDivElement | null) => {\n (modalRootRef as React.MutableRefObject<HTMLDivElement | null>).current =\n node;\n if (typeof ref === 'function') {\n // React 19 lets a callback ref return a cleanup function and detaches\n // by running it instead of calling the ref with `null`; React 18\n // discards the return value entirely. Returning it from here would be\n // a React-19-only contract, so instead we hold the cleanup and run it\n // ourselves on detach — a consumer's cleanup ref then behaves the same\n // on both majors of the CI matrix. Same shape as `Dropdown`.\n if (node === null) {\n const consumerCleanup = consumerCleanupRef.current;\n consumerCleanupRef.current = null;\n if (consumerCleanup) {\n consumerCleanup();\n } else {\n ref(null);\n }\n return;\n }\n const cleanup: unknown = ref(node);\n consumerCleanupRef.current =\n typeof cleanup === 'function' ? (cleanup as () => void) : null;\n } else if (ref) {\n (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [ref]\n );\n const previouslyFocusedRef = useRef<HTMLElement | null>(null);\n const generatedTitleId = useId();\n // A portal has no server-rendered counterpart, so the server render and the\n // hydrating render have to stay inline and only move into the portal once\n // we're past hydration.\n const onClient = useIsHydrated();\n const resolveContainer = usePortalContainer();\n // Moving into the portal, or from one portal target to another, remounts\n // the modal's subtree, so any effect holding a DOM node from before the move\n // is holding a detached one. Effects that touch the modal's nodes key on\n // this, on `portal` and on `defaultTarget`, so they re-run against the new\n // tree.\n const isPortaled = Boolean(portal) && onClient;\n // The configured `portalContainer` only places a modal portaled with\n // `portal` set to `true`. In place, or with a target of its own, a change\n // to it moves nothing, so it mustn't re-run the effects either.\n const defaultTarget =\n isPortaled && portal === true ? portalContainer : undefined;\n\n useScrollLock(isModalActive && lockScroll);\n\n // Read when Escape arrives, so the key listener stays put while `onClose`\n // changes identity, as an inline one does on every render of the parent.\n const onCloseRef = useLatestRef(onClose);\n\n // Joins the stack of open overlays, so the keyboard handling below only\n // applies while this modal is on top.\n const isTopmost = useOverlayStack(isModalActive);\n\n // Escape closes, only for the topmost overlay. The listener is on\n // `window`, where a keydown arrives last, so everything inside the modal\n // has had the key first: React's handlers, and `document` listeners added\n // after this one, such as a date picker's.\n useEffect(() => {\n if (!isModalActive) return undefined;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape' || !isTopmost()) return;\n // Something inside already used this Escape, such as a popup that\n // closed on it, so the modal waits for the next one. One the modal\n // closes on is marked used, so nothing under it acts on it as well.\n if (closeOnEscape && onCloseRef.current && !e.defaultPrevented) {\n e.preventDefault();\n onCloseRef.current();\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, [isModalActive, closeOnEscape, onCloseRef, isTopmost]);\n\n // Keep Tab within the modal: `aria-modal` hides the rest of the page from\n // assistive technology, so the keyboard order has to agree. Only while\n // it's the topmost modal overlay, so an overlay that isn't modal, such as\n // a Sidebar without an overlay, takes Escape from it but leaves it Tab.\n // It's the trap `useFocusTrap` sets, so it wraps at the stops Tab really\n // visits, skipping hidden, inert and closed content, and sends back a Tab\n // the browser still takes out. On `window` for the same reason as Escape:\n // a trap inside, such as a portaled popup's, has had the Tab first, and\n // one it used is left where it put focus. It reads the modal's node as\n // each key arrives, so a portal move that remounts the node, including one\n // to a selector that only starts matching while the modal is open, keeps\n // it trapped.\n useEffect(() => {\n if (!isModalActive) return undefined;\n return trapTab(\n () => modalRootRef.current,\n window,\n () => isTopmost('modal')\n );\n }, [isModalActive, isTopmost]);\n\n // Move focus into the modal on open, restore it on close\n useEffect(() => {\n if (!isModalActive) return undefined;\n\n // The element that had focus, wherever it sits: a portaled modal renders\n // under `document.body` while its opener can be inside a shadow root.\n previouslyFocusedRef.current =\n getDeepestActiveElement() as HTMLElement | null;\n const node = modalRootRef.current;\n if (node) focusTabStop(node);\n\n return () => {\n // Only hand focus back if this modal still owns it: closing a background\n // modal must not pull focus out of one that is still open on top. A\n // removed subtree leaves focus on <body>, which still counts as ours.\n const activeElement = getActiveElementInTree(node);\n if (\n activeElement &&\n activeElement !== document.body &&\n !node?.contains(activeElement)\n ) {\n return;\n }\n previouslyFocusedRef.current?.focus?.();\n };\n // `isPortaled` flips once when a hydrated portal modal moves out of the\n // inline tree, and `portal` or `defaultTarget` changing moves a portaled\n // one to another target; re-running rebinds focus onto the remounted\n // nodes. The cleanup above restores focus to the pre-open element first\n // (the detached subtree has left focus on <body>), so the re-run re-records\n // the same element and restore-on-close still lands in the right place.\n }, [isModalActive, isPortaled, portal, defaultTarget]);\n\n // Check if children contain compound components\n const hasCompoundComponents = React.Children.toArray(children).some(\n child =>\n React.isValidElement(child) &&\n (child.type === ModalBackground ||\n child.type === ModalContent ||\n child.type === ModalCard ||\n child.type === ModalClose)\n );\n\n // Generate Bulma classes with prefix\n const bulmaClasses = usePrefixedClassNames('modal', {\n 'is-active': isModalActive,\n });\n const deleteClass = usePrefixedClassNames('delete');\n\n const modalClasses = classNames(bulmaClasses, bulmaHelperClasses, className);\n\n const resolvedRole = role ?? (isModalActive ? 'dialog' : undefined);\n const resolvedAriaModal =\n ariaModalProp ??\n (isModalActive && resolvedRole !== 'presentation' ? 'true' : undefined);\n // A dialog needs an accessible name: the legacy card title is wired up\n // automatically, compound users pass their own aria-label/aria-labelledby\n // (both arrive in `rest`, which is spread last and so wins).\n const titleId = modalCardTitle ? generatedTitleId : undefined;\n\n let modalElement: React.ReactElement;\n\n // If using compound components, render children as-is\n if (hasCompoundComponents) {\n modalElement = (\n <div\n className={modalClasses}\n ref={combinedRef}\n role={resolvedRole}\n aria-modal={resolvedAriaModal}\n tabIndex={-1}\n {...rest}\n data-testid=\"modal\"\n >\n {children}\n </div>\n );\n } else {\n // Legacy API: EXPLICIT type wins; fallback to auto detection if not provided\n let isModalCard: boolean;\n if (type === 'card') isModalCard = true;\n else if (type === 'content') isModalCard = false;\n else isModalCard = !!modalCardTitle || !!modalCardFoot;\n\n modalElement = (\n <div\n className={modalClasses}\n ref={combinedRef}\n role={resolvedRole}\n aria-modal={resolvedAriaModal}\n aria-labelledby={titleId}\n tabIndex={-1}\n {...rest}\n data-testid=\"modal\"\n >\n <div\n className={prefixedClassNames(classPrefix, 'modal-background')}\n onClick={onClose}\n data-testid=\"modal-background\"\n />\n {isModalCard ? (\n <div className={prefixedClassNames(classPrefix, 'modal-card')}>\n {modalCardTitle && (\n <header\n className={prefixedClassNames(classPrefix, 'modal-card-head')}\n >\n <p\n id={titleId}\n className={prefixedClassNames(\n classPrefix,\n 'modal-card-title'\n )}\n >\n {modalCardTitle}\n </p>\n {onClose && (\n <button\n className={deleteClass}\n aria-label=\"close\"\n onClick={onClose}\n type=\"button\"\n data-testid=\"modal-close\"\n />\n )}\n </header>\n )}\n <section\n className={prefixedClassNames(classPrefix, 'modal-card-body')}\n data-testid=\"modal-body\"\n >\n {children}\n </section>\n {modalCardFoot && (\n <footer\n className={prefixedClassNames(classPrefix, 'modal-card-foot')}\n >\n {modalCardFoot}\n </footer>\n )}\n </div>\n ) : (\n <div\n className={prefixedClassNames(classPrefix, 'modal-content')}\n data-testid=\"modal-content\"\n >\n {children}\n </div>\n )}\n {/* Show floating close button for modal-content, or for modal-card when no header */}\n {(!isModalCard || (!modalCardTitle && onClose)) && onClose && (\n <button\n className={prefixedClassNames(\n classPrefix,\n 'modal-close',\n 'is-large'\n )}\n aria-label=\"close\"\n onClick={onClose}\n type=\"button\"\n data-testid=\"modal-close-float\"\n />\n )}\n </div>\n );\n }\n\n if (isPortaled) {\n const target = resolveContainer(\n typeof portal === 'boolean' ? undefined : portal\n );\n return createPortal(modalElement, target);\n }\n\n return modalElement;\n});\n\nexport const Modal = withSubComponents(\n ModalRoot,\n {\n Background: ModalBackground,\n Content: ModalContent,\n Card: ModalCard,\n Close: ModalClose,\n },\n 'Modal'\n);\nexport default Modal;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}