{"version":3,"file":"AccordionPanelTrigger.cjs","sources":["../../../src/components/AccordionPanel/AccordionPanelTrigger.tsx"],"sourcesContent":["'use client'\n\nimport {\n  type ComponentPropsWithoutRef,\n  type FC,\n  type KeyboardEventHandler,\n  type MouseEvent,\n  type PropsWithChildren,\n  memo,\n  useCallback,\n  useContext,\n  useMemo,\n} from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { getIsInclude, mapToKeyArray } from '../../libs/map'\nimport { Heading, type HeadingTagTypes } from '../Heading'\nimport { FaCaretDownIcon, FaCaretRightIcon } from '../Icon'\nimport { Cluster } from '../Layout'\n\nimport { AccordionPanelContext } from './AccordionPanel'\nimport { AccordionPanelItemContext } from './AccordionPanelItem'\nimport {\n  focusFirstSibling,\n  focusLastSibling,\n  focusNextSibling,\n  focusPreviousSibling,\n  getNewExpandedItems,\n} from './accordionPanelHelper'\n\nimport type { TextProps } from '../Text'\n\ntype AbstractProps = PropsWithChildren<{\n  /** ヘッダ部分のテキストのスタイル */\n  headingType?: Exclude<TextProps['styleType'], 'screenTitle'>\n  /**\n   * 可能な限り利用せず、SectioningContent(Article, Aside, Nav, Section)を使ってHeadingと関連する範囲を明確に指定する方法を検討してください\n   */\n  unrecommendedHeadingTag?: HeadingTagTypes\n}>\ntype Props = AbstractProps & Omit<ComponentPropsWithoutRef<'button'>, keyof AbstractProps>\n\nconst classNameGenerator = tv({\n  slots: {\n    title: 'shr-grow shr-leading-tight',\n    titleWrapper: 'shr-flex-nowrap',\n    button: [\n      'smarthr-ui-AccordionPanel-trigger',\n      'shr-group shr-w-full shr-cursor-pointer shr-appearance-none shr-border-none shr-bg-transparent shr-px-1 shr-py-0.75 shr-text-left shr-text-inherit shr-text-color-inherit',\n      'disabled:shr-cursor-not-allowed disabled:shr-bg-white-darken disabled:shr-text-disabled',\n      'hover:shr-bg-white-darken',\n      'focus-visible:shr-focus-indicator',\n      // Base 直下に AccordionPanel がある場合、背景が付き抜けないように角丸を指定（Base に overflow: hidden を与えるとフォーカスリングが表示されなくなる）\n      '[.smarthr-ui-Base_>_.smarthr-ui-AccordionPanel_.smarthr-ui-AccordionPanel-item:first-child_&]:shr-rounded-t-l [.smarthr-ui-Base_>_.smarthr-ui-AccordionPanel_.smarthr-ui-AccordionPanel-item:last-child_&]:shr-rounded-b-l',\n    ],\n    leftIcon: 'shr-transition-transform shr-duration-100 group-aria-expanded:shr-rotate-90',\n    rightIcon: 'group-aria-expanded:-shr-rotate-180',\n  },\n  compoundSlots: [\n    {\n      slots: ['leftIcon', 'rightIcon'],\n      className: 'shr-shrink-0',\n    },\n  ],\n})\n\nexport const AccordionPanelTrigger: FC<Props> = ({\n  children,\n  className,\n  headingType = 'blockTitle',\n  unrecommendedHeadingTag,\n  ...rest\n}) => {\n  const classNames = useMemo(() => {\n    const { title, titleWrapper, button, leftIcon, rightIcon } = classNameGenerator()\n\n    return {\n      title: title(),\n      titleWrapper: titleWrapper(),\n      button: button({ className }),\n      leftIcon: leftIcon(),\n      rightIcon: rightIcon(),\n    }\n  }, [className])\n\n  const { name } = useContext(AccordionPanelItemContext)\n  const {\n    iconPosition,\n    expandedItems,\n    onClickTrigger,\n    onClickProps,\n    expandableMultiply,\n    parentRef,\n  } = useContext(AccordionPanelContext)\n\n  const isExpanded = useMemo(() => getIsInclude(expandedItems, name), [expandedItems, name])\n\n  const actualOnClickTrigger = useMemo(\n    () =>\n      onClickTrigger\n        ? (e: MouseEvent<HTMLButtonElement>) => onClickTrigger(e.currentTarget.value, !isExpanded)\n        : undefined,\n    [isExpanded, onClickTrigger],\n  )\n  const actualOnClickProps = useMemo(\n    () =>\n      onClickProps\n        ? (e: MouseEvent<HTMLButtonElement>) => {\n            const newExpandedItems = getNewExpandedItems(\n              expandedItems,\n              e.currentTarget.value,\n              !isExpanded,\n              expandableMultiply,\n            )\n            onClickProps(mapToKeyArray(newExpandedItems))\n          }\n        : undefined,\n    [isExpanded, expandedItems, expandableMultiply, onClickProps],\n  )\n  const handleClick = useMemo(() => {\n    if (actualOnClickTrigger) {\n      if (actualOnClickProps) {\n        return (e: MouseEvent<HTMLButtonElement>) => {\n          actualOnClickTrigger(e)\n          actualOnClickProps(e)\n        }\n      }\n\n      return actualOnClickTrigger\n    } else if (actualOnClickProps) {\n      return actualOnClickProps\n    }\n\n    return undefined\n  }, [actualOnClickProps, actualOnClickTrigger])\n\n  const handleKeyDown: KeyboardEventHandler<HTMLButtonElement> = useCallback(\n    (e): void => {\n      if (!parentRef?.current) {\n        return\n      }\n\n      const item = e.target as HTMLElement\n\n      switch (e.key) {\n        case 'Home': {\n          e.preventDefault()\n          focusFirstSibling(parentRef.current)\n          break\n        }\n        case 'End': {\n          e.preventDefault()\n          focusLastSibling(parentRef.current)\n          break\n        }\n        case 'ArrowLeft':\n        case 'ArrowUp': {\n          e.preventDefault()\n          focusPreviousSibling(item, parentRef.current)\n          break\n        }\n        case 'ArrowRight':\n        case 'ArrowDown': {\n          e.preventDefault()\n          focusNextSibling(item, parentRef.current)\n          break\n        }\n      }\n    },\n    [parentRef],\n  )\n\n  return (\n    // eslint-disable-next-line smarthr/a11y-heading-in-sectioning-content\n    <Heading unrecommendedTag={unrecommendedHeadingTag} type={headingType}>\n      <button\n        {...rest}\n        type=\"button\"\n        value={name}\n        id={`${name}-trigger`}\n        aria-expanded={isExpanded}\n        aria-controls={`${name}-content`}\n        onClick={handleClick}\n        onKeyDown={handleKeyDown}\n        className={classNames.button}\n        data-component=\"AccordionHeaderButton\"\n      >\n        <MemoizedTitle iconPosition={iconPosition} classNames={classNames}>\n          {children}\n        </MemoizedTitle>\n      </button>\n    </Heading>\n  )\n}\n\nconst MemoizedTitle = memo<\n  PropsWithChildren<{\n    iconPosition: undefined | 'left' | 'right'\n    classNames: { leftIcon: string; rightIcon: string; title: string; titleWrapper: string }\n  }>\n>(({ classNames, iconPosition, children }) => (\n  <Cluster className={classNames.titleWrapper} align=\"center\" as=\"span\">\n    {iconPosition === 'left' && <FaCaretRightIcon className={classNames.leftIcon} />}\n    <span className={classNames.title}>{children}</span>\n    {iconPosition === 'right' && <FaCaretDownIcon className={classNames.rightIcon} />}\n  </Cluster>\n))\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA0CA;AACE;AACE;AACA;AACA;;;;;;;;AAQC;AACD;AACA;AACD;AACD;AACE;AACE;AACA;AACD;AACF;AACF;;AASC;AACE;;;;AAKE;;;;AAIJ;;AAGA;;AAWA;AAGM;;AAIN;AAGM;AACI;AAMA;;AAEJ;AAGN;;;;;;AAMM;;AAGF;;;AAEA;;AAGF;AACF;AAEA;AAEI;;;AAIA;AAEA;;;AAGI;;;;;AAKA;;;AAGF;;;AAGE;;;AAGF;;;AAGE;;;;AAIN;;;AAMA;AAmBJ;AAEA;;"}