@twreporter/react-typescript-components 0.1.0-beta.16 → 0.1.0-beta.17

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 (172) hide show
  1. package/lib/button/constants.d.mts +2 -2
  2. package/lib/button/index.d.mts +12 -12
  3. package/lib/button/index.js +1 -1
  4. package/lib/button/index.mjs +1 -1
  5. package/lib/{button-hDNHA85d.mjs → button-D_AWI7r9.mjs} +8 -2
  6. package/lib/button-D_AWI7r9.mjs.map +1 -0
  7. package/lib/{button-D50NHdly.js → button-Dk0MxlKd.js} +8 -2
  8. package/lib/button-Dk0MxlKd.js.map +1 -0
  9. package/lib/constants/release-branch.d.mts +2 -2
  10. package/lib/constants/theme.d.mts +2 -2
  11. package/lib/{constants-BNxn_qJc.js → constants-91DoZaeP.js} +1 -1
  12. package/lib/{constants-BNxn_qJc.js.map → constants-91DoZaeP.js.map} +1 -1
  13. package/lib/constants-BGUGvo1A.d.ts +22 -0
  14. package/lib/constants-BP47D2l7.js +36 -0
  15. package/lib/constants-BP47D2l7.js.map +1 -0
  16. package/lib/{constants--CDeoDub.mjs → constants-BYqJQzQQ.mjs} +1 -1
  17. package/lib/{constants--CDeoDub.mjs.map → constants-BYqJQzQQ.mjs.map} +1 -1
  18. package/lib/{constants-Cb4Udkwt.d.mts → constants-BnVX84Yl.d.mts} +2 -2
  19. package/lib/{constants-nmH6p6-y.js → constants-BuIUKM2c.js} +1 -1
  20. package/lib/{constants-nmH6p6-y.js.map → constants-BuIUKM2c.js.map} +1 -1
  21. package/lib/{constants-B6oiTL1L.d.mts → constants-C2kTkuiJ.d.mts} +2 -2
  22. package/lib/{constants-CBjyeHSl.d.ts → constants-COhDITk3.d.ts} +1 -1
  23. package/lib/{constants-CVmr4VOP.d.mts → constants-Cg4dfRV_.d.mts} +2 -2
  24. package/lib/constants-CxHP9dkH.d.mts +22 -0
  25. package/lib/{constants-z9Q8ph_H.mjs → constants-Cz7n-nLz.mjs} +1 -1
  26. package/lib/{constants-z9Q8ph_H.mjs.map → constants-Cz7n-nLz.mjs.map} +1 -1
  27. package/lib/{constants-B_NgWFML.d.ts → constants-CzHmv07x.d.ts} +1 -1
  28. package/lib/constants-Dfgyc0ND.mjs +18 -0
  29. package/lib/constants-Dfgyc0ND.mjs.map +1 -0
  30. package/lib/{constants-D-mBwgNQ.d.mts → constants-P65Nafg1.d.mts} +2 -2
  31. package/lib/{constants-BqAhJjFv.d.mts → constants-oX1rftqQ.d.mts} +2 -2
  32. package/lib/customized-link/external-link.d.mts +2 -2
  33. package/lib/customized-link/external-link.js +1 -1
  34. package/lib/customized-link/external-link.mjs +1 -1
  35. package/lib/customized-link/index.d.mts +6 -6
  36. package/lib/customized-link/index.js +3 -3
  37. package/lib/customized-link/index.mjs +2 -2
  38. package/lib/customized-link/internal-link.d.mts +2 -2
  39. package/lib/customized-link/internal-link.js +1 -1
  40. package/lib/customized-link/type.d.mts +1 -1
  41. package/lib/{customized-link-DnaZxeKK.mjs → customized-link-DNKmWI0u.mjs} +2 -2
  42. package/lib/{customized-link-DnaZxeKK.mjs.map → customized-link-DNKmWI0u.mjs.map} +1 -1
  43. package/lib/{customized-link-DqW2a8oZ.js → customized-link-XNoMkeYw.js} +3 -3
  44. package/lib/{customized-link-DqW2a8oZ.js.map → customized-link-XNoMkeYw.js.map} +1 -1
  45. package/lib/divider/constants.d.mts +2 -2
  46. package/lib/divider/constants.js +1 -1
  47. package/lib/divider/constants.mjs +1 -1
  48. package/lib/divider/index.d.mts +2 -2
  49. package/lib/divider/index.js +2 -2
  50. package/lib/divider/index.mjs +2 -2
  51. package/lib/{divider-CE4u6SR5.mjs → divider-CEIxmAsH.mjs} +2 -2
  52. package/lib/{divider-CE4u6SR5.mjs.map → divider-CEIxmAsH.mjs.map} +1 -1
  53. package/lib/{divider-B1zvSjNJ.js → divider-Db3AhImD.js} +2 -2
  54. package/lib/{divider-B1zvSjNJ.js.map → divider-Db3AhImD.js.map} +1 -1
  55. package/lib/dropdown-menu/index.d.mts +1 -1
  56. package/lib/dropdown-menu/index.js +4 -4
  57. package/lib/dropdown-menu/index.mjs +3 -3
  58. package/lib/{dropdown-menu-D7VNOiIl.mjs → dropdown-menu-CuyS5r71.mjs} +2 -2
  59. package/lib/{dropdown-menu-D7VNOiIl.mjs.map → dropdown-menu-CuyS5r71.mjs.map} +1 -1
  60. package/lib/{dropdown-menu-BAqmP8qa.js → dropdown-menu-tbV9rhnw.js} +3 -3
  61. package/lib/{dropdown-menu-BAqmP8qa.js.map → dropdown-menu-tbV9rhnw.js.map} +1 -1
  62. package/lib/{external-link-DoBTwlV3.js → external-link-BMrkjNyi.js} +1 -1
  63. package/lib/{external-link-DoBTwlV3.js.map → external-link-BMrkjNyi.js.map} +1 -1
  64. package/lib/{external-link-DXT5ep5-.mjs → external-link-BykRRwmY.mjs} +1 -1
  65. package/lib/{external-link-DXT5ep5-.mjs.map → external-link-BykRRwmY.mjs.map} +1 -1
  66. package/lib/{external-link-goP_Ay-S.d.mts → external-link-khVeTReZ.d.mts} +2 -2
  67. package/lib/hamburger-menu/index.js +12 -9
  68. package/lib/hamburger-menu/index.mjs +11 -8
  69. package/lib/{hamburger-menu-DOrmybn_.mjs → hamburger-menu-Ca6QMgF9.mjs} +43 -35
  70. package/lib/hamburger-menu-Ca6QMgF9.mjs.map +1 -0
  71. package/lib/{hamburger-menu-DNfJ2jMA.js → hamburger-menu-qrLPGpHF.js} +44 -36
  72. package/lib/hamburger-menu-qrLPGpHF.js.map +1 -0
  73. package/lib/header/index.d.mts +3 -3
  74. package/lib/header/index.js +58 -17
  75. package/lib/header/index.js.map +1 -1
  76. package/lib/header/index.mjs +57 -16
  77. package/lib/header/index.mjs.map +1 -1
  78. package/lib/{heading-BSEtBLuY.mjs → heading-BWuXn7wB.mjs} +1 -1
  79. package/lib/{heading-BSEtBLuY.mjs.map → heading-BWuXn7wB.mjs.map} +1 -1
  80. package/lib/{heading-CNS7rJIc.js → heading-DJepEhoE.js} +1 -1
  81. package/lib/{heading-CNS7rJIc.js.map → heading-DJepEhoE.js.map} +1 -1
  82. package/lib/hooks/index.d.mts +10 -0
  83. package/lib/hooks/index.d.ts +10 -0
  84. package/lib/hooks/index.js +6 -0
  85. package/lib/hooks/index.mjs +4 -0
  86. package/lib/hooks/use-outside-click.d.mts +2 -0
  87. package/lib/hooks/use-outside-click.d.ts +2 -0
  88. package/lib/hooks/use-outside-click.js +3 -0
  89. package/lib/hooks/use-outside-click.mjs +3 -0
  90. package/lib/hooks-DFV2v01e.mjs +8 -0
  91. package/lib/hooks-DFV2v01e.mjs.map +1 -0
  92. package/lib/hooks-Mt5N4Z2W.js +13 -0
  93. package/lib/hooks-Mt5N4Z2W.js.map +1 -0
  94. package/lib/icons/constants.d.mts +2 -2
  95. package/lib/icons/constants.d.ts +1 -1
  96. package/lib/icons/index.d.mts +3 -3
  97. package/lib/icons/index.d.ts +1 -1
  98. package/lib/{index-CYb6xr3M.d.mts → index-DaRD2S-9.d.mts} +1 -1
  99. package/lib/input/constants.d.mts +3 -0
  100. package/lib/input/constants.d.ts +3 -0
  101. package/lib/input/constants.js +5 -0
  102. package/lib/input/constants.mjs +3 -0
  103. package/lib/input/index.d.mts +44 -0
  104. package/lib/input/index.d.ts +44 -0
  105. package/lib/input/index.js +15 -0
  106. package/lib/input/index.mjs +13 -0
  107. package/lib/input/theme.d.mts +16 -0
  108. package/lib/input/theme.d.ts +16 -0
  109. package/lib/input/theme.js +4 -0
  110. package/lib/input/theme.mjs +4 -0
  111. package/lib/input-_Hl5B4_K.mjs +73 -0
  112. package/lib/input-_Hl5B4_K.mjs.map +1 -0
  113. package/lib/input-czWOItrW.js +88 -0
  114. package/lib/input-czWOItrW.js.map +1 -0
  115. package/lib/{internal-link-B9ExuJfg.js → internal-link-BLXTBMRq.js} +1 -1
  116. package/lib/{internal-link-B9ExuJfg.js.map → internal-link-BLXTBMRq.js.map} +1 -1
  117. package/lib/{internal-link-Ciu7CWSY.d.mts → internal-link-BSb3__eR.d.mts} +2 -2
  118. package/lib/logo/constants.d.mts +2 -2
  119. package/lib/logo/constants.d.ts +1 -1
  120. package/lib/logo/index.d.mts +8 -8
  121. package/lib/logo/index.d.ts +6 -6
  122. package/lib/logo/index.js +1 -1
  123. package/lib/logo/index.mjs +1 -1
  124. package/lib/{logo-CuMjQGbj.js → logo-BTNfdxTv.js} +1 -1
  125. package/lib/{logo-CuMjQGbj.js.map → logo-BTNfdxTv.js.map} +1 -1
  126. package/lib/{logo-CxXblyO9.mjs → logo-D68VZ-fc.mjs} +1 -1
  127. package/lib/{logo-CxXblyO9.mjs.map → logo-D68VZ-fc.mjs.map} +1 -1
  128. package/lib/{release-branch-BqeBsvrl.d.mts → release-branch-8qGtkKtd.d.mts} +2 -2
  129. package/lib/styles.css +104 -9
  130. package/lib/tab-bar/constants.d.mts +3 -3
  131. package/lib/tab-bar/constants.js +1 -1
  132. package/lib/tab-bar/constants.mjs +1 -1
  133. package/lib/tab-bar/index.js +7 -7
  134. package/lib/tab-bar/index.mjs +6 -6
  135. package/lib/tab-bar/theme.d.mts +2 -2
  136. package/lib/tab-bar/theme.js +1 -1
  137. package/lib/tab-bar/theme.mjs +1 -1
  138. package/lib/{tab-bar-qKbhyjg-.js → tab-bar-Binq1EhQ.js} +7 -7
  139. package/lib/{tab-bar-qKbhyjg-.js.map → tab-bar-Binq1EhQ.js.map} +1 -1
  140. package/lib/{tab-bar-CdsxfUdk.mjs → tab-bar-BqiC7-Lw.mjs} +6 -6
  141. package/lib/{tab-bar-CdsxfUdk.mjs.map → tab-bar-BqiC7-Lw.mjs.map} +1 -1
  142. package/lib/text/constants.d.mts +2 -2
  143. package/lib/text/heading.d.mts +2 -2
  144. package/lib/text/heading.js +1 -1
  145. package/lib/text/heading.mjs +1 -1
  146. package/lib/text/paragraph.d.mts +2 -2
  147. package/lib/{theme-lCi6tmmS.d.mts → theme-B9CWW8U9.d.mts} +2 -2
  148. package/lib/{theme-W--MzZEH.js → theme-BOMyqC4d.js} +1 -1
  149. package/lib/{theme-W--MzZEH.js.map → theme-BOMyqC4d.js.map} +1 -1
  150. package/lib/theme-CIEkzycI.js +43 -0
  151. package/lib/theme-CIEkzycI.js.map +1 -0
  152. package/lib/theme-CkSx7UX3.mjs +38 -0
  153. package/lib/theme-CkSx7UX3.mjs.map +1 -0
  154. package/lib/{theme-DQCIQh_8.mjs → theme-PhMjSVv9.mjs} +1 -1
  155. package/lib/{theme-DQCIQh_8.mjs.map → theme-PhMjSVv9.mjs.map} +1 -1
  156. package/lib/title-bar/index.d.mts +4 -4
  157. package/lib/title-bar/index.d.ts +4 -4
  158. package/lib/title-bar/index.js +5 -5
  159. package/lib/title-bar/index.mjs +4 -4
  160. package/lib/{type-2Go0njwa.d.mts → type-4zpM3Fk5.d.mts} +1 -1
  161. package/lib/types/index.d.mts +1 -1
  162. package/lib/use-outside-click-436PXIeY.js +27 -0
  163. package/lib/use-outside-click-436PXIeY.js.map +1 -0
  164. package/lib/use-outside-click-Bz_v9VCq.mjs +20 -0
  165. package/lib/use-outside-click-Bz_v9VCq.mjs.map +1 -0
  166. package/lib/use-outside-click-CHxRFaTZ.d.ts +7 -0
  167. package/lib/use-outside-click-DToGSYRk.d.mts +7 -0
  168. package/package.json +2 -2
  169. package/lib/button-D50NHdly.js.map +0 -1
  170. package/lib/button-hDNHA85d.mjs.map +0 -1
  171. package/lib/hamburger-menu-DNfJ2jMA.js.map +0 -1
  172. package/lib/hamburger-menu-DOrmybn_.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}>","RELEASE_BRANCH","THEME","HeaderContext","ExternalLink","InternalLink","IconButton","Search","INTERNAL_LINKS","KidStar","Member","THEME","LOGO_TYPE","TopRow: FC<TopRowProps>","HeaderContext","HamburgerContext","ExternalLink","InternalLink","ZIndex","IconButton","Hamburger","INTERNAL_LINKS","LogoHeader","HEADER_ACTION_LINKS","PillButton","CHANNELS: ChannelType[]","INTERNAL_LINKS","_","ChannelItem: FC<ChannelItemProps>","HeaderContext","ExternalLink","InternalLink","TextButton","HamburgerContext","IconButton","Hamburger","Divider","DesktopAndAbove: FC<DesktopAndAboveProps>","HeaderContext","TopRow","Divider","ZIndex","CSSTransition","Channel","RELEASE_BRANCH","forClientSideRendering","TabletAndBelow: FC<TabletAndBelowProps>","HeaderContext","ExternalLink","InternalLink","INTERNAL_LINKS","ZIndex","IconButton","Arrow","LogoHeader","EXTERNAL_LINKS","PillButton","Member","TextButton","creator: StateCreator<AuthState>","Header: FC<HeaderProps>","HeaderContext","HamburgerContext","ZIndex","THEME","DesktopAndAbove","TabletAndBelow","HamburgerMenu","TabBar"],"sources":["../../src/header/constants/animation.ts","../../src/header/components/top-row/icons.tsx","../../src/header/utils/theme.ts","../../src/header/components/top-row/index.tsx","../../src/header/components/channels/constants/index.ts","../../src/header/components/channels/index.tsx","../../src/header/components/desktop-and-above.tsx","../../src/header/utils/links.ts","../../src/header/components/tablet-and-below.tsx","../../src/header/store/auth-store.ts","../../src/header/index.tsx"],"sourcesContent":["export const ANIMATION = {\n step1Duration: 'duration-[200ms]',\n step2Delay: 'delay-[150ms]',\n step2Duration: 'duration-[50ms]',\n step3Delay: 'delay-[150ms]',\n step3Duration: 'duration-[200ms]',\n} as const\n","import { useContext, type FC } from 'react'\n// context\nimport { HeaderContext } from '../../context'\n// constants\nimport { THEME, type Theme } from '../../../constants/theme'\nimport {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../../constants/release-branch'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// icons\nimport { Search, KidStar, Member } from '../../../icons'\n// button\nimport { IconButton } from '../../../button'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\nexport const Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}> = ({ releaseBranch = RELEASE_BRANCH.master, theme = THEME.normal }) => {\n const { isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className=\"ml-[24px] flex flex-row gap-[16px]\">\n <IconButton iconComponent={Search(releaseBranch)} theme={theme} />\n <LinkComponent to={INTERNAL_LINKS.myReading.index}>\n <IconButton iconComponent={KidStar(releaseBranch)} theme={theme} />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n <IconButton iconComponent={Member(releaseBranch)} theme={theme} />\n </LinkComponent>\n </div>\n )\n}\n","import { THEME, type Theme } from '../../constants/theme'\nimport { LOGO_TYPE } from '../../logo/constants'\n\nexport const selectLogoType = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return LOGO_TYPE.white\n default:\n return LOGO_TYPE.default\n }\n}\n\nexport const selectHeaderTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n return {\n bgColor: 'bg-photo-dark',\n topRowBgColor: 'bg-photo-dark',\n }\n case THEME.transparent:\n return {\n bgColor: 'bg-opacity-black-02',\n topRowBgColor: 'bg-transparent',\n }\n case THEME.index:\n return {\n bgColor: 'bg-gray-white',\n topRowBgColor: 'bg-gray-white',\n }\n default:\n return {\n bgColor: 'bg-gray-100',\n topRowBgColor: 'bg-gray-100',\n }\n }\n}\n\nexport const selectSloganTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return 'text-gray-white'\n default:\n return 'text-gray-800'\n }\n}\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// constants\nimport { ZIndex } from '../../constants/z-index'\nimport { ANIMATION } from '../../constants/animation'\nimport { HEADER_ACTION_LINKS } from '../../constants/action-links'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// logo\nimport { LogoHeader } from '../../../logo'\nimport type { LogoType } from '../../../logo/constants'\n// buton\nimport { IconButton, PillButton } from '../../../button'\n// components\nimport { Icons } from './icons'\nimport { Hamburger } from '../../../icons'\n// utils\nimport { selectSloganTheme } from '../../utils/theme'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\ntype TopRowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TopRow: FC<TopRowProps> = ({ topRowBgColor, logoType }) => {\n const { toUseNarrow, releaseBranch, theme, isLinkExternal } =\n useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} px-[16px] ${topRowBgColor}`,\n toUseNarrow ? 'py-[16px]' : 'py-[24px]'\n )}\n >\n {/* left group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n toUseNarrow ? 'opacity-100' : 'opacity-0',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'delay-[350ms]' : 'delay-0'\n )}\n >\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n </div>\n {/* Logo */}\n <div\n className={clsx(\n `flex items-center mr-[16px] transition-all ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'ml-[24px]' : 'ml-0',\n toUseNarrow ? 'translate-x-0' : '-translate-x-[24px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0'\n )}\n >\n <LinkComponent to={INTERNAL_LINKS.home}>\n <LogoHeader\n type={logoType}\n releaseBranch={releaseBranch}\n className={clsx(\n `transition-height ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'h-[24px]' : 'h-[32px]'\n )}\n />\n </LinkComponent>\n </div>\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step3Duration}`,\n 'flex items-center font-serif font-normal text-[14px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n selectSloganTheme(theme)\n )}\n >\n 深度 × 開放 × 非營利\n </div>\n </div>\n {/* right group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n 'flex items-center gap-[16px]',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100'\n )}\n >\n {HEADER_ACTION_LINKS.map((link) => (\n <LinkComponent to={link.to} target={link.target} key={link.label}>\n <PillButton text={link.label} theme={theme} type={link.type} />\n </LinkComponent>\n ))}\n </div>\n {/* icons */}\n <Icons releaseBranch={releaseBranch} theme={theme} />\n </div>\n </div>\n )\n}\n\nexport default TopRow\n","import { INTERNAL_LINKS } from '../../../../constants/internal-links'\nimport type { LinkTarget } from '../../../../customized-link/type'\n\ntype ChannelType = {\n label: string\n to: string\n target: LinkTarget\n}\nexport const CHANNELS: ChannelType[] = [\n {\n label: '最新',\n to: INTERNAL_LINKS.latest,\n target: '_self',\n },\n {\n label: '深度專題',\n to: INTERNAL_LINKS.topics,\n target: '_self',\n },\n {\n label: '國際兩岸',\n to: INTERNAL_LINKS.categories.world,\n target: '_self',\n },\n {\n label: '人權司法',\n to: INTERNAL_LINKS.categories.humanRights,\n target: '_self',\n },\n {\n label: '政治社會',\n to: INTERNAL_LINKS.categories.politicsAndSociety,\n target: '_self',\n },\n {\n label: '醫療健康',\n to: INTERNAL_LINKS.categories.health,\n target: '_self',\n },\n {\n label: '環境永續',\n to: INTERNAL_LINKS.categories.environment,\n target: '_self',\n },\n {\n label: '經濟產業',\n to: INTERNAL_LINKS.categories.econ,\n target: '_self',\n },\n {\n label: '文化生活',\n to: INTERNAL_LINKS.categories.culture,\n target: '_self',\n },\n {\n label: '教育校園',\n to: INTERNAL_LINKS.categories.education,\n target: '_self',\n },\n]\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// components\nimport { IconButton, TextButton } from '../../../button'\nimport { Hamburger } from '../../../icons'\nimport Divider from '../../../divider'\n// constants\nimport { CHANNELS } from './constants'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\nimport type { LinkTarget } from '../../../customized-link/type'\n// lodash\nimport map from 'lodash/map'\nconst _ = {\n map,\n}\ntype ChannelItemProps = {\n link: {\n href: string\n target: LinkTarget\n }\n label: string\n}\nconst ChannelItem: FC<ChannelItemProps> = ({\n link = { href: '', target: '_self' },\n label = '',\n}) => {\n const { theme, isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className={clsx('flex items-center', '[&>a]:no-underline')}>\n <LinkComponent to={link.href} target={link.target}>\n <TextButton\n text={label}\n size={TextButton.Size.l}\n theme={theme}\n style={TextButton.Style.dark}\n />\n </LinkComponent>\n </div>\n )\n}\n\nconst Channel = () => {\n const { releaseBranch, theme } = useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-between w-full px-[16px] py-[8px]\">\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n {_.map(CHANNELS, (channel) => {\n return (\n <ChannelItem\n key={`channel-${channel.label}`}\n label={channel.label}\n link={{\n href: channel.to,\n target: channel.target,\n }}\n />\n )\n })}\n </div>\n <Divider />\n </div>\n )\n}\n\nexport default Channel\n","import { useContext, useRef, type FC } from 'react'\nimport clsx from 'clsx'\nimport { CSSTransition } from 'react-transition-group'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { ANIMATION } from '../constants/animation'\n// compontents\nimport TopRow from './top-row'\nimport Channel from './channels'\nimport Divider from '../../divider'\n// type\nimport type { LogoType } from '../../logo/constants'\ntype DesktopAndAboveProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst DesktopAndAbove: FC<DesktopAndAboveProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const { toUseNarrow } = useContext(HeaderContext)\n const channelRef = useRef<HTMLDivElement>(null)\n return (\n <div className=\"hidden desktop:flex desktop:flex-col\">\n <TopRow topRowBgColor={topRowBgColor} logoType={logoType} />\n {/* divider */}\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step2Duration}`,\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n toUseNarrow ? 'delay-0' : `${ANIMATION.step2Delay}`\n )}\n >\n <Divider direction={Divider.Direction.horizontal} />\n </div>\n {/* channels */}\n <div className={`${ZIndex.channel}`}>\n <CSSTransition\n in={!toUseNarrow}\n nodeRef={channelRef}\n classNames={{\n enter: `opacity-0 -translate-y-full`,\n enterActive: `transition-all ease-linear ${ANIMATION.step1Duration} ${ANIMATION.step2Delay} opacity-100 translate-y-0`,\n exit: `opacity-100 translate-y-0`,\n exitActive: `transition-all ease-linear ${ANIMATION.step1Duration} -translate-y-full`,\n }}\n timeout={{ appear: 0, enter: 350, exit: 200 }}\n unmountOnExit\n >\n <div ref={channelRef}>\n <Channel />\n </div>\n </CSSTransition>\n </div>\n </div>\n )\n}\n\nexport default DesktopAndAbove\n","import {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../constants/release-branch'\nimport { forClientSideRendering } from '../../constants/request-origins'\n\nexport const checkReferrer = (\n referrer: string = '',\n releaseBranch: ReleaseBranch = RELEASE_BRANCH.master\n) => {\n try {\n const url = new URL(referrer)\n return url.origin === forClientSideRendering[releaseBranch].main\n } catch (_err) {\n return false\n }\n}\n","import { useContext, useState, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\n// logo\nimport { LogoHeader } from '../../logo'\nimport type { LogoType } from '../../logo/constants'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\n// button\nimport { PillButton, TextButton, IconButton } from '../../button'\n// icon\nimport { Arrow, Member } from '../../icons'\n// utils\nimport { checkReferrer } from '../utils/links'\n// lodash\nimport some from 'lodash/some'\nimport includes from 'lodash/includes'\nimport throttle from 'lodash/throttle'\nconst _ = {\n some,\n includes,\n throttle,\n}\n\ntype TabletAndBelowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TabletAndBelow: FC<TabletAndBelowProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const {\n isLinkExternal,\n releaseBranch,\n theme,\n pathname,\n referrerPath,\n isAuthed,\n } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n\n const [currentClientWidth, setCurrentClientWidth] = useState(0)\n useEffect(() => {\n const handleResize = _.throttle(() => {\n setCurrentClientWidth(document.body.clientWidth)\n }, 200)\n\n handleResize()\n window.addEventListener('resize', handleResize)\n\n return () => {\n window.removeEventListener('resize', handleResize)\n }\n }, [])\n\n const isOnArticlePage = _.includes(pathname, `${INTERNAL_LINKS.article}/`)\n const needPrevIconRoute = [\n INTERNAL_LINKS.account.donationHistoryPage,\n INTERNAL_LINKS.account.emailSubscription,\n INTERNAL_LINKS.myReading.savedBookmarks,\n INTERNAL_LINKS.myReading.browsingHistory,\n ]\n const isOnNeedPrevIconPage = _.some(needPrevIconRoute, (el) =>\n _.includes(pathname, el)\n )\n\n const showPrevIcon =\n isOnArticlePage || (isOnNeedPrevIconPage && currentClientWidth < 768) // only show it on mobile\n\n const gotoPrev = () => {\n if (referrerPath || checkReferrer(document.referrer, releaseBranch)) {\n // go to previous page when referer is twreporter site\n window.history.back()\n } else {\n // go to home page when referer is not twreporter site\n window.location.href = '/'\n }\n }\n\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} py-[16px] ${topRowBgColor}`,\n 'desktop:hidden'\n )}\n >\n <div className=\"flex flex-row gap-[8px]\">\n {/* pre button */}\n {showPrevIcon ? (\n <div className=\"p-[4px] -translate-x-[8px]\">\n <IconButton\n iconComponent={\n <Arrow\n direction={Arrow.Direction.left}\n releaseBranch={releaseBranch}\n />\n }\n theme={theme}\n onClick={gotoPrev}\n />\n </div>\n ) : null}\n {/* logo */}\n <LinkComponent to={INTERNAL_LINKS.home} className=\"flex items-center\">\n <LogoHeader type={logoType} className=\"h-[21px]\" />\n </LinkComponent>\n </div>\n {/* actions */}\n <div className=\"flex flex-row items-center gap-[16px]\">\n <LinkComponent to={EXTERNAL_LINKS.monthlyDonation}>\n <PillButton\n text=\"贊助\"\n theme={PillButton.Theme.normal}\n type={PillButton.Type.primary}\n style={PillButton.Style.brand}\n />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n {isAuthed ? (\n <IconButton iconComponent={Member(releaseBranch)} />\n ) : (\n <TextButton\n text=\"登入\"\n theme={TextButton.Theme.normal}\n style={TextButton.Style.dark}\n size={TextButton.Size.s}\n />\n )}\n </LinkComponent>\n </div>\n </div>\n )\n}\n\nexport default TabletAndBelow\n","import { create, type StateCreator } from 'zustand'\n\nexport type AuthState = {\n isAuthed: boolean\n token?: string\n setAuthed: (isAuthed: boolean) => void\n setToken: (token?: string) => void\n reset: () => void\n}\n\nconst creator: StateCreator<AuthState> = (set) => ({\n isAuthed: false,\n token: undefined,\n setAuthed: (isAuthed: boolean) => set({ isAuthed }),\n setToken: (token?: string) => set({ token }),\n reset: () => set({ isAuthed: false, token: undefined }),\n})\n\nexport const useAuthStore = create<AuthState>()(creator)\n","import { useRef, useState, useCallback, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n\n// constants\nimport { THEME, type Theme } from '../constants/theme'\nimport type { ReleaseBranch } from '../constants/release-branch'\nimport { ZIndex } from './constants/z-index'\n// components\nimport DesktopAndAbove from './components/desktop-and-above'\nimport TabletAndBelow from './components/tablet-and-below'\n// context\nimport {\n HeaderContext,\n HamburgerContext,\n type HamburgerContextType,\n} from './context'\n// utils\nimport { selectHeaderTheme, selectLogoType } from './utils/theme'\n// hamburger menu\nimport HamburgerMenu from '../hamburger-menu'\n// tab bar\nimport TabBar from '../tab-bar'\nimport { useAuthStore, type AuthState } from './store/auth-store'\n\nconst HIDE_HEADER_THRESHOLD = 8\nconst TRANSFORM_HEADER_THRESHOLD = 40\nconst TRANSFORM_TIMEOUT = 800\n\ntype HeaderProps = {\n releaseBranch: ReleaseBranch\n isLinkExternal: boolean\n theme: Theme\n pathname: string\n referrerPath: string\n hamburgerContext: HamburgerContextType\n}\nconst Header: FC<HeaderProps> = ({\n releaseBranch,\n isLinkExternal,\n theme,\n pathname,\n referrerPath,\n hamburgerContext,\n}) => {\n const isAuthed = useAuthStore((s: AuthState) => s.isAuthed)\n const { bgColor, topRowBgColor } = selectHeaderTheme(theme)\n const logoType = selectLogoType(theme)\n\n const { isHamburgerMenuOpen } = hamburgerContext\n\n const [toUseNarrow, setToUseNarrow] = useState(false)\n const [hideHeader, setHideHeader] = useState(false)\n\n const lastKnownPageYOffset = useRef(0)\n const ticking = useRef(false)\n const currentY = useRef(0)\n const readyY = useRef(0)\n const isTransforming = useRef(false)\n const transformTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const getScrollState = useCallback(\n (scrollTop: number, scrollDirection: 'up' | 'down') => {\n const isCurrentNarrow = toUseNarrow\n const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD\n const scrollState = { toUseNarrow, hideHeader }\n\n if (isTransforming.current) {\n return scrollState\n }\n\n if (scrollDirection === 'up') {\n readyY.current = scrollTop\n scrollState.hideHeader = false\n }\n\n if (scrollDirection === 'down') {\n if (\n isCurrentNarrow &&\n scrollTop - readyY.current > HIDE_HEADER_THRESHOLD\n ) {\n scrollState.hideHeader = true\n }\n }\n\n if (isCurrentNarrow) {\n scrollState.toUseNarrow =\n scrollDirection === 'down' ? true : nextToUseNarrow\n } else {\n scrollState.toUseNarrow =\n scrollDirection === 'up' ? false : nextToUseNarrow\n }\n\n if (isCurrentNarrow !== scrollState.toUseNarrow) {\n if (!transformTimer.current) {\n isTransforming.current = true\n transformTimer.current = setTimeout(() => {\n isTransforming.current = false\n readyY.current = currentY.current\n transformTimer.current = null\n }, TRANSFORM_TIMEOUT)\n }\n }\n\n return scrollState\n },\n [toUseNarrow, hideHeader]\n )\n\n const updateScrollState = useCallback(\n (currentScrollTop: number) => {\n const scrollDirection =\n currentScrollTop > currentY.current ? 'down' : 'up'\n currentY.current = currentScrollTop\n const updateState = getScrollState(currentScrollTop, scrollDirection)\n setToUseNarrow(() => updateState.toUseNarrow)\n setHideHeader(() => updateState.hideHeader)\n },\n [getScrollState]\n )\n\n const handleScroll = useCallback(() => {\n lastKnownPageYOffset.current = window.pageYOffset\n if (!ticking.current) {\n window.requestAnimationFrame(() => {\n updateScrollState(lastKnownPageYOffset.current)\n ticking.current = false\n })\n ticking.current = true\n }\n }, [updateScrollState])\n\n useEffect(() => {\n window.addEventListener('scroll', handleScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n return (\n <HeaderContext\n value={{\n releaseBranch,\n isLinkExternal,\n isAuthed,\n theme,\n pathname,\n referrerPath,\n toUseNarrow,\n hideHeader,\n }}\n >\n <HamburgerContext value={hamburgerContext}>\n <header\n className={clsx(\n `w-full top-0 transition-transform duration-300 ${bgColor} ${ZIndex.header}`,\n theme === THEME.transparent ? 'fixed' : 'sticky',\n hideHeader ? 'ease-in' : 'ease-out',\n hideHeader ? '-translate-y-full' : 'translate-y-0'\n )}\n >\n <div\n className={clsx(\n `flex flex-col mx-auto px-[24px]`,\n 'tablet:px-[32px]',\n 'desktop:px-[48px]',\n 'hd:w-[1280px] hd:px-0'\n )}\n >\n <DesktopAndAbove\n topRowBgColor={topRowBgColor}\n logoType={logoType}\n />\n <TabletAndBelow topRowBgColor={topRowBgColor} logoType={logoType} />\n </div>\n </header>\n <div\n className={clsx(\n `fixed top-0 left-0 ${ZIndex.hamburger} transition-transform duration-300 ease-in-out`,\n isHamburgerMenuOpen\n ? 'translate-x-0 opacity-100'\n : '-translate-x-full opacity-100',\n 'tablet:-left-[320px]',\n isHamburgerMenuOpen\n ? 'tablet:translate-x-[320px] tablet:opacity-100'\n : 'tablet:-translate-x-[320px] tablet:opacity-100',\n 'desktop:-left-[280px]',\n isHamburgerMenuOpen\n ? 'desktop:translate-x-[280px] desktop:opacity-100'\n : 'desktop:-translate-x-[280px] desktop:opacity-100'\n )}\n >\n <HamburgerMenu />\n </div>\n <TabBar />\n </HamburgerContext>\n </HeaderContext>\n )\n}\n\nexport default Header\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAa,YAAY;CACvB,eAAe;CACf,YAAY;CACZ,eAAe;CACf,YAAY;CACZ,eAAe;CAChB;;;;ACWD,MAAaA,SAGP,EAAE,gBAAgBC,sCAAe,QAAQ,QAAQC,oBAAM,aAAa;CACxE,MAAM,EAAE,yCAA8BC,8BAAc;CACpD,MAAM,gBAAgB,iBAAiBC,8CAAeC;AACtD,QACE,4CAAC;EAAI,WAAU;;GACb,2CAACC;IAAW,eAAeC,qBAAO,cAAc;IAAS;KAAS;GAClE,2CAAC;IAAc,IAAIC,sCAAe,UAAU;cAC1C,2CAACF;KAAW,eAAeG,sBAAQ,cAAc;KAAS;MAAS;KACrD;GAChB,2CAAC;IAAc,IAAID,sCAAe,QAAQ;cACxC,2CAACF;KAAW,eAAeI,qBAAO,cAAc;KAAS;MAAS;KACpD;;GACZ;;;;;AC7BV,MAAa,kBAAkB,UAAiB;AAC9C,SAAQ,OAAR;EACE,KAAKC,oBAAM;EACX,KAAKA,oBAAM,YACT,QAAOC,8BAAU;EACnB,QACE,QAAOA,8BAAU;;;AAIvB,MAAa,qBAAqB,UAAiB;AACjD,SAAQ,OAAR;EACE,KAAKD,oBAAM,YACT,QAAO;GACL,SAAS;GACT,eAAe;GAChB;EACH,KAAKA,oBAAM,YACT,QAAO;GACL,SAAS;GACT,eAAe;GAChB;EACH,KAAKA,oBAAM,MACT,QAAO;GACL,SAAS;GACT,eAAe;GAChB;EACH,QACE,QAAO;GACL,SAAS;GACT,eAAe;GAChB;;;AAIP,MAAa,qBAAqB,UAAiB;AACjD,SAAQ,OAAR;EACE,KAAKA,oBAAM;EACX,KAAKA,oBAAM,YACT,QAAO;EACT,QACE,QAAO;;;;;;AClBb,MAAME,UAA2B,EAAE,eAAe,eAAe;CAC/D,MAAM,EAAE,aAAa,eAAe,OAAO,yCAC9BC,8BAAc;CAC3B,MAAM,EAAE,0CAA+BC,iCAAiB;CACxD,MAAM,gBAAgB,iBAAiBC,8CAAeC;AACtD,QACE,4CAAC;EACC,6BACE,qCAAqCC,uBAAO,OAAO,aAAa,iBAChE,cAAc,cAAc,YAC7B;aAGD,4CAAC;GAAI,WAAU;;IACb,2CAAC;KACC,6BACE,cAAc,gBAAgB,aAC9B,sBAAsB,UAAU,iBAChC,cAAc,kBAAkB,UACjC;eAED,2CAACC;MACC,eAAeC,wBAAU,cAAc;MAChC;MACP,SAAS;OACT;MACE;IAEN,2CAAC;KACC,6BACE,8CAA8C,UAAU,iBACxD,cAAc,cAAc,QAC5B,cAAc,kBAAkB,uBAChC,cAAc,GAAG,UAAU,eAAe,UAC3C;eAED,2CAAC;MAAc,IAAIC,sCAAe;gBAChC,2CAACC;OACC,MAAM;OACS;OACf,6BACE,qBAAqB,UAAU,iBAC/B,cAAc,GAAG,UAAU,eAAe,WAC1C,cAAc,aAAa,WAC5B;QACD;OACY;MACZ;IACN,2CAAC;KACC,6BACE,sBAAsB,UAAU,iBAChC,wDACA,cAAc,GAAG,UAAU,eAAe,WAC1C,cAAc,wBAAwB,uBACtC,cAAc,cAAc,eAC5B,kBAAkB,MAAM,CACzB;eACF;MAEK;;IACF,EAEN,4CAAC;GAAI,WAAU;cACb,2CAAC;IACC,6BACE,gCACA,sBAAsB,UAAU,iBAChC,cAAc,GAAG,UAAU,eAAe,WAC1C,cAAc,wBAAwB,uBACtC,cAAc,cAAc,cAC7B;cAEAC,2CAAoB,KAAK,SACxB,2CAAC;KAAc,IAAI,KAAK;KAAI,QAAQ,KAAK;eACvC,2CAACC;MAAW,MAAM,KAAK;MAAc;MAAO,MAAM,KAAK;OAAQ;OADX,KAAK,MAE3C,CAChB;KACE,EAEN,2CAAC;IAAqB;IAAsB;KAAS;IACjD;GACF;;AAIV,sBAAe;;;;ACvGf,MAAaC,WAA0B;CACrC;EACE,OAAO;EACP,IAAIC,sCAAe;EACnB,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe;EACnB,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACD;EACE,OAAO;EACP,IAAIA,sCAAe,WAAW;EAC9B,QAAQ;EACT;CACF;;;;AC5CD,MAAMC,MAAI,EACR,yBACD;AAQD,MAAMC,eAAqC,EACzC,OAAO;CAAE,MAAM;CAAI,QAAQ;CAAS,EACpC,QAAQ,SACJ;CACJ,MAAM,EAAE,OAAO,yCAA8BC,8BAAc;CAC3D,MAAM,gBAAgB,iBAAiBC,8CAAeC;AACtD,QACE,2CAAC;EAAI,6BAAgB,qBAAqB,qBAAqB;YAC7D,2CAAC;GAAc,IAAI,KAAK;GAAM,QAAQ,KAAK;aACzC,2CAACC;IACC,MAAM;IACN,MAAMA,mCAAW,KAAK;IACf;IACP,OAAOA,mCAAW,MAAM;KACxB;IACY;GACZ;;AAIV,MAAM,gBAAgB;CACpB,MAAM,EAAE,eAAe,gCAAqBH,8BAAc;CAC1D,MAAM,EAAE,0CAA+BI,iCAAiB;AACxD,QACE,4CAAC;EAAI,WAAU;aACb,4CAAC;GAAI,WAAU;cACb,2CAACC;IACC,eAAeC,wBAAU,cAAc;IAChC;IACP,SAAS;KACT,EACDR,IAAE,IAAI,WAAW,YAAY;AAC5B,WACE,2CAAC;KAEC,OAAO,QAAQ;KACf,MAAM;MACJ,MAAM,QAAQ;MACd,QAAQ,QAAQ;MACjB;OALI,WAAW,QAAQ,QAMxB;KAEJ;IACE,EACN,2CAACS,oCAAU;GACP;;AAIV,uBAAe;;;;ACxDf,MAAMC,mBAA6C,EACjD,eACA,eACI;CACJ,MAAM,EAAE,sCAA2BC,8BAAc;CACjD,MAAM,+BAAoC,KAAK;AAC/C,QACE,4CAAC;EAAI,WAAU;;GACb,2CAACC;IAAsB;IAAyB;KAAY;GAE5D,2CAAC;IACC,6BACE,sBAAsB,UAAU,iBAChC,cAAc,cAAc,eAC5B,cAAc,YAAY,GAAG,UAAU,aACxC;cAED,2CAACC,mCAAQ,WAAWA,gCAAQ,UAAU,aAAc;KAChD;GAEN,2CAAC;IAAI,WAAW,GAAGC,uBAAO;cACxB,2CAACC;KACC,IAAI,CAAC;KACL,SAAS;KACT,YAAY;MACV,OAAO;MACP,aAAa,8BAA8B,UAAU,cAAc,GAAG,UAAU,WAAW;MAC3F,MAAM;MACN,YAAY,8BAA8B,UAAU,cAAc;MACnE;KACD,SAAS;MAAE,QAAQ;MAAG,OAAO;MAAK,MAAM;MAAK;KAC7C;eAEA,2CAAC;MAAI,KAAK;gBACR,2CAACC,qBAAU;OACP;MACQ;KACZ;;GACF;;AAIV,gCAAe;;;;ACtDf,MAAa,iBACX,WAAmB,IACnB,gBAA+BC,sCAAe,WAC3C;AACH,KAAI;AAEF,SADY,IAAI,IAAI,SAAS,CAClB,WAAWC,+CAAuB,eAAe;UACrD,MAAM;AACb,SAAO;;;;;;ACSX,MAAM,IAAI;CACR;CACA;CACA;CACD;AAMD,MAAMC,kBAA2C,EAC/C,eACA,eACI;CACJ,MAAM,EACJ,gBACA,eACA,OACA,UACA,cACA,mCACaC,8BAAc;CAC7B,MAAM,gBAAgB,iBAAiBC,8CAAeC;CAEtD,MAAM,CAAC,oBAAoB,6CAAkC,EAAE;AAC/D,4BAAgB;EACd,MAAM,eAAe,EAAE,eAAe;AACpC,yBAAsB,SAAS,KAAK,YAAY;KAC/C,IAAI;AAEP,gBAAc;AACd,SAAO,iBAAiB,UAAU,aAAa;AAE/C,eAAa;AACX,UAAO,oBAAoB,UAAU,aAAa;;IAEnD,EAAE,CAAC;CAEN,MAAM,kBAAkB,EAAE,SAAS,UAAU,GAAGC,sCAAe,QAAQ,GAAG;CAC1E,MAAM,oBAAoB;EACxBA,sCAAe,QAAQ;EACvBA,sCAAe,QAAQ;EACvBA,sCAAe,UAAU;EACzBA,sCAAe,UAAU;EAC1B;CACD,MAAM,uBAAuB,EAAE,KAAK,oBAAoB,OACtD,EAAE,SAAS,UAAU,GAAG,CACzB;CAED,MAAM,eACJ,mBAAoB,wBAAwB,qBAAqB;CAEnE,MAAM,iBAAiB;AACrB,MAAI,gBAAgB,cAAc,SAAS,UAAU,cAAc,CAEjE,QAAO,QAAQ,MAAM;MAGrB,QAAO,SAAS,OAAO;;AAI3B,QACE,4CAAC;EACC,6BACE,qCAAqCC,uBAAO,OAAO,aAAa,iBAChE,iBACD;aAED,4CAAC;GAAI,WAAU;cAEZ,eACC,2CAAC;IAAI,WAAU;cACb,2CAACC;KACC,eACE,2CAACC;MACC,WAAWA,oBAAM,UAAU;MACZ;OACf;KAEG;KACP,SAAS;MACT;KACE,GACJ,MAEJ,2CAAC;IAAc,IAAIH,sCAAe;IAAM,WAAU;cAChD,2CAACI;KAAW,MAAM;KAAU,WAAU;MAAa;KACrC;IACZ,EAEN,4CAAC;GAAI,WAAU;cACb,2CAAC;IAAc,IAAIC,sCAAe;cAChC,2CAACC;KACC,MAAK;KACL,OAAOA,mCAAW,MAAM;KACxB,MAAMA,mCAAW,KAAK;KACtB,OAAOA,mCAAW,MAAM;MACxB;KACY,EAChB,2CAAC;IAAc,IAAIN,sCAAe,QAAQ;cACvC,WACC,2CAACE,sCAAW,eAAeK,qBAAO,cAAc,GAAI,GAEpD,2CAACC;KACC,MAAK;KACL,OAAOA,mCAAW,MAAM;KACxB,OAAOA,mCAAW,MAAM;KACxB,MAAMA,mCAAW,KAAK;MACtB;KAEU;IACZ;GACF;;AAIV,+BAAe;;;;AClIf,MAAMC,WAAoC,SAAS;CACjD,UAAU;CACV,OAAO;CACP,YAAY,aAAsB,IAAI,EAAE,UAAU,CAAC;CACnD,WAAW,UAAmB,IAAI,EAAE,OAAO,CAAC;CAC5C,aAAa,IAAI;EAAE,UAAU;EAAO,OAAO;EAAW,CAAC;CACxD;AAED,MAAa,oCAAkC,CAAC,QAAQ;;;;ACMxD,MAAM,wBAAwB;AAC9B,MAAM,6BAA6B;AACnC,MAAM,oBAAoB;AAU1B,MAAMC,UAA2B,EAC/B,eACA,gBACA,OACA,UACA,cACA,uBACI;CACJ,MAAM,WAAW,cAAc,MAAiB,EAAE,SAAS;CAC3D,MAAM,EAAE,SAAS,kBAAkB,kBAAkB,MAAM;CAC3D,MAAM,WAAW,eAAe,MAAM;CAEtC,MAAM,EAAE,wBAAwB;CAEhC,MAAM,CAAC,aAAa,sCAA2B,MAAM;CACrD,MAAM,CAAC,YAAY,qCAA0B,MAAM;CAEnD,MAAM,yCAA8B,EAAE;CACtC,MAAM,4BAAiB,MAAM;CAC7B,MAAM,6BAAkB,EAAE;CAC1B,MAAM,2BAAgB,EAAE;CACxB,MAAM,mCAAwB,MAAM;CACpC,MAAM,mCAA8D,KAAK;CAEzE,MAAM,yCACH,WAAmB,oBAAmC;EACrD,MAAM,kBAAkB;EACxB,MAAM,kBAAkB,YAAY;EACpC,MAAM,cAAc;GAAE;GAAa;GAAY;AAE/C,MAAI,eAAe,QACjB,QAAO;AAGT,MAAI,oBAAoB,MAAM;AAC5B,UAAO,UAAU;AACjB,eAAY,aAAa;;AAG3B,MAAI,oBAAoB,QACtB;OACE,mBACA,YAAY,OAAO,UAAU,sBAE7B,aAAY,aAAa;;AAI7B,MAAI,gBACF,aAAY,cACV,oBAAoB,SAAS,OAAO;MAEtC,aAAY,cACV,oBAAoB,OAAO,QAAQ;AAGvC,MAAI,oBAAoB,YAAY,aAClC;OAAI,CAAC,eAAe,SAAS;AAC3B,mBAAe,UAAU;AACzB,mBAAe,UAAU,iBAAiB;AACxC,oBAAe,UAAU;AACzB,YAAO,UAAU,SAAS;AAC1B,oBAAe,UAAU;OACxB,kBAAkB;;;AAIzB,SAAO;IAET,CAAC,aAAa,WAAW,CAC1B;CAED,MAAM,4CACH,qBAA6B;EAC5B,MAAM,kBACJ,mBAAmB,SAAS,UAAU,SAAS;AACjD,WAAS,UAAU;EACnB,MAAM,cAAc,eAAe,kBAAkB,gBAAgB;AACrE,uBAAqB,YAAY,YAAY;AAC7C,sBAAoB,YAAY,WAAW;IAE7C,CAAC,eAAe,CACjB;CAED,MAAM,4CAAiC;AACrC,uBAAqB,UAAU,OAAO;AACtC,MAAI,CAAC,QAAQ,SAAS;AACpB,UAAO,4BAA4B;AACjC,sBAAkB,qBAAqB,QAAQ;AAC/C,YAAQ,UAAU;KAClB;AACF,WAAQ,UAAU;;IAEnB,CAAC,kBAAkB,CAAC;AAEvB,4BAAgB;AACd,SAAO,iBAAiB,UAAU,cAAc,EAAE,SAAS,MAAM,CAAC;AAClE,eAAa;AACX,UAAO,oBAAoB,UAAU,aAAa;;IAEnD,CAAC,aAAa,CAAC;AAElB,QACE,2CAACC;EACC,OAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;YAED,4CAACC;GAAiB,OAAO;;IACvB,2CAAC;KACC,6BACE,kDAAkD,QAAQ,GAAGC,uBAAO,UACpE,UAAUC,oBAAM,cAAc,UAAU,UACxC,aAAa,YAAY,YACzB,aAAa,sBAAsB,gBACpC;eAED,4CAAC;MACC,6BACE,mCACA,oBACA,qBACA,wBACD;iBAED,2CAACC;OACgB;OACL;QACV,EACF,2CAACC;OAA8B;OAAyB;QAAY;OAChE;MACC;IACT,2CAAC;KACC,6BACE,sBAAsBH,uBAAO,UAAU,iDACvC,sBACI,8BACA,iCACJ,wBACA,sBACI,kDACA,kDACJ,yBACA,sBACI,oDACA,mDACL;eAED,2CAACI,kDAAgB;MACb;IACN,2CAACC,oCAAS;;IACO;GACL;;AAIpB,qBAAe"}
1
+ {"version":3,"file":"index.js","names":["HeaderContext","useOutsideClick","INTERNAL_LINKS","IconButton","Search","SearchBar","Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}>","RELEASE_BRANCH","THEME","ExternalLink","InternalLink","KidStar","Member","THEME","LOGO_TYPE","TopRow: FC<TopRowProps>","HeaderContext","HamburgerContext","ExternalLink","InternalLink","ZIndex","IconButton","Hamburger","INTERNAL_LINKS","LogoHeader","HEADER_ACTION_LINKS","PillButton","CHANNELS: ChannelType[]","INTERNAL_LINKS","_","ChannelItem: FC<ChannelItemProps>","HeaderContext","ExternalLink","InternalLink","TextButton","HamburgerContext","IconButton","Hamburger","Divider","DesktopAndAbove: FC<DesktopAndAboveProps>","HeaderContext","TopRow","Divider","ZIndex","CSSTransition","Channel","RELEASE_BRANCH","forClientSideRendering","TabletAndBelow: FC<TabletAndBelowProps>","HeaderContext","ExternalLink","InternalLink","INTERNAL_LINKS","ZIndex","IconButton","Arrow","LogoHeader","EXTERNAL_LINKS","PillButton","Member","TextButton","creator: StateCreator<AuthState>","Header: FC<HeaderProps>","useOutsideClick","HeaderContext","HamburgerContext","ZIndex","THEME","DesktopAndAbove","TabletAndBelow","HamburgerMenu","TabBar"],"sources":["../../src/header/constants/animation.ts","../../src/header/components/top-row/icons.tsx","../../src/header/utils/theme.ts","../../src/header/components/top-row/index.tsx","../../src/header/components/channels/constants/index.ts","../../src/header/components/channels/index.tsx","../../src/header/components/desktop-and-above.tsx","../../src/header/utils/links.ts","../../src/header/components/tablet-and-below.tsx","../../src/header/store/auth-store.ts","../../src/header/index.tsx"],"sourcesContent":["export const ANIMATION = {\n step1Duration: 'duration-[200ms]',\n step2Delay: 'delay-[150ms]',\n step2Duration: 'duration-[50ms]',\n step3Delay: 'delay-[150ms]',\n step3Duration: 'duration-[200ms]',\n} as const\n","import { useContext, useState, type FC, type MouseEvent } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../../context'\n// constants\nimport { THEME, type Theme } from '../../../constants/theme'\nimport {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../../constants/release-branch'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// icons\nimport { Search, KidStar, Member } from '../../../icons'\n// button\nimport { IconButton } from '../../../button'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n// hooks\nimport { useOutsideClick } from '../../../hooks'\n// search bar\nimport { SearchBar } from '../../../input'\n\nconst SearchIcon = () => {\n const [isSearchOpened, setSearchOpened] = useState(false)\n const { releaseBranch, theme } = useContext(HeaderContext)\n\n const closeSearchBox = () => {\n setSearchOpened(false)\n }\n const ref = useOutsideClick(closeSearchBox)\n\n const handleClickSearch = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault()\n setSearchOpened(true)\n if (!ref.current) return\n const input = ref.current.getElementsByTagName('input')[0]\n input?.focus()\n }\n\n const onSearch = (keywords: string) => {\n setSearchOpened(false)\n if (typeof window !== 'undefined') {\n window.location.href = `${INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`\n }\n }\n\n return (\n <div className=\"relative\" ref={ref} key=\"search\">\n <IconButton\n iconComponent={Search(releaseBranch)}\n theme={theme}\n onClick={handleClickSearch}\n className={clsx(\n 'transition-opacity ease-in-out duration-[300ms]',\n isSearchOpened ? 'opacity-0 pointer-events-none' : 'opacity-100'\n )}\n />\n <div\n className={clsx(\n 'absolute right-0 -top-[8px] transition-opacity ease-in-out duration-[300ms]',\n isSearchOpened ? 'opacity-100' : 'opacity-0 pointer-events-none',\n isSearchOpened ? 'z-999' : '-z-1'\n )}\n >\n <SearchBar\n placeholder=\"關鍵字搜尋\"\n theme={theme}\n onClose={closeSearchBox}\n onSearch={onSearch}\n releaseBranch={releaseBranch}\n />\n </div>\n </div>\n )\n}\n\nexport const Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}> = ({ releaseBranch = RELEASE_BRANCH.master, theme = THEME.normal }) => {\n const { isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className=\"ml-[24px] flex flex-row gap-[16px]\">\n <SearchIcon />\n <LinkComponent to={INTERNAL_LINKS.myReading.index}>\n <IconButton iconComponent={KidStar(releaseBranch)} theme={theme} />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n <IconButton iconComponent={Member(releaseBranch)} theme={theme} />\n </LinkComponent>\n </div>\n )\n}\n","import { THEME, type Theme } from '../../constants/theme'\nimport { LOGO_TYPE } from '../../logo/constants'\n\nexport const selectLogoType = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return LOGO_TYPE.white\n default:\n return LOGO_TYPE.default\n }\n}\n\nexport const selectHeaderTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n return {\n bgColor: 'bg-photo-dark',\n topRowBgColor: 'bg-photo-dark',\n }\n case THEME.transparent:\n return {\n bgColor: 'bg-opacity-black-02',\n topRowBgColor: 'bg-transparent',\n }\n case THEME.index:\n return {\n bgColor: 'bg-gray-white',\n topRowBgColor: 'bg-gray-white',\n }\n default:\n return {\n bgColor: 'bg-gray-100',\n topRowBgColor: 'bg-gray-100',\n }\n }\n}\n\nexport const selectSloganTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return 'text-gray-white'\n default:\n return 'text-gray-800'\n }\n}\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// constants\nimport { ZIndex } from '../../constants/z-index'\nimport { ANIMATION } from '../../constants/animation'\nimport { HEADER_ACTION_LINKS } from '../../constants/action-links'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// logo\nimport { LogoHeader } from '../../../logo'\nimport type { LogoType } from '../../../logo/constants'\n// buton\nimport { IconButton, PillButton } from '../../../button'\n// components\nimport { Icons } from './icons'\nimport { Hamburger } from '../../../icons'\n// utils\nimport { selectSloganTheme } from '../../utils/theme'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\ntype TopRowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TopRow: FC<TopRowProps> = ({ topRowBgColor, logoType }) => {\n const { toUseNarrow, releaseBranch, theme, isLinkExternal } =\n useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} px-[16px] ${topRowBgColor}`,\n toUseNarrow ? 'py-[16px]' : 'py-[24px]'\n )}\n >\n {/* left group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n toUseNarrow ? 'opacity-100' : 'opacity-0',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'delay-[350ms]' : 'delay-0'\n )}\n >\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n </div>\n {/* Logo */}\n <div\n className={clsx(\n `flex items-center mr-[16px] transition-all ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'ml-[24px]' : 'ml-0',\n toUseNarrow ? 'translate-x-0' : '-translate-x-[24px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0'\n )}\n >\n <LinkComponent to={INTERNAL_LINKS.home}>\n <LogoHeader\n type={logoType}\n releaseBranch={releaseBranch}\n className={clsx(\n `transition-height ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'h-[24px]' : 'h-[32px]'\n )}\n />\n </LinkComponent>\n </div>\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step3Duration}`,\n 'flex items-center font-serif font-normal text-[14px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n selectSloganTheme(theme)\n )}\n >\n 深度 × 開放 × 非營利\n </div>\n </div>\n {/* right group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n 'flex items-center gap-[16px]',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100'\n )}\n >\n {HEADER_ACTION_LINKS.map((link) => (\n <LinkComponent to={link.to} target={link.target} key={link.label}>\n <PillButton text={link.label} theme={theme} type={link.type} />\n </LinkComponent>\n ))}\n </div>\n {/* icons */}\n <Icons releaseBranch={releaseBranch} theme={theme} />\n </div>\n </div>\n )\n}\n\nexport default TopRow\n","import { INTERNAL_LINKS } from '../../../../constants/internal-links'\nimport type { LinkTarget } from '../../../../customized-link/type'\n\ntype ChannelType = {\n label: string\n to: string\n target: LinkTarget\n}\nexport const CHANNELS: ChannelType[] = [\n {\n label: '最新',\n to: INTERNAL_LINKS.latest,\n target: '_self',\n },\n {\n label: '深度專題',\n to: INTERNAL_LINKS.topics,\n target: '_self',\n },\n {\n label: '國際兩岸',\n to: INTERNAL_LINKS.categories.world,\n target: '_self',\n },\n {\n label: '人權司法',\n to: INTERNAL_LINKS.categories.humanRights,\n target: '_self',\n },\n {\n label: '政治社會',\n to: INTERNAL_LINKS.categories.politicsAndSociety,\n target: '_self',\n },\n {\n label: '醫療健康',\n to: INTERNAL_LINKS.categories.health,\n target: '_self',\n },\n {\n label: '環境永續',\n to: INTERNAL_LINKS.categories.environment,\n target: '_self',\n },\n {\n label: '經濟產業',\n to: INTERNAL_LINKS.categories.econ,\n target: '_self',\n },\n {\n label: '文化生活',\n to: INTERNAL_LINKS.categories.culture,\n target: '_self',\n },\n {\n label: '教育校園',\n to: INTERNAL_LINKS.categories.education,\n target: '_self',\n },\n]\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// components\nimport { IconButton, TextButton } from '../../../button'\nimport { Hamburger } from '../../../icons'\nimport Divider from '../../../divider'\n// constants\nimport { CHANNELS } from './constants'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\nimport type { LinkTarget } from '../../../customized-link/type'\n// lodash\nimport map from 'lodash/map'\nconst _ = {\n map,\n}\ntype ChannelItemProps = {\n link: {\n href: string\n target: LinkTarget\n }\n label: string\n}\nconst ChannelItem: FC<ChannelItemProps> = ({\n link = { href: '', target: '_self' },\n label = '',\n}) => {\n const { theme, isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className={clsx('flex items-center', '[&>a]:no-underline')}>\n <LinkComponent to={link.href} target={link.target}>\n <TextButton\n text={label}\n size={TextButton.Size.l}\n theme={theme}\n style={TextButton.Style.dark}\n />\n </LinkComponent>\n </div>\n )\n}\n\nconst Channel = () => {\n const { releaseBranch, theme } = useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-between w-full px-[16px] py-[8px]\">\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n {_.map(CHANNELS, (channel) => {\n return (\n <ChannelItem\n key={`channel-${channel.label}`}\n label={channel.label}\n link={{\n href: channel.to,\n target: channel.target,\n }}\n />\n )\n })}\n </div>\n <Divider />\n </div>\n )\n}\n\nexport default Channel\n","import { useContext, useRef, type FC } from 'react'\nimport clsx from 'clsx'\nimport { CSSTransition } from 'react-transition-group'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { ANIMATION } from '../constants/animation'\n// compontents\nimport TopRow from './top-row'\nimport Channel from './channels'\nimport Divider from '../../divider'\n// type\nimport type { LogoType } from '../../logo/constants'\ntype DesktopAndAboveProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst DesktopAndAbove: FC<DesktopAndAboveProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const { toUseNarrow } = useContext(HeaderContext)\n const channelRef = useRef<HTMLDivElement>(null)\n return (\n <div className=\"hidden desktop:flex desktop:flex-col\">\n <TopRow topRowBgColor={topRowBgColor} logoType={logoType} />\n {/* divider */}\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step2Duration}`,\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n toUseNarrow ? 'delay-0' : `${ANIMATION.step2Delay}`\n )}\n >\n <Divider direction={Divider.Direction.horizontal} />\n </div>\n {/* channels */}\n <div className={`${ZIndex.channel}`}>\n <CSSTransition\n in={!toUseNarrow}\n nodeRef={channelRef}\n classNames={{\n enter: `opacity-0 -translate-y-full`,\n enterActive: `transition-all ease-linear ${ANIMATION.step1Duration} ${ANIMATION.step2Delay} opacity-100 translate-y-0`,\n exit: `opacity-100 translate-y-0`,\n exitActive: `transition-all ease-linear ${ANIMATION.step1Duration} -translate-y-full`,\n }}\n timeout={{ appear: 0, enter: 350, exit: 200 }}\n unmountOnExit\n >\n <div ref={channelRef}>\n <Channel />\n </div>\n </CSSTransition>\n </div>\n </div>\n )\n}\n\nexport default DesktopAndAbove\n","import {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../constants/release-branch'\nimport { forClientSideRendering } from '../../constants/request-origins'\n\nexport const checkReferrer = (\n referrer: string = '',\n releaseBranch: ReleaseBranch = RELEASE_BRANCH.master\n) => {\n try {\n const url = new URL(referrer)\n return url.origin === forClientSideRendering[releaseBranch].main\n } catch (_err) {\n return false\n }\n}\n","import { useContext, useState, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\n// logo\nimport { LogoHeader } from '../../logo'\nimport type { LogoType } from '../../logo/constants'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\n// button\nimport { PillButton, TextButton, IconButton } from '../../button'\n// icon\nimport { Arrow, Member } from '../../icons'\n// utils\nimport { checkReferrer } from '../utils/links'\n// lodash\nimport some from 'lodash/some'\nimport includes from 'lodash/includes'\nimport throttle from 'lodash/throttle'\nconst _ = {\n some,\n includes,\n throttle,\n}\n\ntype TabletAndBelowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TabletAndBelow: FC<TabletAndBelowProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const {\n isLinkExternal,\n releaseBranch,\n theme,\n pathname,\n referrerPath,\n isAuthed,\n } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n\n const [currentClientWidth, setCurrentClientWidth] = useState(0)\n useEffect(() => {\n const handleResize = _.throttle(() => {\n setCurrentClientWidth(document.body.clientWidth)\n }, 200)\n\n handleResize()\n window.addEventListener('resize', handleResize)\n\n return () => {\n window.removeEventListener('resize', handleResize)\n }\n }, [])\n\n const isOnArticlePage = _.includes(pathname, `${INTERNAL_LINKS.article}/`)\n const needPrevIconRoute = [\n INTERNAL_LINKS.account.donationHistoryPage,\n INTERNAL_LINKS.account.emailSubscription,\n INTERNAL_LINKS.myReading.savedBookmarks,\n INTERNAL_LINKS.myReading.browsingHistory,\n ]\n const isOnNeedPrevIconPage = _.some(needPrevIconRoute, (el) =>\n _.includes(pathname, el)\n )\n\n const showPrevIcon =\n isOnArticlePage || (isOnNeedPrevIconPage && currentClientWidth < 768) // only show it on mobile\n\n const gotoPrev = () => {\n if (referrerPath || checkReferrer(document.referrer, releaseBranch)) {\n // go to previous page when referer is twreporter site\n window.history.back()\n } else {\n // go to home page when referer is not twreporter site\n window.location.href = '/'\n }\n }\n\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} py-[16px] ${topRowBgColor}`,\n 'desktop:hidden'\n )}\n >\n <div className=\"flex flex-row gap-[8px]\">\n {/* pre button */}\n {showPrevIcon ? (\n <div className=\"p-[4px] -translate-x-[8px]\">\n <IconButton\n iconComponent={\n <Arrow\n direction={Arrow.Direction.left}\n releaseBranch={releaseBranch}\n />\n }\n theme={theme}\n onClick={gotoPrev}\n />\n </div>\n ) : null}\n {/* logo */}\n <LinkComponent to={INTERNAL_LINKS.home} className=\"flex items-center\">\n <LogoHeader type={logoType} className=\"h-[21px]\" />\n </LinkComponent>\n </div>\n {/* actions */}\n <div className=\"flex flex-row items-center gap-[16px]\">\n <LinkComponent to={EXTERNAL_LINKS.monthlyDonation}>\n <PillButton\n text=\"贊助\"\n theme={PillButton.Theme.normal}\n type={PillButton.Type.primary}\n style={PillButton.Style.brand}\n />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n {isAuthed ? (\n <IconButton iconComponent={Member(releaseBranch)} />\n ) : (\n <TextButton\n text=\"登入\"\n theme={TextButton.Theme.normal}\n style={TextButton.Style.dark}\n size={TextButton.Size.s}\n />\n )}\n </LinkComponent>\n </div>\n </div>\n )\n}\n\nexport default TabletAndBelow\n","import { create, type StateCreator } from 'zustand'\n\nexport type AuthState = {\n isAuthed: boolean\n token?: string\n setAuthed: (isAuthed: boolean) => void\n setToken: (token?: string) => void\n reset: () => void\n}\n\nconst creator: StateCreator<AuthState> = (set) => ({\n isAuthed: false,\n token: undefined,\n setAuthed: (isAuthed: boolean) => set({ isAuthed }),\n setToken: (token?: string) => set({ token }),\n reset: () => set({ isAuthed: false, token: undefined }),\n})\n\nexport const useAuthStore = create<AuthState>()(creator)\n","import { useRef, useState, useCallback, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n\n// constants\nimport { THEME, type Theme } from '../constants/theme'\nimport type { ReleaseBranch } from '../constants/release-branch'\nimport { ZIndex } from './constants/z-index'\n// components\nimport DesktopAndAbove from './components/desktop-and-above'\nimport TabletAndBelow from './components/tablet-and-below'\n// context\nimport {\n HeaderContext,\n HamburgerContext,\n type HamburgerContextType,\n} from './context'\n// utils\nimport { selectHeaderTheme, selectLogoType } from './utils/theme'\n// hamburger menu\nimport HamburgerMenu from '../hamburger-menu'\n// tab bar\nimport TabBar from '../tab-bar'\nimport { useAuthStore, type AuthState } from './store/auth-store'\n// hook\nimport { useOutsideClick } from '../hooks'\n\nconst HIDE_HEADER_THRESHOLD = 8\nconst TRANSFORM_HEADER_THRESHOLD = 40\nconst TRANSFORM_TIMEOUT = 800\n\ntype HeaderProps = {\n releaseBranch: ReleaseBranch\n isLinkExternal: boolean\n theme: Theme\n pathname: string\n referrerPath: string\n hamburgerContext: HamburgerContextType\n}\nconst Header: FC<HeaderProps> = ({\n releaseBranch,\n isLinkExternal,\n theme,\n pathname,\n referrerPath,\n hamburgerContext,\n}) => {\n const isAuthed = useAuthStore((s: AuthState) => s.isAuthed)\n const { bgColor, topRowBgColor } = selectHeaderTheme(theme)\n const logoType = selectLogoType(theme)\n\n const { isHamburgerMenuOpen, closeHamburgerMenu } = hamburgerContext\n\n const [toUseNarrow, setToUseNarrow] = useState(false)\n const [hideHeader, setHideHeader] = useState(false)\n\n const lastKnownPageYOffset = useRef(0)\n const ticking = useRef(false)\n const currentY = useRef(0)\n const readyY = useRef(0)\n const isTransforming = useRef(false)\n const transformTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const outsideRef = useOutsideClick(closeHamburgerMenu)\n\n const getScrollState = useCallback(\n (scrollTop: number, scrollDirection: 'up' | 'down') => {\n const isCurrentNarrow = toUseNarrow\n const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD\n const scrollState = { toUseNarrow, hideHeader }\n\n if (isTransforming.current) {\n return scrollState\n }\n\n if (scrollDirection === 'up') {\n readyY.current = scrollTop\n scrollState.hideHeader = false\n }\n\n if (scrollDirection === 'down') {\n if (\n isCurrentNarrow &&\n scrollTop - readyY.current > HIDE_HEADER_THRESHOLD\n ) {\n scrollState.hideHeader = true\n }\n }\n\n if (isCurrentNarrow) {\n scrollState.toUseNarrow =\n scrollDirection === 'down' ? true : nextToUseNarrow\n } else {\n scrollState.toUseNarrow =\n scrollDirection === 'up' ? false : nextToUseNarrow\n }\n\n if (isCurrentNarrow !== scrollState.toUseNarrow) {\n if (!transformTimer.current) {\n isTransforming.current = true\n transformTimer.current = setTimeout(() => {\n isTransforming.current = false\n readyY.current = currentY.current\n transformTimer.current = null\n }, TRANSFORM_TIMEOUT)\n }\n }\n\n return scrollState\n },\n [toUseNarrow, hideHeader]\n )\n\n const updateScrollState = useCallback(\n (currentScrollTop: number) => {\n const scrollDirection =\n currentScrollTop > currentY.current ? 'down' : 'up'\n currentY.current = currentScrollTop\n const updateState = getScrollState(currentScrollTop, scrollDirection)\n setToUseNarrow(() => updateState.toUseNarrow)\n setHideHeader(() => updateState.hideHeader)\n },\n [getScrollState]\n )\n\n const handleScroll = useCallback(() => {\n lastKnownPageYOffset.current = window.pageYOffset\n if (!ticking.current) {\n window.requestAnimationFrame(() => {\n updateScrollState(lastKnownPageYOffset.current)\n ticking.current = false\n })\n ticking.current = true\n }\n }, [updateScrollState])\n\n useEffect(() => {\n window.addEventListener('scroll', handleScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n return (\n <HeaderContext\n value={{\n releaseBranch,\n isLinkExternal,\n isAuthed,\n theme,\n pathname,\n referrerPath,\n toUseNarrow,\n hideHeader,\n }}\n >\n <HamburgerContext value={hamburgerContext}>\n <header\n className={clsx(\n `w-full top-0 transition-transform duration-300 ${bgColor} ${ZIndex.header}`,\n theme === THEME.transparent ? 'fixed' : 'sticky',\n hideHeader ? 'ease-in' : 'ease-out',\n hideHeader ? '-translate-y-full' : 'translate-y-0'\n )}\n >\n <div\n className={clsx(\n `flex flex-col mx-auto px-[24px]`,\n 'tablet:px-[32px]',\n 'desktop:px-[48px]',\n 'hd:w-[1280px] hd:px-0'\n )}\n >\n <DesktopAndAbove\n topRowBgColor={topRowBgColor}\n logoType={logoType}\n />\n <TabletAndBelow topRowBgColor={topRowBgColor} logoType={logoType} />\n </div>\n </header>\n <div\n ref={outsideRef}\n className={clsx(\n `fixed top-0 left-0 ${ZIndex.hamburger} transition-transform duration-300 ease-in-out`,\n isHamburgerMenuOpen\n ? 'translate-x-0 opacity-100'\n : '-translate-x-full opacity-100',\n 'tablet:-left-[320px]',\n isHamburgerMenuOpen\n ? 'tablet:translate-x-[320px] tablet:opacity-100'\n : 'tablet:-translate-x-[320px] tablet:opacity-100',\n 'desktop:-left-[280px]',\n isHamburgerMenuOpen\n ? 'desktop:translate-x-[280px] desktop:opacity-100'\n : 'desktop:-translate-x-[280px] desktop:opacity-100'\n )}\n >\n <HamburgerMenu />\n </div>\n <TabBar />\n </HamburgerContext>\n </HeaderContext>\n )\n}\n\nexport default Header\n"],"mappings":"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"}
@@ -3,25 +3,30 @@ import "../constants-oTHAnh6r.mjs";
3
3
  import "../constants-CBSEPx91.mjs";
4
4
  import "../paragraph-Cf9jr8RF.mjs";
5
5
  import { THEME } from "../theme-BG6yZVj-.mjs";
6
- import { icon_button_default, pill_button_default, text_button_default } from "../button-hDNHA85d.mjs";
6
+ import { icon_button_default, pill_button_default, text_button_default } from "../button-D_AWI7r9.mjs";
7
7
  import { EXTERNAL_LINKS } from "../external-links-B-A17Osq.mjs";
8
8
  import { INTERNAL_LINKS } from "../internal-links-CP3dqmrz.mjs";
9
9
  import { RELEASE_BRANCH } from "../release-branch-DNCD1uH_.mjs";
10
10
  import { forClientSideRendering } from "../request-origins-CGkNWg8R.mjs";
11
- import { external_link_default } from "../external-link-DXT5ep5-.mjs";
12
- import "../customized-link-DnaZxeKK.mjs";
13
- import "../constants-z9Q8ph_H.mjs";
14
- import { divider_default } from "../divider-CE4u6SR5.mjs";
11
+ import "../constants-Cz7n-nLz.mjs";
12
+ import { divider_default } from "../divider-CEIxmAsH.mjs";
13
+ import { external_link_default } from "../external-link-BykRRwmY.mjs";
14
+ import "../customized-link-DNKmWI0u.mjs";
15
15
  import { HamburgerContext, HeaderContext } from "../context-BgdqM3zA.mjs";
16
16
  import "../constants-5phfWHvb.mjs";
17
17
  import { Arrow, Hamburger, KidStar, Member, Search } from "../icons-I7T-auOQ.mjs";
18
18
  import { LOGO_TYPE } from "../constants-DRxdMM_X.mjs";
19
- import "../dropdown-menu-D7VNOiIl.mjs";
20
- import { ZIndex, tab_bar_default } from "../tab-bar-CdsxfUdk.mjs";
21
- import { HEADER_ACTION_LINKS, hamburger_menu_default } from "../hamburger-menu-DOrmybn_.mjs";
22
- import { logo_header_default } from "../logo-CxXblyO9.mjs";
23
- import "../theme-DQCIQh_8.mjs";
24
- import "../constants--CDeoDub.mjs";
19
+ import "../dropdown-menu-CuyS5r71.mjs";
20
+ import { HEADER_ACTION_LINKS, hamburger_menu_default } from "../hamburger-menu-Ca6QMgF9.mjs";
21
+ import { logo_header_default } from "../logo-D68VZ-fc.mjs";
22
+ import "../constants-Dfgyc0ND.mjs";
23
+ import "../theme-CkSx7UX3.mjs";
24
+ import { search_bar_default } from "../input-_Hl5B4_K.mjs";
25
+ import { ZIndex, tab_bar_default } from "../tab-bar-BqiC7-Lw.mjs";
26
+ import { useOutsideClick } from "../use-outside-click-Bz_v9VCq.mjs";
27
+ import "../hooks-DFV2v01e.mjs";
28
+ import "../theme-PhMjSVv9.mjs";
29
+ import "../constants-BYqJQzQQ.mjs";
25
30
  import { useCallback, useContext, useEffect, useRef, useState } from "react";
26
31
  import clsx from "clsx";
27
32
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -43,16 +48,50 @@ const ANIMATION = {
43
48
 
44
49
  //#endregion
45
50
  //#region src/header/components/top-row/icons.tsx
51
+ const SearchIcon = () => {
52
+ const [isSearchOpened, setSearchOpened] = useState(false);
53
+ const { releaseBranch, theme } = useContext(HeaderContext);
54
+ const closeSearchBox = () => {
55
+ setSearchOpened(false);
56
+ };
57
+ const ref = useOutsideClick(closeSearchBox);
58
+ const handleClickSearch = (e) => {
59
+ e.preventDefault();
60
+ setSearchOpened(true);
61
+ if (!ref.current) return;
62
+ ref.current.getElementsByTagName("input")[0]?.focus();
63
+ };
64
+ const onSearch = (keywords) => {
65
+ setSearchOpened(false);
66
+ if (typeof window !== "undefined") window.location.href = `${INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`;
67
+ };
68
+ return /* @__PURE__ */ jsxs("div", {
69
+ className: "relative",
70
+ ref,
71
+ children: [/* @__PURE__ */ jsx(icon_button_default, {
72
+ iconComponent: Search(releaseBranch),
73
+ theme,
74
+ onClick: handleClickSearch,
75
+ className: clsx("transition-opacity ease-in-out duration-[300ms]", isSearchOpened ? "opacity-0 pointer-events-none" : "opacity-100")
76
+ }), /* @__PURE__ */ jsx("div", {
77
+ className: clsx("absolute right-0 -top-[8px] transition-opacity ease-in-out duration-[300ms]", isSearchOpened ? "opacity-100" : "opacity-0 pointer-events-none", isSearchOpened ? "z-999" : "-z-1"),
78
+ children: /* @__PURE__ */ jsx(search_bar_default, {
79
+ placeholder: "關鍵字搜尋",
80
+ theme,
81
+ onClose: closeSearchBox,
82
+ onSearch,
83
+ releaseBranch
84
+ })
85
+ })]
86
+ }, "search");
87
+ };
46
88
  const Icons = ({ releaseBranch = RELEASE_BRANCH.master, theme = THEME.normal }) => {
47
89
  const { isLinkExternal } = useContext(HeaderContext);
48
90
  const LinkComponent = isLinkExternal ? external_link_default : internal_link_default;
49
91
  return /* @__PURE__ */ jsxs("div", {
50
92
  className: "ml-[24px] flex flex-row gap-[16px]",
51
93
  children: [
52
- /* @__PURE__ */ jsx(icon_button_default, {
53
- iconComponent: Search(releaseBranch),
54
- theme
55
- }),
94
+ /* @__PURE__ */ jsx(SearchIcon, {}),
56
95
  /* @__PURE__ */ jsx(LinkComponent, {
57
96
  to: INTERNAL_LINKS.myReading.index,
58
97
  children: /* @__PURE__ */ jsx(icon_button_default, {
@@ -425,7 +464,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
425
464
  const isAuthed = useAuthStore((s) => s.isAuthed);
426
465
  const { bgColor, topRowBgColor } = selectHeaderTheme(theme);
427
466
  const logoType = selectLogoType(theme);
428
- const { isHamburgerMenuOpen } = hamburgerContext;
467
+ const { isHamburgerMenuOpen, closeHamburgerMenu } = hamburgerContext;
429
468
  const [toUseNarrow, setToUseNarrow] = useState(false);
430
469
  const [hideHeader, setHideHeader] = useState(false);
431
470
  const lastKnownPageYOffset = useRef(0);
@@ -434,6 +473,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
434
473
  const readyY = useRef(0);
435
474
  const isTransforming = useRef(false);
436
475
  const transformTimer = useRef(null);
476
+ const outsideRef = useOutsideClick(closeHamburgerMenu);
437
477
  const getScrollState = useCallback((scrollTop, scrollDirection) => {
438
478
  const isCurrentNarrow = toUseNarrow;
439
479
  const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD;
@@ -514,6 +554,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
514
554
  })
515
555
  }),
516
556
  /* @__PURE__ */ jsx("div", {
557
+ ref: outsideRef,
517
558
  className: clsx(`fixed top-0 left-0 ${ZIndex.hamburger} transition-transform duration-300 ease-in-out`, isHamburgerMenuOpen ? "translate-x-0 opacity-100" : "-translate-x-full opacity-100", "tablet:-left-[320px]", isHamburgerMenuOpen ? "tablet:translate-x-[320px] tablet:opacity-100" : "tablet:-translate-x-[320px] tablet:opacity-100", "desktop:-left-[280px]", isHamburgerMenuOpen ? "desktop:translate-x-[280px] desktop:opacity-100" : "desktop:-translate-x-[280px] desktop:opacity-100"),
518
559
  children: /* @__PURE__ */ jsx(hamburger_menu_default, {})
519
560
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}>","ExternalLink","InternalLink","IconButton","TopRow: FC<TopRowProps>","ExternalLink","InternalLink","IconButton","LogoHeader","PillButton","CHANNELS: ChannelType[]","_","ChannelItem: FC<ChannelItemProps>","ExternalLink","InternalLink","TextButton","IconButton","Divider","DesktopAndAbove: FC<DesktopAndAboveProps>","TopRow","Divider","Channel","TabletAndBelow: FC<TabletAndBelowProps>","ExternalLink","InternalLink","IconButton","LogoHeader","PillButton","TextButton","creator: StateCreator<AuthState>","Header: FC<HeaderProps>","DesktopAndAbove","TabletAndBelow","HamburgerMenu","TabBar"],"sources":["../../src/header/constants/animation.ts","../../src/header/components/top-row/icons.tsx","../../src/header/utils/theme.ts","../../src/header/components/top-row/index.tsx","../../src/header/components/channels/constants/index.ts","../../src/header/components/channels/index.tsx","../../src/header/components/desktop-and-above.tsx","../../src/header/utils/links.ts","../../src/header/components/tablet-and-below.tsx","../../src/header/store/auth-store.ts","../../src/header/index.tsx"],"sourcesContent":["export const ANIMATION = {\n step1Duration: 'duration-[200ms]',\n step2Delay: 'delay-[150ms]',\n step2Duration: 'duration-[50ms]',\n step3Delay: 'delay-[150ms]',\n step3Duration: 'duration-[200ms]',\n} as const\n","import { useContext, type FC } from 'react'\n// context\nimport { HeaderContext } from '../../context'\n// constants\nimport { THEME, type Theme } from '../../../constants/theme'\nimport {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../../constants/release-branch'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// icons\nimport { Search, KidStar, Member } from '../../../icons'\n// button\nimport { IconButton } from '../../../button'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\nexport const Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}> = ({ releaseBranch = RELEASE_BRANCH.master, theme = THEME.normal }) => {\n const { isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className=\"ml-[24px] flex flex-row gap-[16px]\">\n <IconButton iconComponent={Search(releaseBranch)} theme={theme} />\n <LinkComponent to={INTERNAL_LINKS.myReading.index}>\n <IconButton iconComponent={KidStar(releaseBranch)} theme={theme} />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n <IconButton iconComponent={Member(releaseBranch)} theme={theme} />\n </LinkComponent>\n </div>\n )\n}\n","import { THEME, type Theme } from '../../constants/theme'\nimport { LOGO_TYPE } from '../../logo/constants'\n\nexport const selectLogoType = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return LOGO_TYPE.white\n default:\n return LOGO_TYPE.default\n }\n}\n\nexport const selectHeaderTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n return {\n bgColor: 'bg-photo-dark',\n topRowBgColor: 'bg-photo-dark',\n }\n case THEME.transparent:\n return {\n bgColor: 'bg-opacity-black-02',\n topRowBgColor: 'bg-transparent',\n }\n case THEME.index:\n return {\n bgColor: 'bg-gray-white',\n topRowBgColor: 'bg-gray-white',\n }\n default:\n return {\n bgColor: 'bg-gray-100',\n topRowBgColor: 'bg-gray-100',\n }\n }\n}\n\nexport const selectSloganTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return 'text-gray-white'\n default:\n return 'text-gray-800'\n }\n}\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// constants\nimport { ZIndex } from '../../constants/z-index'\nimport { ANIMATION } from '../../constants/animation'\nimport { HEADER_ACTION_LINKS } from '../../constants/action-links'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// logo\nimport { LogoHeader } from '../../../logo'\nimport type { LogoType } from '../../../logo/constants'\n// buton\nimport { IconButton, PillButton } from '../../../button'\n// components\nimport { Icons } from './icons'\nimport { Hamburger } from '../../../icons'\n// utils\nimport { selectSloganTheme } from '../../utils/theme'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\ntype TopRowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TopRow: FC<TopRowProps> = ({ topRowBgColor, logoType }) => {\n const { toUseNarrow, releaseBranch, theme, isLinkExternal } =\n useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} px-[16px] ${topRowBgColor}`,\n toUseNarrow ? 'py-[16px]' : 'py-[24px]'\n )}\n >\n {/* left group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n toUseNarrow ? 'opacity-100' : 'opacity-0',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'delay-[350ms]' : 'delay-0'\n )}\n >\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n </div>\n {/* Logo */}\n <div\n className={clsx(\n `flex items-center mr-[16px] transition-all ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'ml-[24px]' : 'ml-0',\n toUseNarrow ? 'translate-x-0' : '-translate-x-[24px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0'\n )}\n >\n <LinkComponent to={INTERNAL_LINKS.home}>\n <LogoHeader\n type={logoType}\n releaseBranch={releaseBranch}\n className={clsx(\n `transition-height ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'h-[24px]' : 'h-[32px]'\n )}\n />\n </LinkComponent>\n </div>\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step3Duration}`,\n 'flex items-center font-serif font-normal text-[14px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n selectSloganTheme(theme)\n )}\n >\n 深度 × 開放 × 非營利\n </div>\n </div>\n {/* right group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n 'flex items-center gap-[16px]',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100'\n )}\n >\n {HEADER_ACTION_LINKS.map((link) => (\n <LinkComponent to={link.to} target={link.target} key={link.label}>\n <PillButton text={link.label} theme={theme} type={link.type} />\n </LinkComponent>\n ))}\n </div>\n {/* icons */}\n <Icons releaseBranch={releaseBranch} theme={theme} />\n </div>\n </div>\n )\n}\n\nexport default TopRow\n","import { INTERNAL_LINKS } from '../../../../constants/internal-links'\nimport type { LinkTarget } from '../../../../customized-link/type'\n\ntype ChannelType = {\n label: string\n to: string\n target: LinkTarget\n}\nexport const CHANNELS: ChannelType[] = [\n {\n label: '最新',\n to: INTERNAL_LINKS.latest,\n target: '_self',\n },\n {\n label: '深度專題',\n to: INTERNAL_LINKS.topics,\n target: '_self',\n },\n {\n label: '國際兩岸',\n to: INTERNAL_LINKS.categories.world,\n target: '_self',\n },\n {\n label: '人權司法',\n to: INTERNAL_LINKS.categories.humanRights,\n target: '_self',\n },\n {\n label: '政治社會',\n to: INTERNAL_LINKS.categories.politicsAndSociety,\n target: '_self',\n },\n {\n label: '醫療健康',\n to: INTERNAL_LINKS.categories.health,\n target: '_self',\n },\n {\n label: '環境永續',\n to: INTERNAL_LINKS.categories.environment,\n target: '_self',\n },\n {\n label: '經濟產業',\n to: INTERNAL_LINKS.categories.econ,\n target: '_self',\n },\n {\n label: '文化生活',\n to: INTERNAL_LINKS.categories.culture,\n target: '_self',\n },\n {\n label: '教育校園',\n to: INTERNAL_LINKS.categories.education,\n target: '_self',\n },\n]\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// components\nimport { IconButton, TextButton } from '../../../button'\nimport { Hamburger } from '../../../icons'\nimport Divider from '../../../divider'\n// constants\nimport { CHANNELS } from './constants'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\nimport type { LinkTarget } from '../../../customized-link/type'\n// lodash\nimport map from 'lodash/map'\nconst _ = {\n map,\n}\ntype ChannelItemProps = {\n link: {\n href: string\n target: LinkTarget\n }\n label: string\n}\nconst ChannelItem: FC<ChannelItemProps> = ({\n link = { href: '', target: '_self' },\n label = '',\n}) => {\n const { theme, isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className={clsx('flex items-center', '[&>a]:no-underline')}>\n <LinkComponent to={link.href} target={link.target}>\n <TextButton\n text={label}\n size={TextButton.Size.l}\n theme={theme}\n style={TextButton.Style.dark}\n />\n </LinkComponent>\n </div>\n )\n}\n\nconst Channel = () => {\n const { releaseBranch, theme } = useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-between w-full px-[16px] py-[8px]\">\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n {_.map(CHANNELS, (channel) => {\n return (\n <ChannelItem\n key={`channel-${channel.label}`}\n label={channel.label}\n link={{\n href: channel.to,\n target: channel.target,\n }}\n />\n )\n })}\n </div>\n <Divider />\n </div>\n )\n}\n\nexport default Channel\n","import { useContext, useRef, type FC } from 'react'\nimport clsx from 'clsx'\nimport { CSSTransition } from 'react-transition-group'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { ANIMATION } from '../constants/animation'\n// compontents\nimport TopRow from './top-row'\nimport Channel from './channels'\nimport Divider from '../../divider'\n// type\nimport type { LogoType } from '../../logo/constants'\ntype DesktopAndAboveProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst DesktopAndAbove: FC<DesktopAndAboveProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const { toUseNarrow } = useContext(HeaderContext)\n const channelRef = useRef<HTMLDivElement>(null)\n return (\n <div className=\"hidden desktop:flex desktop:flex-col\">\n <TopRow topRowBgColor={topRowBgColor} logoType={logoType} />\n {/* divider */}\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step2Duration}`,\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n toUseNarrow ? 'delay-0' : `${ANIMATION.step2Delay}`\n )}\n >\n <Divider direction={Divider.Direction.horizontal} />\n </div>\n {/* channels */}\n <div className={`${ZIndex.channel}`}>\n <CSSTransition\n in={!toUseNarrow}\n nodeRef={channelRef}\n classNames={{\n enter: `opacity-0 -translate-y-full`,\n enterActive: `transition-all ease-linear ${ANIMATION.step1Duration} ${ANIMATION.step2Delay} opacity-100 translate-y-0`,\n exit: `opacity-100 translate-y-0`,\n exitActive: `transition-all ease-linear ${ANIMATION.step1Duration} -translate-y-full`,\n }}\n timeout={{ appear: 0, enter: 350, exit: 200 }}\n unmountOnExit\n >\n <div ref={channelRef}>\n <Channel />\n </div>\n </CSSTransition>\n </div>\n </div>\n )\n}\n\nexport default DesktopAndAbove\n","import {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../constants/release-branch'\nimport { forClientSideRendering } from '../../constants/request-origins'\n\nexport const checkReferrer = (\n referrer: string = '',\n releaseBranch: ReleaseBranch = RELEASE_BRANCH.master\n) => {\n try {\n const url = new URL(referrer)\n return url.origin === forClientSideRendering[releaseBranch].main\n } catch (_err) {\n return false\n }\n}\n","import { useContext, useState, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\n// logo\nimport { LogoHeader } from '../../logo'\nimport type { LogoType } from '../../logo/constants'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\n// button\nimport { PillButton, TextButton, IconButton } from '../../button'\n// icon\nimport { Arrow, Member } from '../../icons'\n// utils\nimport { checkReferrer } from '../utils/links'\n// lodash\nimport some from 'lodash/some'\nimport includes from 'lodash/includes'\nimport throttle from 'lodash/throttle'\nconst _ = {\n some,\n includes,\n throttle,\n}\n\ntype TabletAndBelowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TabletAndBelow: FC<TabletAndBelowProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const {\n isLinkExternal,\n releaseBranch,\n theme,\n pathname,\n referrerPath,\n isAuthed,\n } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n\n const [currentClientWidth, setCurrentClientWidth] = useState(0)\n useEffect(() => {\n const handleResize = _.throttle(() => {\n setCurrentClientWidth(document.body.clientWidth)\n }, 200)\n\n handleResize()\n window.addEventListener('resize', handleResize)\n\n return () => {\n window.removeEventListener('resize', handleResize)\n }\n }, [])\n\n const isOnArticlePage = _.includes(pathname, `${INTERNAL_LINKS.article}/`)\n const needPrevIconRoute = [\n INTERNAL_LINKS.account.donationHistoryPage,\n INTERNAL_LINKS.account.emailSubscription,\n INTERNAL_LINKS.myReading.savedBookmarks,\n INTERNAL_LINKS.myReading.browsingHistory,\n ]\n const isOnNeedPrevIconPage = _.some(needPrevIconRoute, (el) =>\n _.includes(pathname, el)\n )\n\n const showPrevIcon =\n isOnArticlePage || (isOnNeedPrevIconPage && currentClientWidth < 768) // only show it on mobile\n\n const gotoPrev = () => {\n if (referrerPath || checkReferrer(document.referrer, releaseBranch)) {\n // go to previous page when referer is twreporter site\n window.history.back()\n } else {\n // go to home page when referer is not twreporter site\n window.location.href = '/'\n }\n }\n\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} py-[16px] ${topRowBgColor}`,\n 'desktop:hidden'\n )}\n >\n <div className=\"flex flex-row gap-[8px]\">\n {/* pre button */}\n {showPrevIcon ? (\n <div className=\"p-[4px] -translate-x-[8px]\">\n <IconButton\n iconComponent={\n <Arrow\n direction={Arrow.Direction.left}\n releaseBranch={releaseBranch}\n />\n }\n theme={theme}\n onClick={gotoPrev}\n />\n </div>\n ) : null}\n {/* logo */}\n <LinkComponent to={INTERNAL_LINKS.home} className=\"flex items-center\">\n <LogoHeader type={logoType} className=\"h-[21px]\" />\n </LinkComponent>\n </div>\n {/* actions */}\n <div className=\"flex flex-row items-center gap-[16px]\">\n <LinkComponent to={EXTERNAL_LINKS.monthlyDonation}>\n <PillButton\n text=\"贊助\"\n theme={PillButton.Theme.normal}\n type={PillButton.Type.primary}\n style={PillButton.Style.brand}\n />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n {isAuthed ? (\n <IconButton iconComponent={Member(releaseBranch)} />\n ) : (\n <TextButton\n text=\"登入\"\n theme={TextButton.Theme.normal}\n style={TextButton.Style.dark}\n size={TextButton.Size.s}\n />\n )}\n </LinkComponent>\n </div>\n </div>\n )\n}\n\nexport default TabletAndBelow\n","import { create, type StateCreator } from 'zustand'\n\nexport type AuthState = {\n isAuthed: boolean\n token?: string\n setAuthed: (isAuthed: boolean) => void\n setToken: (token?: string) => void\n reset: () => void\n}\n\nconst creator: StateCreator<AuthState> = (set) => ({\n isAuthed: false,\n token: undefined,\n setAuthed: (isAuthed: boolean) => set({ isAuthed }),\n setToken: (token?: string) => set({ token }),\n reset: () => set({ isAuthed: false, token: undefined }),\n})\n\nexport const useAuthStore = create<AuthState>()(creator)\n","import { useRef, useState, useCallback, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n\n// constants\nimport { THEME, type Theme } from '../constants/theme'\nimport type { ReleaseBranch } from '../constants/release-branch'\nimport { ZIndex } from './constants/z-index'\n// components\nimport DesktopAndAbove from './components/desktop-and-above'\nimport TabletAndBelow from './components/tablet-and-below'\n// context\nimport {\n HeaderContext,\n HamburgerContext,\n type HamburgerContextType,\n} from './context'\n// utils\nimport { selectHeaderTheme, selectLogoType } from './utils/theme'\n// hamburger menu\nimport HamburgerMenu from '../hamburger-menu'\n// tab bar\nimport TabBar from '../tab-bar'\nimport { useAuthStore, type AuthState } from './store/auth-store'\n\nconst HIDE_HEADER_THRESHOLD = 8\nconst TRANSFORM_HEADER_THRESHOLD = 40\nconst TRANSFORM_TIMEOUT = 800\n\ntype HeaderProps = {\n releaseBranch: ReleaseBranch\n isLinkExternal: boolean\n theme: Theme\n pathname: string\n referrerPath: string\n hamburgerContext: HamburgerContextType\n}\nconst Header: FC<HeaderProps> = ({\n releaseBranch,\n isLinkExternal,\n theme,\n pathname,\n referrerPath,\n hamburgerContext,\n}) => {\n const isAuthed = useAuthStore((s: AuthState) => s.isAuthed)\n const { bgColor, topRowBgColor } = selectHeaderTheme(theme)\n const logoType = selectLogoType(theme)\n\n const { isHamburgerMenuOpen } = hamburgerContext\n\n const [toUseNarrow, setToUseNarrow] = useState(false)\n const [hideHeader, setHideHeader] = useState(false)\n\n const lastKnownPageYOffset = useRef(0)\n const ticking = useRef(false)\n const currentY = useRef(0)\n const readyY = useRef(0)\n const isTransforming = useRef(false)\n const transformTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const getScrollState = useCallback(\n (scrollTop: number, scrollDirection: 'up' | 'down') => {\n const isCurrentNarrow = toUseNarrow\n const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD\n const scrollState = { toUseNarrow, hideHeader }\n\n if (isTransforming.current) {\n return scrollState\n }\n\n if (scrollDirection === 'up') {\n readyY.current = scrollTop\n scrollState.hideHeader = false\n }\n\n if (scrollDirection === 'down') {\n if (\n isCurrentNarrow &&\n scrollTop - readyY.current > HIDE_HEADER_THRESHOLD\n ) {\n scrollState.hideHeader = true\n }\n }\n\n if (isCurrentNarrow) {\n scrollState.toUseNarrow =\n scrollDirection === 'down' ? true : nextToUseNarrow\n } else {\n scrollState.toUseNarrow =\n scrollDirection === 'up' ? false : nextToUseNarrow\n }\n\n if (isCurrentNarrow !== scrollState.toUseNarrow) {\n if (!transformTimer.current) {\n isTransforming.current = true\n transformTimer.current = setTimeout(() => {\n isTransforming.current = false\n readyY.current = currentY.current\n transformTimer.current = null\n }, TRANSFORM_TIMEOUT)\n }\n }\n\n return scrollState\n },\n [toUseNarrow, hideHeader]\n )\n\n const updateScrollState = useCallback(\n (currentScrollTop: number) => {\n const scrollDirection =\n currentScrollTop > currentY.current ? 'down' : 'up'\n currentY.current = currentScrollTop\n const updateState = getScrollState(currentScrollTop, scrollDirection)\n setToUseNarrow(() => updateState.toUseNarrow)\n setHideHeader(() => updateState.hideHeader)\n },\n [getScrollState]\n )\n\n const handleScroll = useCallback(() => {\n lastKnownPageYOffset.current = window.pageYOffset\n if (!ticking.current) {\n window.requestAnimationFrame(() => {\n updateScrollState(lastKnownPageYOffset.current)\n ticking.current = false\n })\n ticking.current = true\n }\n }, [updateScrollState])\n\n useEffect(() => {\n window.addEventListener('scroll', handleScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n return (\n <HeaderContext\n value={{\n releaseBranch,\n isLinkExternal,\n isAuthed,\n theme,\n pathname,\n referrerPath,\n toUseNarrow,\n hideHeader,\n }}\n >\n <HamburgerContext value={hamburgerContext}>\n <header\n className={clsx(\n `w-full top-0 transition-transform duration-300 ${bgColor} ${ZIndex.header}`,\n theme === THEME.transparent ? 'fixed' : 'sticky',\n hideHeader ? 'ease-in' : 'ease-out',\n hideHeader ? '-translate-y-full' : 'translate-y-0'\n )}\n >\n <div\n className={clsx(\n `flex flex-col mx-auto px-[24px]`,\n 'tablet:px-[32px]',\n 'desktop:px-[48px]',\n 'hd:w-[1280px] hd:px-0'\n )}\n >\n <DesktopAndAbove\n topRowBgColor={topRowBgColor}\n logoType={logoType}\n />\n <TabletAndBelow topRowBgColor={topRowBgColor} logoType={logoType} />\n </div>\n </header>\n <div\n className={clsx(\n `fixed top-0 left-0 ${ZIndex.hamburger} transition-transform duration-300 ease-in-out`,\n isHamburgerMenuOpen\n ? 'translate-x-0 opacity-100'\n : '-translate-x-full opacity-100',\n 'tablet:-left-[320px]',\n isHamburgerMenuOpen\n ? 'tablet:translate-x-[320px] tablet:opacity-100'\n : 'tablet:-translate-x-[320px] tablet:opacity-100',\n 'desktop:-left-[280px]',\n isHamburgerMenuOpen\n ? 'desktop:translate-x-[280px] desktop:opacity-100'\n : 'desktop:-translate-x-[280px] desktop:opacity-100'\n )}\n >\n <HamburgerMenu />\n </div>\n <TabBar />\n </HamburgerContext>\n </HeaderContext>\n )\n}\n\nexport default Header\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["IconButton","SearchBar","Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}>","ExternalLink","InternalLink","TopRow: FC<TopRowProps>","ExternalLink","InternalLink","IconButton","LogoHeader","PillButton","CHANNELS: ChannelType[]","_","ChannelItem: FC<ChannelItemProps>","ExternalLink","InternalLink","TextButton","IconButton","Divider","DesktopAndAbove: FC<DesktopAndAboveProps>","TopRow","Divider","Channel","TabletAndBelow: FC<TabletAndBelowProps>","ExternalLink","InternalLink","IconButton","LogoHeader","PillButton","TextButton","creator: StateCreator<AuthState>","Header: FC<HeaderProps>","DesktopAndAbove","TabletAndBelow","HamburgerMenu","TabBar"],"sources":["../../src/header/constants/animation.ts","../../src/header/components/top-row/icons.tsx","../../src/header/utils/theme.ts","../../src/header/components/top-row/index.tsx","../../src/header/components/channels/constants/index.ts","../../src/header/components/channels/index.tsx","../../src/header/components/desktop-and-above.tsx","../../src/header/utils/links.ts","../../src/header/components/tablet-and-below.tsx","../../src/header/store/auth-store.ts","../../src/header/index.tsx"],"sourcesContent":["export const ANIMATION = {\n step1Duration: 'duration-[200ms]',\n step2Delay: 'delay-[150ms]',\n step2Duration: 'duration-[50ms]',\n step3Delay: 'delay-[150ms]',\n step3Duration: 'duration-[200ms]',\n} as const\n","import { useContext, useState, type FC, type MouseEvent } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../../context'\n// constants\nimport { THEME, type Theme } from '../../../constants/theme'\nimport {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../../constants/release-branch'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// icons\nimport { Search, KidStar, Member } from '../../../icons'\n// button\nimport { IconButton } from '../../../button'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n// hooks\nimport { useOutsideClick } from '../../../hooks'\n// search bar\nimport { SearchBar } from '../../../input'\n\nconst SearchIcon = () => {\n const [isSearchOpened, setSearchOpened] = useState(false)\n const { releaseBranch, theme } = useContext(HeaderContext)\n\n const closeSearchBox = () => {\n setSearchOpened(false)\n }\n const ref = useOutsideClick(closeSearchBox)\n\n const handleClickSearch = (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault()\n setSearchOpened(true)\n if (!ref.current) return\n const input = ref.current.getElementsByTagName('input')[0]\n input?.focus()\n }\n\n const onSearch = (keywords: string) => {\n setSearchOpened(false)\n if (typeof window !== 'undefined') {\n window.location.href = `${INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`\n }\n }\n\n return (\n <div className=\"relative\" ref={ref} key=\"search\">\n <IconButton\n iconComponent={Search(releaseBranch)}\n theme={theme}\n onClick={handleClickSearch}\n className={clsx(\n 'transition-opacity ease-in-out duration-[300ms]',\n isSearchOpened ? 'opacity-0 pointer-events-none' : 'opacity-100'\n )}\n />\n <div\n className={clsx(\n 'absolute right-0 -top-[8px] transition-opacity ease-in-out duration-[300ms]',\n isSearchOpened ? 'opacity-100' : 'opacity-0 pointer-events-none',\n isSearchOpened ? 'z-999' : '-z-1'\n )}\n >\n <SearchBar\n placeholder=\"關鍵字搜尋\"\n theme={theme}\n onClose={closeSearchBox}\n onSearch={onSearch}\n releaseBranch={releaseBranch}\n />\n </div>\n </div>\n )\n}\n\nexport const Icons: FC<{\n releaseBranch?: ReleaseBranch\n theme?: Theme\n}> = ({ releaseBranch = RELEASE_BRANCH.master, theme = THEME.normal }) => {\n const { isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className=\"ml-[24px] flex flex-row gap-[16px]\">\n <SearchIcon />\n <LinkComponent to={INTERNAL_LINKS.myReading.index}>\n <IconButton iconComponent={KidStar(releaseBranch)} theme={theme} />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n <IconButton iconComponent={Member(releaseBranch)} theme={theme} />\n </LinkComponent>\n </div>\n )\n}\n","import { THEME, type Theme } from '../../constants/theme'\nimport { LOGO_TYPE } from '../../logo/constants'\n\nexport const selectLogoType = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return LOGO_TYPE.white\n default:\n return LOGO_TYPE.default\n }\n}\n\nexport const selectHeaderTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n return {\n bgColor: 'bg-photo-dark',\n topRowBgColor: 'bg-photo-dark',\n }\n case THEME.transparent:\n return {\n bgColor: 'bg-opacity-black-02',\n topRowBgColor: 'bg-transparent',\n }\n case THEME.index:\n return {\n bgColor: 'bg-gray-white',\n topRowBgColor: 'bg-gray-white',\n }\n default:\n return {\n bgColor: 'bg-gray-100',\n topRowBgColor: 'bg-gray-100',\n }\n }\n}\n\nexport const selectSloganTheme = (theme: Theme) => {\n switch (theme) {\n case THEME.photography:\n case THEME.transparent:\n return 'text-gray-white'\n default:\n return 'text-gray-800'\n }\n}\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// constants\nimport { ZIndex } from '../../constants/z-index'\nimport { ANIMATION } from '../../constants/animation'\nimport { HEADER_ACTION_LINKS } from '../../constants/action-links'\nimport { INTERNAL_LINKS } from '../../../constants/internal-links'\n// logo\nimport { LogoHeader } from '../../../logo'\nimport type { LogoType } from '../../../logo/constants'\n// buton\nimport { IconButton, PillButton } from '../../../button'\n// components\nimport { Icons } from './icons'\nimport { Hamburger } from '../../../icons'\n// utils\nimport { selectSloganTheme } from '../../utils/theme'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\n\ntype TopRowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TopRow: FC<TopRowProps> = ({ topRowBgColor, logoType }) => {\n const { toUseNarrow, releaseBranch, theme, isLinkExternal } =\n useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} px-[16px] ${topRowBgColor}`,\n toUseNarrow ? 'py-[16px]' : 'py-[24px]'\n )}\n >\n {/* left group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n toUseNarrow ? 'opacity-100' : 'opacity-0',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'delay-[350ms]' : 'delay-0'\n )}\n >\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n </div>\n {/* Logo */}\n <div\n className={clsx(\n `flex items-center mr-[16px] transition-all ${ANIMATION.step3Duration}`,\n toUseNarrow ? 'ml-[24px]' : 'ml-0',\n toUseNarrow ? 'translate-x-0' : '-translate-x-[24px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0'\n )}\n >\n <LinkComponent to={INTERNAL_LINKS.home}>\n <LogoHeader\n type={logoType}\n releaseBranch={releaseBranch}\n className={clsx(\n `transition-height ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'h-[24px]' : 'h-[32px]'\n )}\n />\n </LinkComponent>\n </div>\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step3Duration}`,\n 'flex items-center font-serif font-normal text-[14px]',\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n selectSloganTheme(theme)\n )}\n >\n 深度 × 開放 × 非營利\n </div>\n </div>\n {/* right group */}\n <div className=\"flex items-center\">\n <div\n className={clsx(\n 'flex items-center gap-[16px]',\n `transition-opacity ${ANIMATION.step3Duration}`,\n toUseNarrow ? `${ANIMATION.step3Delay}` : 'delay-0',\n toUseNarrow ? 'pointer-events-none' : 'pointer-events-auto',\n toUseNarrow ? 'opacity-0' : 'opacity-100'\n )}\n >\n {HEADER_ACTION_LINKS.map((link) => (\n <LinkComponent to={link.to} target={link.target} key={link.label}>\n <PillButton text={link.label} theme={theme} type={link.type} />\n </LinkComponent>\n ))}\n </div>\n {/* icons */}\n <Icons releaseBranch={releaseBranch} theme={theme} />\n </div>\n </div>\n )\n}\n\nexport default TopRow\n","import { INTERNAL_LINKS } from '../../../../constants/internal-links'\nimport type { LinkTarget } from '../../../../customized-link/type'\n\ntype ChannelType = {\n label: string\n to: string\n target: LinkTarget\n}\nexport const CHANNELS: ChannelType[] = [\n {\n label: '最新',\n to: INTERNAL_LINKS.latest,\n target: '_self',\n },\n {\n label: '深度專題',\n to: INTERNAL_LINKS.topics,\n target: '_self',\n },\n {\n label: '國際兩岸',\n to: INTERNAL_LINKS.categories.world,\n target: '_self',\n },\n {\n label: '人權司法',\n to: INTERNAL_LINKS.categories.humanRights,\n target: '_self',\n },\n {\n label: '政治社會',\n to: INTERNAL_LINKS.categories.politicsAndSociety,\n target: '_self',\n },\n {\n label: '醫療健康',\n to: INTERNAL_LINKS.categories.health,\n target: '_self',\n },\n {\n label: '環境永續',\n to: INTERNAL_LINKS.categories.environment,\n target: '_self',\n },\n {\n label: '經濟產業',\n to: INTERNAL_LINKS.categories.econ,\n target: '_self',\n },\n {\n label: '文化生活',\n to: INTERNAL_LINKS.categories.culture,\n target: '_self',\n },\n {\n label: '教育校園',\n to: INTERNAL_LINKS.categories.education,\n target: '_self',\n },\n]\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../../context'\n// components\nimport { IconButton, TextButton } from '../../../button'\nimport { Hamburger } from '../../../icons'\nimport Divider from '../../../divider'\n// constants\nimport { CHANNELS } from './constants'\n// link\nimport { ExternalLink, InternalLink } from '../../../customized-link'\nimport type { LinkTarget } from '../../../customized-link/type'\n// lodash\nimport map from 'lodash/map'\nconst _ = {\n map,\n}\ntype ChannelItemProps = {\n link: {\n href: string\n target: LinkTarget\n }\n label: string\n}\nconst ChannelItem: FC<ChannelItemProps> = ({\n link = { href: '', target: '_self' },\n label = '',\n}) => {\n const { theme, isLinkExternal } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <div className={clsx('flex items-center', '[&>a]:no-underline')}>\n <LinkComponent to={link.href} target={link.target}>\n <TextButton\n text={label}\n size={TextButton.Size.l}\n theme={theme}\n style={TextButton.Style.dark}\n />\n </LinkComponent>\n </div>\n )\n}\n\nconst Channel = () => {\n const { releaseBranch, theme } = useContext(HeaderContext)\n const { toggleHamburger } = useContext(HamburgerContext)\n return (\n <div className=\"flex flex-col items-center\">\n <div className=\"flex items-center justify-between w-full px-[16px] py-[8px]\">\n <IconButton\n iconComponent={Hamburger(releaseBranch)}\n theme={theme}\n onClick={toggleHamburger}\n />\n {_.map(CHANNELS, (channel) => {\n return (\n <ChannelItem\n key={`channel-${channel.label}`}\n label={channel.label}\n link={{\n href: channel.to,\n target: channel.target,\n }}\n />\n )\n })}\n </div>\n <Divider />\n </div>\n )\n}\n\nexport default Channel\n","import { useContext, useRef, type FC } from 'react'\nimport clsx from 'clsx'\nimport { CSSTransition } from 'react-transition-group'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { ANIMATION } from '../constants/animation'\n// compontents\nimport TopRow from './top-row'\nimport Channel from './channels'\nimport Divider from '../../divider'\n// type\nimport type { LogoType } from '../../logo/constants'\ntype DesktopAndAboveProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst DesktopAndAbove: FC<DesktopAndAboveProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const { toUseNarrow } = useContext(HeaderContext)\n const channelRef = useRef<HTMLDivElement>(null)\n return (\n <div className=\"hidden desktop:flex desktop:flex-col\">\n <TopRow topRowBgColor={topRowBgColor} logoType={logoType} />\n {/* divider */}\n <div\n className={clsx(\n `transition-opacity ${ANIMATION.step2Duration}`,\n toUseNarrow ? 'opacity-0' : 'opacity-100',\n toUseNarrow ? 'delay-0' : `${ANIMATION.step2Delay}`\n )}\n >\n <Divider direction={Divider.Direction.horizontal} />\n </div>\n {/* channels */}\n <div className={`${ZIndex.channel}`}>\n <CSSTransition\n in={!toUseNarrow}\n nodeRef={channelRef}\n classNames={{\n enter: `opacity-0 -translate-y-full`,\n enterActive: `transition-all ease-linear ${ANIMATION.step1Duration} ${ANIMATION.step2Delay} opacity-100 translate-y-0`,\n exit: `opacity-100 translate-y-0`,\n exitActive: `transition-all ease-linear ${ANIMATION.step1Duration} -translate-y-full`,\n }}\n timeout={{ appear: 0, enter: 350, exit: 200 }}\n unmountOnExit\n >\n <div ref={channelRef}>\n <Channel />\n </div>\n </CSSTransition>\n </div>\n </div>\n )\n}\n\nexport default DesktopAndAbove\n","import {\n RELEASE_BRANCH,\n type ReleaseBranch,\n} from '../../constants/release-branch'\nimport { forClientSideRendering } from '../../constants/request-origins'\n\nexport const checkReferrer = (\n referrer: string = '',\n releaseBranch: ReleaseBranch = RELEASE_BRANCH.master\n) => {\n try {\n const url = new URL(referrer)\n return url.origin === forClientSideRendering[releaseBranch].main\n } catch (_err) {\n return false\n }\n}\n","import { useContext, useState, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../context'\n// constants\nimport { ZIndex } from '../constants/z-index'\nimport { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\n// logo\nimport { LogoHeader } from '../../logo'\nimport type { LogoType } from '../../logo/constants'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\n// button\nimport { PillButton, TextButton, IconButton } from '../../button'\n// icon\nimport { Arrow, Member } from '../../icons'\n// utils\nimport { checkReferrer } from '../utils/links'\n// lodash\nimport some from 'lodash/some'\nimport includes from 'lodash/includes'\nimport throttle from 'lodash/throttle'\nconst _ = {\n some,\n includes,\n throttle,\n}\n\ntype TabletAndBelowProps = {\n topRowBgColor: string\n logoType: LogoType\n}\nconst TabletAndBelow: FC<TabletAndBelowProps> = ({\n topRowBgColor,\n logoType,\n}) => {\n const {\n isLinkExternal,\n releaseBranch,\n theme,\n pathname,\n referrerPath,\n isAuthed,\n } = useContext(HeaderContext)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n\n const [currentClientWidth, setCurrentClientWidth] = useState(0)\n useEffect(() => {\n const handleResize = _.throttle(() => {\n setCurrentClientWidth(document.body.clientWidth)\n }, 200)\n\n handleResize()\n window.addEventListener('resize', handleResize)\n\n return () => {\n window.removeEventListener('resize', handleResize)\n }\n }, [])\n\n const isOnArticlePage = _.includes(pathname, `${INTERNAL_LINKS.article}/`)\n const needPrevIconRoute = [\n INTERNAL_LINKS.account.donationHistoryPage,\n INTERNAL_LINKS.account.emailSubscription,\n INTERNAL_LINKS.myReading.savedBookmarks,\n INTERNAL_LINKS.myReading.browsingHistory,\n ]\n const isOnNeedPrevIconPage = _.some(needPrevIconRoute, (el) =>\n _.includes(pathname, el)\n )\n\n const showPrevIcon =\n isOnArticlePage || (isOnNeedPrevIconPage && currentClientWidth < 768) // only show it on mobile\n\n const gotoPrev = () => {\n if (referrerPath || checkReferrer(document.referrer, releaseBranch)) {\n // go to previous page when referer is twreporter site\n window.history.back()\n } else {\n // go to home page when referer is not twreporter site\n window.location.href = '/'\n }\n }\n\n return (\n <div\n className={clsx(\n `flex items-center justify-between ${ZIndex.topRow} py-[16px] ${topRowBgColor}`,\n 'desktop:hidden'\n )}\n >\n <div className=\"flex flex-row gap-[8px]\">\n {/* pre button */}\n {showPrevIcon ? (\n <div className=\"p-[4px] -translate-x-[8px]\">\n <IconButton\n iconComponent={\n <Arrow\n direction={Arrow.Direction.left}\n releaseBranch={releaseBranch}\n />\n }\n theme={theme}\n onClick={gotoPrev}\n />\n </div>\n ) : null}\n {/* logo */}\n <LinkComponent to={INTERNAL_LINKS.home} className=\"flex items-center\">\n <LogoHeader type={logoType} className=\"h-[21px]\" />\n </LinkComponent>\n </div>\n {/* actions */}\n <div className=\"flex flex-row items-center gap-[16px]\">\n <LinkComponent to={EXTERNAL_LINKS.monthlyDonation}>\n <PillButton\n text=\"贊助\"\n theme={PillButton.Theme.normal}\n type={PillButton.Type.primary}\n style={PillButton.Style.brand}\n />\n </LinkComponent>\n <LinkComponent to={INTERNAL_LINKS.account.index}>\n {isAuthed ? (\n <IconButton iconComponent={Member(releaseBranch)} />\n ) : (\n <TextButton\n text=\"登入\"\n theme={TextButton.Theme.normal}\n style={TextButton.Style.dark}\n size={TextButton.Size.s}\n />\n )}\n </LinkComponent>\n </div>\n </div>\n )\n}\n\nexport default TabletAndBelow\n","import { create, type StateCreator } from 'zustand'\n\nexport type AuthState = {\n isAuthed: boolean\n token?: string\n setAuthed: (isAuthed: boolean) => void\n setToken: (token?: string) => void\n reset: () => void\n}\n\nconst creator: StateCreator<AuthState> = (set) => ({\n isAuthed: false,\n token: undefined,\n setAuthed: (isAuthed: boolean) => set({ isAuthed }),\n setToken: (token?: string) => set({ token }),\n reset: () => set({ isAuthed: false, token: undefined }),\n})\n\nexport const useAuthStore = create<AuthState>()(creator)\n","import { useRef, useState, useCallback, useEffect, type FC } from 'react'\nimport clsx from 'clsx'\n\n// constants\nimport { THEME, type Theme } from '../constants/theme'\nimport type { ReleaseBranch } from '../constants/release-branch'\nimport { ZIndex } from './constants/z-index'\n// components\nimport DesktopAndAbove from './components/desktop-and-above'\nimport TabletAndBelow from './components/tablet-and-below'\n// context\nimport {\n HeaderContext,\n HamburgerContext,\n type HamburgerContextType,\n} from './context'\n// utils\nimport { selectHeaderTheme, selectLogoType } from './utils/theme'\n// hamburger menu\nimport HamburgerMenu from '../hamburger-menu'\n// tab bar\nimport TabBar from '../tab-bar'\nimport { useAuthStore, type AuthState } from './store/auth-store'\n// hook\nimport { useOutsideClick } from '../hooks'\n\nconst HIDE_HEADER_THRESHOLD = 8\nconst TRANSFORM_HEADER_THRESHOLD = 40\nconst TRANSFORM_TIMEOUT = 800\n\ntype HeaderProps = {\n releaseBranch: ReleaseBranch\n isLinkExternal: boolean\n theme: Theme\n pathname: string\n referrerPath: string\n hamburgerContext: HamburgerContextType\n}\nconst Header: FC<HeaderProps> = ({\n releaseBranch,\n isLinkExternal,\n theme,\n pathname,\n referrerPath,\n hamburgerContext,\n}) => {\n const isAuthed = useAuthStore((s: AuthState) => s.isAuthed)\n const { bgColor, topRowBgColor } = selectHeaderTheme(theme)\n const logoType = selectLogoType(theme)\n\n const { isHamburgerMenuOpen, closeHamburgerMenu } = hamburgerContext\n\n const [toUseNarrow, setToUseNarrow] = useState(false)\n const [hideHeader, setHideHeader] = useState(false)\n\n const lastKnownPageYOffset = useRef(0)\n const ticking = useRef(false)\n const currentY = useRef(0)\n const readyY = useRef(0)\n const isTransforming = useRef(false)\n const transformTimer = useRef<ReturnType<typeof setTimeout> | null>(null)\n\n const outsideRef = useOutsideClick(closeHamburgerMenu)\n\n const getScrollState = useCallback(\n (scrollTop: number, scrollDirection: 'up' | 'down') => {\n const isCurrentNarrow = toUseNarrow\n const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD\n const scrollState = { toUseNarrow, hideHeader }\n\n if (isTransforming.current) {\n return scrollState\n }\n\n if (scrollDirection === 'up') {\n readyY.current = scrollTop\n scrollState.hideHeader = false\n }\n\n if (scrollDirection === 'down') {\n if (\n isCurrentNarrow &&\n scrollTop - readyY.current > HIDE_HEADER_THRESHOLD\n ) {\n scrollState.hideHeader = true\n }\n }\n\n if (isCurrentNarrow) {\n scrollState.toUseNarrow =\n scrollDirection === 'down' ? true : nextToUseNarrow\n } else {\n scrollState.toUseNarrow =\n scrollDirection === 'up' ? false : nextToUseNarrow\n }\n\n if (isCurrentNarrow !== scrollState.toUseNarrow) {\n if (!transformTimer.current) {\n isTransforming.current = true\n transformTimer.current = setTimeout(() => {\n isTransforming.current = false\n readyY.current = currentY.current\n transformTimer.current = null\n }, TRANSFORM_TIMEOUT)\n }\n }\n\n return scrollState\n },\n [toUseNarrow, hideHeader]\n )\n\n const updateScrollState = useCallback(\n (currentScrollTop: number) => {\n const scrollDirection =\n currentScrollTop > currentY.current ? 'down' : 'up'\n currentY.current = currentScrollTop\n const updateState = getScrollState(currentScrollTop, scrollDirection)\n setToUseNarrow(() => updateState.toUseNarrow)\n setHideHeader(() => updateState.hideHeader)\n },\n [getScrollState]\n )\n\n const handleScroll = useCallback(() => {\n lastKnownPageYOffset.current = window.pageYOffset\n if (!ticking.current) {\n window.requestAnimationFrame(() => {\n updateScrollState(lastKnownPageYOffset.current)\n ticking.current = false\n })\n ticking.current = true\n }\n }, [updateScrollState])\n\n useEffect(() => {\n window.addEventListener('scroll', handleScroll, { passive: true })\n return () => {\n window.removeEventListener('scroll', handleScroll)\n }\n }, [handleScroll])\n\n return (\n <HeaderContext\n value={{\n releaseBranch,\n isLinkExternal,\n isAuthed,\n theme,\n pathname,\n referrerPath,\n toUseNarrow,\n hideHeader,\n }}\n >\n <HamburgerContext value={hamburgerContext}>\n <header\n className={clsx(\n `w-full top-0 transition-transform duration-300 ${bgColor} ${ZIndex.header}`,\n theme === THEME.transparent ? 'fixed' : 'sticky',\n hideHeader ? 'ease-in' : 'ease-out',\n hideHeader ? '-translate-y-full' : 'translate-y-0'\n )}\n >\n <div\n className={clsx(\n `flex flex-col mx-auto px-[24px]`,\n 'tablet:px-[32px]',\n 'desktop:px-[48px]',\n 'hd:w-[1280px] hd:px-0'\n )}\n >\n <DesktopAndAbove\n topRowBgColor={topRowBgColor}\n logoType={logoType}\n />\n <TabletAndBelow topRowBgColor={topRowBgColor} logoType={logoType} />\n </div>\n </header>\n <div\n ref={outsideRef}\n className={clsx(\n `fixed top-0 left-0 ${ZIndex.hamburger} transition-transform duration-300 ease-in-out`,\n isHamburgerMenuOpen\n ? 'translate-x-0 opacity-100'\n : '-translate-x-full opacity-100',\n 'tablet:-left-[320px]',\n isHamburgerMenuOpen\n ? 'tablet:translate-x-[320px] tablet:opacity-100'\n : 'tablet:-translate-x-[320px] tablet:opacity-100',\n 'desktop:-left-[280px]',\n isHamburgerMenuOpen\n ? 'desktop:translate-x-[280px] desktop:opacity-100'\n : 'desktop:-translate-x-[280px] desktop:opacity-100'\n )}\n >\n <HamburgerMenu />\n </div>\n <TabBar />\n </HamburgerContext>\n </HeaderContext>\n )\n}\n\nexport default Header\n"],"mappings":"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"}
@@ -34,4 +34,4 @@ const H6 = HeadingVariant("H6");
34
34
 
35
35
  //#endregion
36
36
  export { H1, H2, H3, H4, H5, H6 };
37
- //# sourceMappingURL=heading-BSEtBLuY.mjs.map
37
+ //# sourceMappingURL=heading-BWuXn7wB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"heading-BSEtBLuY.mjs","names":["Component: React.FC<HeadingProps> & { Type: typeof TYPE }"],"sources":["../src/text/heading.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React from 'react'\nimport { TYPE, type Type } from './constants'\n\ntype HeadingProps = React.HTMLAttributes<HTMLHeadingElement> & {\n text?: string\n type?: Type\n className?: string\n}\n\nconst baseClass = 'font-bold'\n\nconst variantClass = {\n H1: 'text-[28px] leading-[125%] tablet:text-[36px]',\n H2: 'text-[24px] leading-[125%] tablet:text-[32px]',\n H3: 'text-[22px] leading-[150%] tablet:text-[28px]',\n H4: 'text-[18px] leading-[150%] tablet:text-[22px]',\n H5: 'text-[17px] leading-[150%] tablet:text-[18px]',\n H6: 'text-[16px] leading-[150%] tablet:text-[16px]',\n}\n\nconst HeadingVariant = (variant: keyof typeof variantClass) => {\n const Component: React.FC<HeadingProps> & { Type: typeof TYPE } = ({\n text = '',\n type = TYPE.default,\n className = '',\n ...props\n }) => {\n const htmlTag = variant.toLowerCase() // 產生 'h1', 'h2', ...\n const fontFamily = type === TYPE.article ? 'font-title' : 'font-default'\n return React.createElement(\n htmlTag,\n {\n className: clsx(\n fontFamily,\n baseClass,\n variantClass[variant],\n className\n ),\n ...props,\n },\n text\n )\n }\n Component.displayName = variant\n Component.Type = TYPE\n return Component\n}\n\nconst H1 = HeadingVariant('H1')\nconst H2 = HeadingVariant('H2')\nconst H3 = HeadingVariant('H3')\nconst H4 = HeadingVariant('H4')\nconst H5 = HeadingVariant('H5')\nconst H6 = HeadingVariant('H6')\n\nexport { H1, H2, H3, H4, H5, H6 }\n"],"mappings":";;;;;AAUA,MAAM,YAAY;AAElB,MAAM,eAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,MAAM,kBAAkB,YAAuC;CAC7D,MAAMA,aAA6D,EACjE,OAAO,IACP,OAAO,KAAK,SACZ,YAAY,GACZ,GAAG,YACC;EACJ,MAAM,UAAU,QAAQ,aAAa;EACrC,MAAM,aAAa,SAAS,KAAK,UAAU,eAAe;AAC1D,SAAO,MAAM,cACX,SACA;GACE,WAAW,KACT,YACA,WACA,aAAa,UACb,UACD;GACD,GAAG;GACJ,EACD,KACD;;AAEH,WAAU,cAAc;AACxB,WAAU,OAAO;AACjB,QAAO;;AAGT,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK"}
1
+ {"version":3,"file":"heading-BWuXn7wB.mjs","names":["Component: React.FC<HeadingProps> & { Type: typeof TYPE }"],"sources":["../src/text/heading.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React from 'react'\nimport { TYPE, type Type } from './constants'\n\ntype HeadingProps = React.HTMLAttributes<HTMLHeadingElement> & {\n text?: string\n type?: Type\n className?: string\n}\n\nconst baseClass = 'font-bold'\n\nconst variantClass = {\n H1: 'text-[28px] leading-[125%] tablet:text-[36px]',\n H2: 'text-[24px] leading-[125%] tablet:text-[32px]',\n H3: 'text-[22px] leading-[150%] tablet:text-[28px]',\n H4: 'text-[18px] leading-[150%] tablet:text-[22px]',\n H5: 'text-[17px] leading-[150%] tablet:text-[18px]',\n H6: 'text-[16px] leading-[150%] tablet:text-[16px]',\n}\n\nconst HeadingVariant = (variant: keyof typeof variantClass) => {\n const Component: React.FC<HeadingProps> & { Type: typeof TYPE } = ({\n text = '',\n type = TYPE.default,\n className = '',\n ...props\n }) => {\n const htmlTag = variant.toLowerCase() // 產生 'h1', 'h2', ...\n const fontFamily = type === TYPE.article ? 'font-title' : 'font-default'\n return React.createElement(\n htmlTag,\n {\n className: clsx(\n fontFamily,\n baseClass,\n variantClass[variant],\n className\n ),\n ...props,\n },\n text\n )\n }\n Component.displayName = variant\n Component.Type = TYPE\n return Component\n}\n\nconst H1 = HeadingVariant('H1')\nconst H2 = HeadingVariant('H2')\nconst H3 = HeadingVariant('H3')\nconst H4 = HeadingVariant('H4')\nconst H5 = HeadingVariant('H5')\nconst H6 = HeadingVariant('H6')\n\nexport { H1, H2, H3, H4, H5, H6 }\n"],"mappings":";;;;;AAUA,MAAM,YAAY;AAElB,MAAM,eAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,MAAM,kBAAkB,YAAuC;CAC7D,MAAMA,aAA6D,EACjE,OAAO,IACP,OAAO,KAAK,SACZ,YAAY,GACZ,GAAG,YACC;EACJ,MAAM,UAAU,QAAQ,aAAa;EACrC,MAAM,aAAa,SAAS,KAAK,UAAU,eAAe;AAC1D,SAAO,MAAM,cACX,SACA;GACE,WAAW,KACT,YACA,WACA,aAAa,UACb,UACD;GACD,GAAG;GACJ,EACD,KACD;;AAEH,WAAU,cAAc;AACxB,WAAU,OAAO;AACjB,QAAO;;AAGT,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK"}
@@ -72,4 +72,4 @@ Object.defineProperty(exports, 'H6', {
72
72
  return H6;
73
73
  }
74
74
  });
75
- //# sourceMappingURL=heading-CNS7rJIc.js.map
75
+ //# sourceMappingURL=heading-DJepEhoE.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"heading-CNS7rJIc.js","names":["Component: React.FC<HeadingProps> & { Type: typeof TYPE }","TYPE","React"],"sources":["../src/text/heading.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React from 'react'\nimport { TYPE, type Type } from './constants'\n\ntype HeadingProps = React.HTMLAttributes<HTMLHeadingElement> & {\n text?: string\n type?: Type\n className?: string\n}\n\nconst baseClass = 'font-bold'\n\nconst variantClass = {\n H1: 'text-[28px] leading-[125%] tablet:text-[36px]',\n H2: 'text-[24px] leading-[125%] tablet:text-[32px]',\n H3: 'text-[22px] leading-[150%] tablet:text-[28px]',\n H4: 'text-[18px] leading-[150%] tablet:text-[22px]',\n H5: 'text-[17px] leading-[150%] tablet:text-[18px]',\n H6: 'text-[16px] leading-[150%] tablet:text-[16px]',\n}\n\nconst HeadingVariant = (variant: keyof typeof variantClass) => {\n const Component: React.FC<HeadingProps> & { Type: typeof TYPE } = ({\n text = '',\n type = TYPE.default,\n className = '',\n ...props\n }) => {\n const htmlTag = variant.toLowerCase() // 產生 'h1', 'h2', ...\n const fontFamily = type === TYPE.article ? 'font-title' : 'font-default'\n return React.createElement(\n htmlTag,\n {\n className: clsx(\n fontFamily,\n baseClass,\n variantClass[variant],\n className\n ),\n ...props,\n },\n text\n )\n }\n Component.displayName = variant\n Component.Type = TYPE\n return Component\n}\n\nconst H1 = HeadingVariant('H1')\nconst H2 = HeadingVariant('H2')\nconst H3 = HeadingVariant('H3')\nconst H4 = HeadingVariant('H4')\nconst H5 = HeadingVariant('H5')\nconst H6 = HeadingVariant('H6')\n\nexport { H1, H2, H3, H4, H5, H6 }\n"],"mappings":";;;;;;;;AAUA,MAAM,YAAY;AAElB,MAAM,eAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,MAAM,kBAAkB,YAAuC;CAC7D,MAAMA,aAA6D,EACjE,OAAO,IACP,OAAOC,uBAAK,SACZ,YAAY,GACZ,GAAG,YACC;EACJ,MAAM,UAAU,QAAQ,aAAa;EACrC,MAAM,aAAa,SAASA,uBAAK,UAAU,eAAe;AAC1D,SAAOC,cAAM,cACX,SACA;GACE,6BACE,YACA,WACA,aAAa,UACb,UACD;GACD,GAAG;GACJ,EACD,KACD;;AAEH,WAAU,cAAc;AACxB,WAAU,OAAOD;AACjB,QAAO;;AAGT,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK"}
1
+ {"version":3,"file":"heading-DJepEhoE.js","names":["Component: React.FC<HeadingProps> & { Type: typeof TYPE }","TYPE","React"],"sources":["../src/text/heading.tsx"],"sourcesContent":["import clsx from 'clsx'\nimport React from 'react'\nimport { TYPE, type Type } from './constants'\n\ntype HeadingProps = React.HTMLAttributes<HTMLHeadingElement> & {\n text?: string\n type?: Type\n className?: string\n}\n\nconst baseClass = 'font-bold'\n\nconst variantClass = {\n H1: 'text-[28px] leading-[125%] tablet:text-[36px]',\n H2: 'text-[24px] leading-[125%] tablet:text-[32px]',\n H3: 'text-[22px] leading-[150%] tablet:text-[28px]',\n H4: 'text-[18px] leading-[150%] tablet:text-[22px]',\n H5: 'text-[17px] leading-[150%] tablet:text-[18px]',\n H6: 'text-[16px] leading-[150%] tablet:text-[16px]',\n}\n\nconst HeadingVariant = (variant: keyof typeof variantClass) => {\n const Component: React.FC<HeadingProps> & { Type: typeof TYPE } = ({\n text = '',\n type = TYPE.default,\n className = '',\n ...props\n }) => {\n const htmlTag = variant.toLowerCase() // 產生 'h1', 'h2', ...\n const fontFamily = type === TYPE.article ? 'font-title' : 'font-default'\n return React.createElement(\n htmlTag,\n {\n className: clsx(\n fontFamily,\n baseClass,\n variantClass[variant],\n className\n ),\n ...props,\n },\n text\n )\n }\n Component.displayName = variant\n Component.Type = TYPE\n return Component\n}\n\nconst H1 = HeadingVariant('H1')\nconst H2 = HeadingVariant('H2')\nconst H3 = HeadingVariant('H3')\nconst H4 = HeadingVariant('H4')\nconst H5 = HeadingVariant('H5')\nconst H6 = HeadingVariant('H6')\n\nexport { H1, H2, H3, H4, H5, H6 }\n"],"mappings":";;;;;;;;AAUA,MAAM,YAAY;AAElB,MAAM,eAAe;CACnB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACL;AAED,MAAM,kBAAkB,YAAuC;CAC7D,MAAMA,aAA6D,EACjE,OAAO,IACP,OAAOC,uBAAK,SACZ,YAAY,GACZ,GAAG,YACC;EACJ,MAAM,UAAU,QAAQ,aAAa;EACrC,MAAM,aAAa,SAASA,uBAAK,UAAU,eAAe;AAC1D,SAAOC,cAAM,cACX,SACA;GACE,6BACE,YACA,WACA,aAAa,UACb,UACD;GACD,GAAG;GACJ,EACD,KACD;;AAEH,WAAU,cAAc;AACxB,WAAU,OAAOD;AACjB,QAAO;;AAGT,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK;AAC/B,MAAM,KAAK,eAAe,KAAK"}
@@ -0,0 +1,10 @@
1
+ import { useOutsideClick } from "../use-outside-click-DToGSYRk.mjs";
2
+ import * as react8 from "react";
3
+
4
+ //#region src/hooks/index.d.ts
5
+ declare const _default: {
6
+ useOutsideClick: (callback: () => void) => react8.RefObject<HTMLDivElement | null>;
7
+ };
8
+ //#endregion
9
+ export { _default as default, useOutsideClick };
10
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1,10 @@
1
+ import { useOutsideClick } from "../use-outside-click-CHxRFaTZ.js";
2
+ import * as react8 from "react";
3
+
4
+ //#region src/hooks/index.d.ts
5
+ declare const _default: {
6
+ useOutsideClick: (callback: () => void) => react8.RefObject<HTMLDivElement | null>;
7
+ };
8
+ //#endregion
9
+ export { _default as default, useOutsideClick };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,6 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+ const require_use_outside_click = require('../use-outside-click-436PXIeY.js');
3
+ const require_hooks = require('../hooks-Mt5N4Z2W.js');
4
+
5
+ exports.default = require_hooks.hooks_default;
6
+ exports.useOutsideClick = require_use_outside_click.useOutsideClick;
@@ -0,0 +1,4 @@
1
+ import { useOutsideClick } from "../use-outside-click-Bz_v9VCq.mjs";
2
+ import { hooks_default } from "../hooks-DFV2v01e.mjs";
3
+
4
+ export { hooks_default as default, useOutsideClick };
@@ -0,0 +1,2 @@
1
+ import { useOutsideClick } from "../use-outside-click-DToGSYRk.mjs";
2
+ export { useOutsideClick };
@@ -0,0 +1,2 @@
1
+ import { useOutsideClick } from "../use-outside-click-CHxRFaTZ.js";
2
+ export { useOutsideClick };
@@ -0,0 +1,3 @@
1
+ const require_use_outside_click = require('../use-outside-click-436PXIeY.js');
2
+
3
+ exports.useOutsideClick = require_use_outside_click.useOutsideClick;
@@ -0,0 +1,3 @@
1
+ import { useOutsideClick } from "../use-outside-click-Bz_v9VCq.mjs";
2
+
3
+ export { useOutsideClick };
@@ -0,0 +1,8 @@
1
+ import { useOutsideClick } from "./use-outside-click-Bz_v9VCq.mjs";
2
+
3
+ //#region src/hooks/index.ts
4
+ var hooks_default = { useOutsideClick };
5
+
6
+ //#endregion
7
+ export { hooks_default };
8
+ //# sourceMappingURL=hooks-DFV2v01e.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-DFV2v01e.mjs","names":[],"sources":["../src/hooks/index.ts"],"sourcesContent":["import { useOutsideClick } from './use-outside-click'\n\nexport { useOutsideClick }\n\nexport default { useOutsideClick }\n"],"mappings":";;;AAIA,oBAAe,EAAE,iBAAiB"}