{"version":3,"file":"InformationPanel.cjs","sources":["../../../src/components/InformationPanel/InformationPanel.tsx"],"sourcesContent":["'use client'\n\nimport {\n  type FC,\n  type PropsWithChildren,\n  type ReactNode,\n  memo,\n  useEffect,\n  useId,\n  useMemo,\n  useState,\n} from 'react'\nimport { type VariantProps, tv } from 'tailwind-variants'\n\nimport { useObjectAttributes } from '../../hooks/useObjectAttributes'\nimport { useIntl } from '../../intl'\nimport { Base, type BaseElementProps } from '../Base'\nimport { Button } from '../Button'\nimport { Heading, type HeadingTagTypes } from '../Heading'\nimport {\n  FaCaretDownIcon,\n  FaCaretUpIcon,\n  FaCircleCheckIcon,\n  FaCircleExclamationIcon,\n  FaCircleInfoIcon,\n  FaRotateIcon,\n  WarningIcon,\n} from '../Icon'\nimport { Sidebar } from '../Layout'\n\ntype ObjectHeadingType = {\n  text: ReactNode\n  /**\n   * 可能な限り利用せず、SectioningContent(Article, Aside, Nav, Section)を使ってInformationPanel全体を囲むことで、InformationPanelのheadingのレベルを調整する方法を検討してください\n   */\n  unrecommendedTag?: HeadingTagTypes\n}\ntype HeadingType = ReactNode | ObjectHeadingType\ntype AbstractProps = PropsWithChildren<{\n  /** パネルのタイトル */\n  heading: HeadingType\n  /** `true` のとき、開閉ボタンを表示する */\n  toggleable?: boolean\n  /** 開閉ボタン押下時に発火するコールバック関数 */\n  onClickTrigger?: (active: boolean) => void\n}> &\n  VariantProps<typeof classNameGenerator>\n\ntype Props = AbstractProps & Omit<BaseElementProps, keyof AbstractProps>\n\nconst headingObjectConverter = (text: ReactNode) => ({ text })\n\nconst classNameGenerator = tv({\n  slots: {\n    wrapper: 'smarthr-ui-InformationPanel shr-shadow-layer-3',\n    header: 'shr-p-1.5',\n    heading: 'smarthr-ui-InformationPanel-heading',\n    toggleableButton: 'smarthr-ui-InformationPanel-closeButton -shr-my-0.5 shr-ms-auto',\n    content: [\n      'smarthr-ui-InformationPanel-content',\n      'shr-p-1.5 shr-pt-0 shr-text-base aria-hidden:shr-hidden',\n    ],\n  },\n  variants: {\n    type: {\n      success: {},\n      info: {},\n      warning: {},\n      error: {},\n      sync: {},\n    },\n    active: {\n      true: {},\n      false: {\n        header: 'shr-py-1',\n      },\n    },\n    bold: {\n      true: {\n        header: 'shr-py-1',\n        content: 'shr-pt-1',\n      },\n      false: {},\n    },\n  },\n  compoundVariants: [\n    {\n      type: ['success', 'warning', 'error'],\n      bold: true,\n      className: {\n        header: 'shr-text-white',\n        heading: '[&_.smarthr-ui-Icon]:shr-fill-white',\n      },\n    },\n    {\n      type: 'success',\n      bold: true,\n      className: {\n        header: 'shr-bg-main',\n      },\n    },\n    {\n      type: 'warning',\n      bold: true,\n      className: {\n        header: 'shr-bg-warning-yellow shr-text-black',\n        heading: [\n          '[&_.smarthr-ui-WarningIcon-wrapper]:shr-fill-black',\n          '[&_.smarthr-ui-WarningIcon-mark]:shr-fill-warning-yellow',\n        ],\n      },\n    },\n    {\n      type: 'error',\n      bold: true,\n      className: {\n        header: 'shr-bg-danger',\n      },\n    },\n  ],\n})\n\nexport const InformationPanel: FC<Props> = ({\n  heading,\n  type = 'info',\n  toggleable,\n  active: activeProps = true,\n  bold,\n  className,\n  children,\n  onClickTrigger,\n  ...rest\n}) => {\n  const [active, setActive] = useState(activeProps)\n  const id = useId()\n  const contentId = `${id}-content`\n\n  useEffect(() => {\n    setActive(activeProps)\n  }, [activeProps])\n\n  const classNamesMapper = useMemo(() => {\n    const withActive = classNameGenerator({\n      type,\n      active: true,\n      bold,\n    })\n    const withInactive = classNameGenerator({\n      type,\n      active: false,\n      bold,\n    })\n\n    const wrapperProps = { className }\n\n    return {\n      active: {\n        wrapper: withActive.wrapper(wrapperProps),\n        header: withActive.header(),\n        heading: withActive.heading(),\n        toggleableButton: withActive.toggleableButton(),\n        content: withActive.content(),\n      },\n      inactive: {\n        wrapper: withInactive.wrapper(wrapperProps),\n        header: withInactive.header(),\n        heading: withInactive.heading(),\n        toggleableButton: withInactive.toggleableButton(),\n        content: withInactive.content(),\n      },\n    }\n  }, [bold, type, className])\n\n  const classNames = classNamesMapper[active ? 'active' : 'inactive']\n\n  return (\n    <Base {...rest} overflow=\"hidden\" as=\"section\" className={classNames.wrapper}>\n      <Sidebar align=\"baseline\" right className={classNames.header}>\n        <MemoizedHeading\n          heading={heading}\n          id={`${id}-heading`}\n          className={classNames.heading}\n          type={type}\n        />\n        {toggleable && (\n          <ToggleableButton\n            active={active}\n            onClickTrigger={onClickTrigger}\n            setActive={setActive}\n            contentId={contentId}\n            className={classNames.toggleableButton}\n          />\n        )}\n      </Sidebar>\n      <div id={contentId} aria-hidden={!active} className={classNames.content}>\n        {children}\n      </div>\n    </Base>\n  )\n}\n\nconst MemoizedHeading = memo<\n  Required<Pick<Props, 'type'>> & {\n    heading: Props['heading']\n    id: string\n    className: string\n  }\n>(({ type, heading: orgHeading, ...rest }) => {\n  const heading = useObjectAttributes<HeadingType, ObjectHeadingType>(\n    orgHeading,\n    headingObjectConverter,\n  )\n\n  const icon = useMemo(() => {\n    switch (type) {\n      case 'info':\n        return <FaCircleInfoIcon color=\"TEXT_GREY\" />\n      case 'success':\n        return <FaCircleCheckIcon color=\"MAIN\" />\n      case 'warning':\n        return <WarningIcon />\n      case 'error':\n        return <FaCircleExclamationIcon color=\"DANGER\" />\n      case 'sync':\n        return <FaRotateIcon color=\"MAIN\" />\n    }\n  }, [type])\n\n  return (\n    <Heading\n      {...rest}\n      // eslint-disable-next-line smarthr/a11y-heading-in-sectioning-content\n      unrecommendedTag={heading.unrecommendedTag}\n      icon={{\n        prefix: icon,\n        gap: 0.5,\n      }}\n      type=\"blockTitle\"\n    >\n      {heading.text}\n    </Heading>\n  )\n})\n\nconst ToggleableButton: FC<\n  Pick<Props, 'onClickTrigger'> & {\n    active: boolean\n    setActive: (flg: boolean) => void\n    contentId: string\n    className: string\n  }\n> = ({ active, onClickTrigger, setActive, contentId, className }) => {\n  const { localize } = useIntl()\n\n  const buttonLabels = useMemo(\n    () => ({\n      open: localize({\n        id: 'smarthr-ui/InformationPanel/openButtonLabel',\n        defaultText: '開く',\n      }),\n      close: localize({\n        id: 'smarthr-ui/InformationPanel/closeButtonLabel',\n        defaultText: '閉じる',\n      }),\n    }),\n    [localize],\n  )\n\n  const onClick = useMemo(\n    () => (onClickTrigger ? () => onClickTrigger(active) : () => setActive(!active)),\n    [active, onClickTrigger, setActive],\n  )\n\n  return (\n    <Button\n      aria-expanded={active}\n      aria-controls={contentId}\n      onClick={onClick}\n      suffix={active ? <FaCaretUpIcon /> : <FaCaretDownIcon />}\n      size=\"S\"\n      className={className}\n    >\n      {active ? buttonLabels.close : buttonLabels.open}\n    </Button>\n  )\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA;AAEA;AACE;AACE;AACA;AACA;AACA;AACA;;;AAGC;AACF;AACD;AACE;AACE;AACA;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACE;AACD;AACF;AACD;AACE;AACE;AACA;AACD;AACD;AACD;AACF;AACD;AACE;AACE;AACA;AACA;AACE;AACA;AACD;AACF;AACD;AACE;AACA;AACA;AACE;AACD;AACF;AACD;AACE;AACA;AACA;AACE;AACA;;;AAGC;AACF;AACF;AACD;AACE;AACA;AACA;AACE;AACD;AACF;AACF;AACF;AAEM;;AAYL;AACA;;;AAIA;AAEA;;;AAGI;;AAED;;;AAGC;;AAED;AAED;;AAGE;AACE;AACA;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACA;AACA;AACA;AACD;;;AAIL;;AA0BF;AAEA;;AAYE;;AAEI;AACE;AACF;AACE;AACF;;AAEA;AACE;AACF;AACE;;AAEN;AAEA;;AAII;AAEE;AACA;;AAOR;AAEA;AAQE;AAEA;;AAGM;AACA;;;AAGA;AACA;;AAEH;AAIH;;AAiBF;;"}