{"version":3,"file":"Pagination.cjs","sources":["../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["'use client'\n\nimport {\n  type ElementType,\n  type FC,\n  type HTMLAttributes,\n  type MouseEvent,\n  memo,\n  useMemo,\n} from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useIntl } from '../../intl'\nimport { range } from '../../libs/lodash'\nimport { Cluster, Reel } from '../Layout'\nimport { Nav } from '../SectioningContent'\n\nimport { PaginationControllerItemButton } from './PaginationControllerItemButton'\nimport { PaginationItemButton } from './PaginationItemButton'\n\nconst classNameGenerator = tv({\n  slots: {\n    wrapper: 'smarthr-ui-Pagination shr-inline-block shr-max-w-full',\n    list: 'shr-m-0.25 shr-list-none shr-ps-[unset]',\n    firstListItem: 'smarthr-ui-Pagination-first',\n    prevListItem: 'smarthr-ui-Pagination-prev',\n    nextListItem: 'smarthr-ui-Pagination-next',\n    lastListItem: 'smarthr-ui-Pagination-last',\n  },\n  variants: {\n    withoutNumbers: {\n      true: {\n        firstListItem: 'shr-mr-0.5',\n        prevListItem: 'shr-mr-0',\n        nextListItem: 'shr-ml-0',\n        lastListItem: 'shr-ml-0.5',\n      },\n      false: {\n        prevListItem: 'shr-mr-0.5',\n        nextListItem: 'shr-ml-0.5',\n      },\n    },\n  },\n})\n\ntype CommonProps = {\n  /** 全ページ数 */\n  total: number\n  /** 現在のページ */\n  current: number\n  /** 現在のページの前後に表示するページ番号のボタンの数 */\n  padding?: number\n  /** `true` のとき、ページ番号のボタンを表示しない */\n  withoutNumbers?: boolean\n}\n\ntype ButtonProps = CommonProps & {\n  /** ボタンを押下したときに発火するコールバック関数 */\n  onClick: (pageNumber: number, e: MouseEvent<HTMLElement>) => void\n  /** href属性生成用関数。設定した場合、番号やarrowがbuttonからa要素に置き換わります */\n  hrefTemplate?: undefined\n  /** next/linkなどのカスタムコンポーネントを指定します。指定がない場合はデフォルトで `a` タグが使用されます。 */\n  linkAs?: undefined\n}\ntype AnchorProps = CommonProps & {\n  /** リンクを押下したときに発火するコールバック関数 */\n  onClick?: (href: string, e: MouseEvent<HTMLElement>) => void\n  /** href属性生成用関数。設定した場合、番号やarrowがbuttonからa要素に置き換わります */\n  hrefTemplate: (pageNumber: number) => string\n  /** next/linkなどのカスタムコンポーネントを指定します。指定がない場合はデフォルトで `a` タグが使用されます。 */\n  linkAs?: ElementType\n}\n\ntype AbstractProps = ButtonProps | AnchorProps\ntype Props = AbstractProps & Omit<HTMLAttributes<HTMLElement>, keyof AbstractProps>\n\nconst BUTTON_REGEX = /^button$/i\nconst ANCHOR_REGEX = /^a/i\n\nconst getTargetDelegateElement = (e: MouseEvent<HTMLElement>, regex: RegExp) =>\n  (e.nativeEvent.composedPath() as HTMLElement[]).find((elm) => regex.test(elm.tagName))\n\nexport const Pagination: FC<Props> = (props) =>\n  props.total > 1 ? <ActualPagination {...props} /> : null\n\nconst ActualPagination: FC<Props> = ({\n  total,\n  current,\n  onClick,\n  padding,\n  className,\n  withoutNumbers,\n  hrefTemplate,\n  linkAs,\n  ...rest\n}) => {\n  const { localize } = useIntl()\n  const classNames = useMemo(() => {\n    const { wrapper, list, firstListItem, prevListItem, nextListItem, lastListItem } =\n      classNameGenerator()\n    const itemArg = { withoutNumbers: withoutNumbers || false }\n\n    return {\n      wrapper: wrapper({ className }),\n      list: list(),\n      firstListItem: firstListItem(itemArg),\n      prevListItem: prevListItem(itemArg),\n      nextListItem: nextListItem(itemArg),\n      lastListItem: lastListItem(itemArg),\n    }\n  }, [className, withoutNumbers])\n\n  const onDelegateClick = useMemo(() => {\n    if (!onClick) {\n      return undefined\n    }\n\n    if (hrefTemplate) {\n      return (e: MouseEvent<HTMLElement>) => {\n        const anchor = getTargetDelegateElement(e, ANCHOR_REGEX)\n\n        if (!anchor) {\n          return\n        }\n\n        const href = (anchor as HTMLAnchorElement).href\n\n        if (href) {\n          onClick(href, e)\n        }\n      }\n    }\n\n    return (e: MouseEvent<HTMLElement>) => {\n      const button = getTargetDelegateElement(e, BUTTON_REGEX)\n\n      if (button) {\n        onClick(parseInt((button as HTMLButtonElement).value, 10), e)\n      }\n    }\n  }, [onClick, hrefTemplate])\n\n  const navigationLabel = useMemo(\n    () =>\n      localize({\n        id: 'smarthr-ui/Pagination/navigationLabel',\n        defaultText: 'ページネーション',\n      }),\n    [localize],\n  )\n\n  return (\n    <Nav {...rest} className={classNames.wrapper} aria-label={navigationLabel}>\n      <Reel onClick={onDelegateClick}>\n        <ItemButtons\n          total={total}\n          current={current}\n          padding={padding}\n          withoutNumbers={withoutNumbers}\n          hrefTemplate={hrefTemplate}\n          classNames={classNames}\n          linkAs={linkAs}\n        />\n      </Reel>\n    </Nav>\n  )\n}\n\nconst ItemButtons = memo<\n  Pick<Props, 'total' | 'current' | 'padding' | 'withoutNumbers' | 'hrefTemplate' | 'linkAs'> & {\n    classNames: {\n      list: string\n      firstListItem: string\n      prevListItem: string\n      nextListItem: string\n      lastListItem: string\n    }\n  }\n>(({ total, current, padding, withoutNumbers, hrefTemplate, classNames, linkAs }) => {\n  const pageNumbers = useMemo(() => {\n    if (withoutNumbers) {\n      return []\n    }\n\n    const actualPadding = padding ?? 4\n\n    return range(Math.max(current - actualPadding, 1), Math.min(current + actualPadding, total) + 1)\n  }, [current, total, padding, withoutNumbers])\n\n  const controllerAttrs = useMemo(\n    () => ({\n      prev: {\n        disabled: current === 1,\n        direction: 'prev' as const,\n        hrefTemplate,\n        linkAs,\n      },\n      next: {\n        disabled: current === total,\n        direction: 'next' as const,\n        hrefTemplate,\n        linkAs,\n      },\n    }),\n    [current, total, hrefTemplate, linkAs],\n  )\n\n  return (\n    <Cluster as=\"ul\" className={classNames.list}>\n      <DoubleIconItemButton\n        {...controllerAttrs.prev}\n        targetPage={1}\n        className={classNames.firstListItem}\n      />\n      <li className={classNames.prevListItem}>\n        <PaginationControllerItemButton {...controllerAttrs.prev} targetPage={current - 1} />\n      </li>\n      {pageNumbers.map((page) => (\n        <NumberItemButton\n          key={page}\n          page={page}\n          disabled={page === current}\n          hrefTemplate={hrefTemplate}\n          linkAs={linkAs}\n        />\n      ))}\n      <li className={classNames.nextListItem}>\n        <PaginationControllerItemButton {...controllerAttrs.next} targetPage={current + 1} />\n      </li>\n      <DoubleIconItemButton\n        {...controllerAttrs.next}\n        targetPage={total}\n        className={classNames.lastListItem}\n      />\n    </Cluster>\n  )\n})\n\nconst NumberItemButton = memo<\n  Pick<Props, 'hrefTemplate' | 'linkAs'> & { page: number; disabled: boolean }\n>(({ disabled, ...rest }) => (\n  <li className={`smarthr-ui-Pagination-${disabled ? 'current' : 'page'}`}>\n    <PaginationItemButton {...rest} disabled={disabled} />\n  </li>\n))\n\nconst DoubleIconItemButton = memo<\n  Pick<Props, 'hrefTemplate' | 'linkAs'> & {\n    disabled: boolean\n    direction: 'prev' | 'next'\n    targetPage: number\n    className: string\n  }\n>(({ className, ...rest }) => (\n  <li className={className}>\n    <PaginationControllerItemButton {...rest} double />\n  </li>\n))\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoBA;AACE;AACE;AACA;AACA;AACA;AACA;AACA;AACD;AACD;AACE;AACE;AACE;AACA;AACA;AACA;AACD;AACD;AACE;AACA;AACD;AACF;AACF;AACF;AAiCD;AACA;AAEA;AAGO;AAGP;AAWE;AACA;AACE;;;AAKE;;AAEA;AACA;AACA;AACA;;AAEJ;AAEA;;AAEI;;;;;;;;AAWE;;AAGE;;AAEJ;;;;;AAOE;;AAEJ;AACF;;AAKM;AACA;AACD;;AAmBP;AAEA;AAWE;;AAEI;;AAGF;;;AAKF;AAEI;;AAEE;;;AAGD;AACD;;AAEE;;;AAGD;;AAKL;AA6BF;AAEA;AAQA;;"}