@twreporter/react-typescript-components 0.1.0-beta.15 → 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 (166) hide show
  1. package/lib/button/constants.d.mts +2 -2
  2. package/lib/button/index.d.mts +4 -4
  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 +3 -3
  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 +11 -8
  68. package/lib/hamburger-menu/index.mjs +10 -7
  69. package/lib/{hamburger-menu-b8Ck07ms.mjs → hamburger-menu-Ca6QMgF9.mjs} +17 -9
  70. package/lib/hamburger-menu-Ca6QMgF9.mjs.map +1 -0
  71. package/lib/{hamburger-menu-Dy0hnv0l.js → hamburger-menu-qrLPGpHF.js} +18 -10
  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 +57 -16
  75. package/lib/header/index.js.map +1 -1
  76. package/lib/header/index.mjs +56 -15
  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/{release-branch-BqeBsvrl.d.mts → release-branch-8qGtkKtd.d.mts} +2 -2
  123. package/lib/styles.css +104 -9
  124. package/lib/tab-bar/constants.d.mts +3 -3
  125. package/lib/tab-bar/constants.js +1 -1
  126. package/lib/tab-bar/constants.mjs +1 -1
  127. package/lib/tab-bar/index.js +7 -7
  128. package/lib/tab-bar/index.mjs +6 -6
  129. package/lib/tab-bar/theme.d.mts +2 -2
  130. package/lib/tab-bar/theme.js +1 -1
  131. package/lib/tab-bar/theme.mjs +1 -1
  132. package/lib/{tab-bar-Dv2TkUW1.js → tab-bar-Binq1EhQ.js} +7 -7
  133. package/lib/{tab-bar-Dv2TkUW1.js.map → tab-bar-Binq1EhQ.js.map} +1 -1
  134. package/lib/{tab-bar-SYrjAH5q.mjs → tab-bar-BqiC7-Lw.mjs} +6 -6
  135. package/lib/{tab-bar-SYrjAH5q.mjs.map → tab-bar-BqiC7-Lw.mjs.map} +1 -1
  136. package/lib/text/constants.d.mts +2 -2
  137. package/lib/text/heading.d.mts +2 -2
  138. package/lib/text/heading.js +1 -1
  139. package/lib/text/heading.mjs +1 -1
  140. package/lib/text/paragraph.d.mts +2 -2
  141. package/lib/{theme-lCi6tmmS.d.mts → theme-B9CWW8U9.d.mts} +2 -2
  142. package/lib/{theme-W--MzZEH.js → theme-BOMyqC4d.js} +1 -1
  143. package/lib/{theme-W--MzZEH.js.map → theme-BOMyqC4d.js.map} +1 -1
  144. package/lib/theme-CIEkzycI.js +43 -0
  145. package/lib/theme-CIEkzycI.js.map +1 -0
  146. package/lib/theme-CkSx7UX3.mjs +38 -0
  147. package/lib/theme-CkSx7UX3.mjs.map +1 -0
  148. package/lib/{theme-DQCIQh_8.mjs → theme-PhMjSVv9.mjs} +1 -1
  149. package/lib/{theme-DQCIQh_8.mjs.map → theme-PhMjSVv9.mjs.map} +1 -1
  150. package/lib/title-bar/index.d.mts +4 -4
  151. package/lib/title-bar/index.d.ts +4 -4
  152. package/lib/title-bar/index.js +5 -5
  153. package/lib/title-bar/index.mjs +4 -4
  154. package/lib/{type-2Go0njwa.d.mts → type-4zpM3Fk5.d.mts} +1 -1
  155. package/lib/types/index.d.mts +1 -1
  156. package/lib/use-outside-click-436PXIeY.js +27 -0
  157. package/lib/use-outside-click-436PXIeY.js.map +1 -0
  158. package/lib/use-outside-click-Bz_v9VCq.mjs +20 -0
  159. package/lib/use-outside-click-Bz_v9VCq.mjs.map +1 -0
  160. package/lib/use-outside-click-CHxRFaTZ.d.ts +7 -0
  161. package/lib/use-outside-click-DToGSYRk.d.mts +7 -0
  162. package/package.json +3 -3
  163. package/lib/button-D50NHdly.js.map +0 -1
  164. package/lib/button-hDNHA85d.mjs.map +0 -1
  165. package/lib/hamburger-menu-Dy0hnv0l.js.map +0 -1
  166. package/lib/hamburger-menu-b8Ck07ms.mjs.map +0 -1
@@ -2,17 +2,18 @@ const require_chunk = require('./chunk-BxBTb9qk.js');
2
2
  const require_constants = require('./constants-BmxSMOOn.js');
3
3
  const require_paragraph = require('./paragraph-iuz3jP0Q.js');
4
4
  const require_theme = require('./theme-DDBlIbeS.js');
5
- const require_button = require('./button-D50NHdly.js');
5
+ const require_button = require('./button-Dk0MxlKd.js');
6
6
  const require_external_links = require('./external-links-DCn-uTD-.js');
7
7
  const require_internal_links = require('./internal-links-DxtMobuI.js');
8
- const require_external_link = require('./external-link-DoBTwlV3.js');
9
- const require_internal_link = require('./internal-link-B9ExuJfg.js');
10
- const require_divider = require('./divider-B1zvSjNJ.js');
8
+ const require_divider = require('./divider-Db3AhImD.js');
9
+ const require_external_link = require('./external-link-BMrkjNyi.js');
10
+ const require_internal_link = require('./internal-link-BLXTBMRq.js');
11
11
  const require_context = require('./context-I1lTR5SO.js');
12
12
  const require_constants$1 = require('./constants-D8wNUvoZ.js');
13
13
  const require_icons = require('./icons-qP5oNB0W.js');
14
- const require_dropdown_menu = require('./dropdown-menu-BAqmP8qa.js');
14
+ const require_dropdown_menu = require('./dropdown-menu-tbV9rhnw.js');
15
15
  const require_logo = require('./logo-BTNfdxTv.js');
16
+ const require_input = require('./input-czWOItrW.js');
16
17
  let react = require("react");
17
18
  react = require_chunk.__toESM(react);
18
19
  let clsx = require("clsx");
@@ -338,6 +339,10 @@ const HamburgerMenu = () => {
338
339
  const logoType = require_dropdown_menu.selectLogoType(menuTheme);
339
340
  const [activeKey, setActiveKey] = (0, react.useState)("");
340
341
  const LinkComponent = isLinkExternal ? require_external_link.external_link_default : require_internal_link.internal_link_default;
342
+ const onSearch = (keywords) => {
343
+ if (typeof window === "undefined") return;
344
+ window.location.href = `${require_internal_links.INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`;
345
+ };
341
346
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
342
347
  className: (0, clsx.default)("w-screen h-screen overflow-y-scroll overscroll-contain", bgColor, `pb-[calc(48px+48px)]`, "tablet:w-[320px] tablet:max-h-screen tablet:pb-0", "desktop:w-[280px]", "[&::-webkit-scrollbar]:w-[4px]", "[&::-webkit-scrollbar]:bg-transparent", "[&::-webkit-scrollbar-thumb]:rounded-[2px]", scrollBarColor),
343
348
  children: [
@@ -391,10 +396,13 @@ const HamburgerMenu = () => {
391
396
  }),
392
397
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
393
398
  className: "px-[32px] pt-[24px] pb-[8px] desktop:hidden",
394
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
395
- type: "text",
396
- className: (0, clsx.default)("w-full h-[40px] rounded-[20px] px-[16px]", "focus:outline-none"),
397
- placeholder: "搜尋"
399
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_input.search_bar_default, {
400
+ onSearch,
401
+ autoFocus: false,
402
+ widthType: require_input.search_bar_default.WidthType.stretch,
403
+ placeholder: "關鍵字搜尋",
404
+ theme: menuTheme,
405
+ releaseBranch
398
406
  })
399
407
  }),
400
408
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -486,4 +494,4 @@ Object.defineProperty(exports, 'hamburger_menu_default', {
486
494
  return hamburger_menu_default;
487
495
  }
488
496
  });
489
- //# sourceMappingURL=hamburger-menu-Dy0hnv0l.js.map
497
+ //# sourceMappingURL=hamburger-menu-qrLPGpHF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hamburger-menu-qrLPGpHF.js","names":["INTERNAL_LINKS","EXTERNAL_LINKS","SocialMedias: SocialMediaType[]","MEDIA_TYPE","EXTERNAL_LINKS","HEADER_ACTION_LINKS: ActionLink[]","INTERNAL_LINKS","TYPE","EXTERNAL_LINKS","HAMBURGER_MENU_ACION_LINKS: ActionLink[]","IconLink: FC<IconLinkProps>","HeaderContext","THEME","ExternalLink","InternalLink","selectHamburgerFooterTheme","Icon","P2","IconLink","IconLink: FC<IconLinkProps>","HeaderContext","THEME","selectHamburgerFooterTheme","ExternalLink","InternalLink","P2","SocialMedia: FC<SocialMediaProps>","HeaderContext","THEME","IconButton","SocialMediaIcon","SocialMedia","HamburgerMenu: FC","HeaderContext","HamburgerContext","THEME","selectHamburgerMenuTheme","selectLogoType","ExternalLink","InternalLink","INTERNAL_LINKS","IconButton","Cross","LogoSymbol","LogoHeader","EXTERNAL_LINKS","PillButton","Member","TextButton","SearchBar","selectHamburgerItemTheme","MenuButton","Divider","DropdownMenu","IconLink","LightLink","SocialMedia"],"sources":["../src/hamburger-menu/constants/channels.ts","../src/hamburger-menu/constants/social-media.ts","../src/header/constants/action-links.ts","../src/hamburger-menu/components/icon-link.tsx","../src/hamburger-menu/components/light-link.tsx","../src/hamburger-menu/components/social-media.tsx","../src/hamburger-menu/index.tsx"],"sourcesContent":["import { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\nimport type { LinkTarget } from '../../customized-link/type'\n\nexport const CHANNEL_TYPE = {\n link: 'link',\n divider: 'divider',\n dropdown: 'dropdown',\n iconLink: 'icon-link',\n lightLink: 'light-link',\n} as const\n\nexport const Channels = [\n {\n type: CHANNEL_TYPE.link,\n label: '最新',\n to: INTERNAL_LINKS.latest,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.divider,\n },\n {\n type: CHANNEL_TYPE.link,\n label: '深度專題',\n to: INTERNAL_LINKS.topics,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.dropdown,\n label: '議題',\n dropdownItems: [\n {\n label: '國際兩岸',\n to: INTERNAL_LINKS.categories.world,\n target: '_self' as LinkTarget,\n },\n {\n label: '人權司法',\n to: INTERNAL_LINKS.categories.humanRights,\n target: '_self' as LinkTarget,\n },\n {\n label: '政治社會',\n to: INTERNAL_LINKS.categories.politicsAndSociety,\n target: '_self' as LinkTarget,\n },\n {\n label: '醫療健康',\n to: INTERNAL_LINKS.categories.health,\n target: '_self' as LinkTarget,\n },\n {\n label: '環境永續',\n to: INTERNAL_LINKS.categories.environment,\n target: '_self' as LinkTarget,\n },\n {\n label: '經濟產業',\n to: INTERNAL_LINKS.categories.econ,\n target: '_self' as LinkTarget,\n },\n {\n label: '文化生活',\n to: INTERNAL_LINKS.categories.culture,\n target: '_self' as LinkTarget,\n },\n {\n label: '教育校園',\n to: INTERNAL_LINKS.categories.education,\n target: '_self' as LinkTarget,\n },\n ],\n },\n {\n type: CHANNEL_TYPE.dropdown,\n label: '評論',\n dropdownItems: [\n {\n label: '書摘與書評',\n to: INTERNAL_LINKS.categories.opinion.bookReview,\n target: '_self' as LinkTarget,\n },\n {\n label: '讀者投書',\n to: INTERNAL_LINKS.categories.opinion.letter,\n target: '_self' as LinkTarget,\n },\n {\n label: '全部',\n to: INTERNAL_LINKS.categories.opinion.index,\n target: '_self' as LinkTarget,\n },\n ],\n },\n {\n type: CHANNEL_TYPE.link,\n label: '人物故事',\n to: INTERNAL_LINKS.humanStory,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.divider,\n },\n {\n type: CHANNEL_TYPE.link,\n label: '影像',\n to: INTERNAL_LINKS.photography,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.dropdown,\n label: 'Podcast',\n dropdownItems: [\n {\n label: '關於報導者 Podcast',\n to: INTERNAL_LINKS.podcast.aboutPodcast,\n target: '_self' as LinkTarget,\n },\n {\n label: 'The Real Story',\n to: INTERNAL_LINKS.categories.podcast.theRealStory,\n target: '_self' as LinkTarget,\n },\n {\n label: 'On the Ground 路邊攤計劃',\n to: INTERNAL_LINKS.categories.podcast.onTheGround,\n target: '_self' as LinkTarget,\n },\n ],\n },\n {\n type: CHANNEL_TYPE.link,\n label: '少年報導者',\n to: EXTERNAL_LINKS.kidsReporter,\n target: '_blank' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.link,\n label: '報導者觀測站',\n to: EXTERNAL_LINKS.lawmaker,\n target: '_blank' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.link,\n label: '數位敘事',\n to: INTERNAL_LINKS.infographic,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.divider,\n },\n {\n type: CHANNEL_TYPE.iconLink,\n label: '個人專區',\n icon: 'member',\n to: INTERNAL_LINKS.account.index,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.iconLink,\n label: '我的閱讀',\n icon: 'kid_star',\n to: INTERNAL_LINKS.myReading.index,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.iconLink,\n label: '已收藏',\n icon: 'bookmark_basic',\n to: INTERNAL_LINKS.myReading.savedBookmarks,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.iconLink,\n label: '造訪紀錄',\n icon: 'history',\n to: INTERNAL_LINKS.myReading.browsingHistory,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.divider,\n },\n {\n type: CHANNEL_TYPE.lightLink,\n label: '基金會消息',\n to: INTERNAL_LINKS.categories.foundation.index,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.lightLink,\n label: '關於我們',\n to: INTERNAL_LINKS.about,\n target: '_blank' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.lightLink,\n label: '影響力報告',\n to: INTERNAL_LINKS.influenceReport,\n target: '_self' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.lightLink,\n label: '報導者開放實驗室',\n to: EXTERNAL_LINKS.openLab,\n target: '_blank' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.lightLink,\n label: '出版品與周邊',\n to: EXTERNAL_LINKS.publicationAndMerchandise,\n target: '_blank' as LinkTarget,\n },\n {\n type: CHANNEL_TYPE.divider,\n },\n]\n","import { MEDIA_TYPE, type MediaType } from '../../icons/constants'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\nimport type { LinkTarget } from '../../customized-link/type'\n\ntype SocialMediaType = {\n icon: MediaType\n link: string\n target: LinkTarget\n}\nexport const SocialMedias: SocialMediaType[] = [\n {\n icon: MEDIA_TYPE.facebook,\n link: EXTERNAL_LINKS.facebook,\n target: '_blank',\n },\n {\n icon: MEDIA_TYPE.instagram,\n link: EXTERNAL_LINKS.instagram,\n target: '_blank',\n },\n {\n icon: MEDIA_TYPE.threads,\n link: EXTERNAL_LINKS.threads,\n target: '_blank',\n },\n {\n icon: MEDIA_TYPE.youtube,\n link: EXTERNAL_LINKS.youtube,\n target: '_blank',\n },\n]\n","import { INTERNAL_LINKS } from '../../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../../constants/external-links'\nimport type { LinkTarget } from '../../customized-link/type'\nimport { TYPE, type Type } from '../../button/constants'\n\ntype ActionLink = {\n label: string\n to: string\n target: LinkTarget\n type: Type\n}\n\nexport const HEADER_ACTION_LINKS: ActionLink[] = [\n {\n label: '電子報',\n to: INTERNAL_LINKS.account.emailSubscription,\n target: '_self' as LinkTarget,\n type: TYPE.secondary,\n },\n {\n label: '贊助',\n to: EXTERNAL_LINKS.monthlyDonation,\n target: '_blank',\n type: TYPE.primary,\n },\n]\n\nexport const HAMBURGER_MENU_ACION_LINKS: ActionLink[] = [\n {\n label: '訂閱電子報',\n to: INTERNAL_LINKS.account.emailSubscription,\n target: '_self',\n type: TYPE.secondary,\n },\n {\n label: '贊助我們',\n to: EXTERNAL_LINKS.monthlyDonation,\n target: '_blank',\n type: TYPE.primary,\n },\n]\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../../header/context'\n// theme\nimport { THEME } from '../../constants/theme'\n// utils\nimport { selectHamburgerFooterTheme } from '../utils/theme'\n// icon\nimport { Icon } from '../../icons'\n// text\nimport { P2 } from '../../text/paragraph'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\nimport type { LinkTarget } from '../../customized-link/type'\n\ntype IconLinkProps = {\n label: string\n icon: string\n to: string\n target: LinkTarget\n}\nconst IconLink: FC<IconLinkProps> = ({ label, icon, to, target }) => {\n const { theme, releaseBranch, isLinkExternal } = useContext(HeaderContext)\n const footerTheme = theme === THEME.transparent ? THEME.normal : theme\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n const {\n color,\n hoverColor,\n hoverBgColor,\n svgHoverBgColor,\n svgBgColor,\n activeColor,\n activeBgColor,\n svgActiveBgColor,\n } = selectHamburgerFooterTheme(footerTheme)\n return (\n <LinkComponent to={to} target={target}>\n <div\n className={clsx(\n 'py-[8px] px-[32px] flex items-center',\n '[&>svg]:h-[18px] [&>svg]:w-[18px] [&>svg]:mr-[4px]',\n color,\n hoverColor,\n hoverBgColor,\n svgHoverBgColor,\n svgBgColor,\n activeColor,\n activeBgColor,\n svgActiveBgColor\n )}\n >\n <Icon filename={icon} releaseBranch={releaseBranch} />\n <P2 text={label} />\n </div>\n </LinkComponent>\n )\n}\n\nexport default IconLink\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../../header/context'\n// theme\nimport { THEME } from '../../constants/theme'\n// utils\nimport { selectHamburgerFooterTheme } from '../utils/theme'\n// text\nimport { P2 } from '../../text/paragraph'\n// link\nimport { ExternalLink, InternalLink } from '../../customized-link'\nimport type { LinkTarget } from '../../customized-link/type'\n\ntype IconLinkProps = {\n label: string\n to: string\n target: LinkTarget\n}\nconst IconLink: FC<IconLinkProps> = ({ label, to, target }) => {\n const { theme, isLinkExternal } = useContext(HeaderContext)\n const footerTheme = theme === THEME.transparent ? THEME.normal : theme\n const { color, hoverColor, hoverBgColor, activeColor, activeBgColor } =\n selectHamburgerFooterTheme(footerTheme)\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n return (\n <LinkComponent to={to} target={target}>\n <div\n className={clsx(\n 'py-[8px] px-[32px] flex items-center',\n '[&>svg]:h-[18px] [&>svg]:w-[18px] [&>svg]:mr-[4px]',\n color,\n hoverColor,\n hoverBgColor,\n activeColor,\n activeBgColor\n )}\n >\n <P2 text={label} />\n </div>\n </LinkComponent>\n )\n}\n\nexport default IconLink\n","import { useContext, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext } from '../../header/context'\n// icon\nimport { SocialMedia as SocialMediaIcon } from '../../icons'\n// type\nimport type { MediaType } from '../../icons/constants'\n// theme\nimport { THEME } from '../../constants/theme'\n// button\nimport { IconButton } from '../../button'\n\ntype SocialMediaProps = {\n mediaType: MediaType\n}\nconst SocialMedia: FC<SocialMediaProps> = ({ mediaType }) => {\n const { theme, releaseBranch } = useContext(HeaderContext)\n const footerTheme = theme === THEME.transparent ? THEME.normal : theme\n const Icon = (\n <SocialMediaIcon mediaType={mediaType} releaseBranch={releaseBranch} />\n )\n return (\n <IconButton\n iconComponent={Icon}\n theme={footerTheme}\n className={clsx(\n '[&>svg]:h-[32px] [&>svg]:w-[32px]',\n '[&>svg]:tablet:h-[24px] [&>svg]:tablet:w-[24px]'\n )}\n />\n )\n}\n\nexport default SocialMedia\n","import { useContext, useState, type FC } from 'react'\nimport clsx from 'clsx'\n// context\nimport { HeaderContext, HamburgerContext } from '../header/context'\n// constants\nimport { THEME } from '../constants/theme'\nimport { Channels, CHANNEL_TYPE } from './constants/channels'\nimport { SocialMedias } from './constants/social-media'\nimport { HAMBURGER_MENU_ACION_LINKS } from '../header/constants/action-links'\nimport { INTERNAL_LINKS } from '../constants/internal-links'\nimport { EXTERNAL_LINKS } from '../constants/external-links'\n// utils\nimport {\n selectHamburgerMenuTheme,\n selectHamburgerItemTheme,\n} from './utils/theme'\n// buttons\nimport { IconButton, MenuButton, PillButton, TextButton } from '../button'\n// icons\nimport { Cross, Member } from '../icons'\n// logo\nimport { LogoSymbol, LogoHeader } from '../logo'\n// utils\nimport { selectLogoType } from './utils/theme'\n// divider\nimport Divider from '../divider'\n// components\nimport { DropdownMenu } from '../dropdown-menu'\nimport IconLink from './components/icon-link'\nimport LightLink from './components/light-link'\nimport SocialMedia from './components/social-media'\n// link\nimport { ExternalLink, InternalLink } from '../customized-link'\n// search bar\nimport { SearchBar } from '../input'\n\nconst HamburgerMenu: FC = () => {\n const { theme, releaseBranch, isLinkExternal, isAuthed } =\n useContext(HeaderContext)\n const { closeHamburgerMenu } = useContext(HamburgerContext)\n\n const menuTheme = theme === THEME.photography ? theme : THEME.normal\n const { bgColor, scrollBarColor } = selectHamburgerMenuTheme(menuTheme)\n const logoType = selectLogoType(menuTheme)\n const [activeKey, setActiveKey] = useState('')\n const LinkComponent = isLinkExternal ? ExternalLink : InternalLink\n\n const onSearch = (keywords: string) => {\n if (typeof window === 'undefined') {\n return\n }\n window.location.href = `${INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`\n }\n\n return (\n <div\n className={clsx(\n 'w-screen h-screen overflow-y-scroll overscroll-contain',\n bgColor,\n // reserveHeightForIos15 is 48px\n `pb-[calc(48px+48px)]`,\n 'tablet:w-[320px] tablet:max-h-screen tablet:pb-0',\n 'desktop:w-[280px]',\n '[&::-webkit-scrollbar]:w-[4px]',\n '[&::-webkit-scrollbar]:bg-transparent',\n '[&::-webkit-scrollbar-thumb]:rounded-[2px]',\n scrollBarColor\n )}\n >\n {/* close icon */}\n <div\n className={clsx(\n 'hidden items-center justify-end pt-[24px] pr-[32px] pb-[16px]',\n 'tablet:flex'\n )}\n >\n <IconButton\n iconComponent={Cross(releaseBranch)}\n theme={menuTheme}\n onClick={closeHamburgerMenu}\n />\n </div>\n {/* logo */}\n <LinkComponent to={INTERNAL_LINKS.home}>\n <div\n className={clsx(\n 'hidden justify-center [&>img]:h-[24px] [&>img]:w-[24px]',\n 'tablet:flex'\n )}\n >\n <LogoSymbol type={logoType} releaseBranch={releaseBranch} />\n </div>\n </LinkComponent>\n {/* mobile hamburger header */}\n <div\n className={clsx(\n 'flex items-center justify-between px-[24px] py-[16px]',\n 'tablet:hidden'\n )}\n >\n <LinkComponent to={INTERNAL_LINKS.home}>\n <LogoHeader\n type={logoType}\n releaseBranch={releaseBranch}\n className=\"h-[21px]\"\n />\n </LinkComponent>\n <div className=\"flex 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 {/* search bar (visible on mobile and tablet) */}\n <div className=\"px-[32px] pt-[24px] pb-[8px] desktop:hidden\">\n <SearchBar\n onSearch={onSearch}\n autoFocus={false}\n widthType={SearchBar.WidthType.stretch}\n placeholder=\"關鍵字搜尋\"\n theme={menuTheme}\n releaseBranch={releaseBranch}\n />\n </div>\n {/* menu buttons */}\n <div className=\"flex flex-col pt-[16px]\">\n {Channels.map((channel, idx) => {\n if (channel.type === CHANNEL_TYPE.link) {\n const { color, hoverBgColor, activeBgColor } =\n selectHamburgerItemTheme(theme)\n return (\n <LinkComponent\n to={channel.to}\n target={channel.target}\n key={channel.label}\n >\n <MenuButton\n key={channel.label}\n text={channel.label}\n fontWeight={MenuButton.FontWeight.bold}\n color={color}\n p1ClassName={`${hoverBgColor} ${activeBgColor} pl-[32px] pr-[32px]`}\n />\n </LinkComponent>\n )\n }\n if (channel.type === CHANNEL_TYPE.divider) {\n return (\n <div className=\"py-[16px] px-[32px]\" key={`divider-${idx}`}>\n <Divider direction={Divider.Direction.horizontal} />\n </div>\n )\n }\n if (channel.type === CHANNEL_TYPE.dropdown) {\n const isActive = activeKey === channel.label\n const toggleFunc = (key: string) => {\n const nextActiveKey = activeKey === key ? '' : key\n setActiveKey(nextActiveKey)\n }\n return (\n <button\n onClick={() => toggleFunc(channel.label)}\n key={channel.label}\n type=\"button\"\n >\n <DropdownMenu\n text={channel.label}\n isActive={isActive}\n dropdownItems={channel.dropdownItems}\n />\n </button>\n )\n }\n if (channel.type === CHANNEL_TYPE.iconLink) {\n return (\n <IconLink\n label={channel.label}\n to={channel.to}\n target={channel.target}\n icon={channel.icon}\n key={channel.label}\n />\n )\n }\n if (channel.type === CHANNEL_TYPE.lightLink) {\n return (\n <LightLink\n label={channel.label}\n to={channel.to}\n target={channel.target}\n key={channel.label}\n />\n )\n }\n })}\n </div>\n {/* social media */}\n <div className=\"flex flex-row gap-[16px] justify-center\">\n {SocialMedias.map((socialMedia) => (\n <LinkComponent\n to={socialMedia.link}\n target={socialMedia.target}\n key={socialMedia.icon}\n >\n <SocialMedia mediaType={socialMedia.icon} />\n </LinkComponent>\n ))}\n </div>\n {/* action butoons */}\n <div\n className={clsx(\n 'flex flex-row gap-[16px] px-[32px] pt-[40px] pb-[32px]',\n 'tablet:flex-col'\n )}\n >\n {HAMBURGER_MENU_ACION_LINKS.map((link) => (\n <LinkComponent\n to={link.to}\n target={link.target}\n key={link.label}\n className=\"flex-1\"\n >\n <PillButton\n text={link.label}\n theme={theme}\n type={link.type}\n className=\"w-full justify-center\"\n size={PillButton.Size.l}\n />\n </LinkComponent>\n ))}\n </div>\n </div>\n )\n}\n\nexport default HamburgerMenu\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import "../index-CYb6xr3M.mjs";
2
- import { Theme } from "../theme-lCi6tmmS.mjs";
3
- import { ReleaseBranch } from "../release-branch-BqeBsvrl.mjs";
1
+ import "../index-DaRD2S-9.mjs";
2
+ import { Theme } from "../theme-B9CWW8U9.mjs";
3
+ import { ReleaseBranch } from "../release-branch-8qGtkKtd.mjs";
4
4
  import { FC } from "react";
5
5
 
6
6
  //#region src/header/context/index.d.ts
@@ -3,26 +3,31 @@ require('../constants-BmxSMOOn.js');
3
3
  require('../constants-Cndhv6qr.js');
4
4
  require('../paragraph-iuz3jP0Q.js');
5
5
  const require_theme = require('../theme-DDBlIbeS.js');
6
- const require_button = require('../button-D50NHdly.js');
6
+ const require_button = require('../button-Dk0MxlKd.js');
7
7
  const require_external_links = require('../external-links-DCn-uTD-.js');
8
8
  const require_internal_links = require('../internal-links-DxtMobuI.js');
9
9
  const require_release_branch = require('../release-branch-CRZV4Ivz.js');
10
10
  const require_request_origins = require('../request-origins-BDXulkK9.js');
11
- const require_external_link = require('../external-link-DoBTwlV3.js');
12
- const require_internal_link = require('../internal-link-B9ExuJfg.js');
13
- require('../customized-link-DqW2a8oZ.js');
14
- require('../constants-nmH6p6-y.js');
15
- const require_divider = require('../divider-B1zvSjNJ.js');
11
+ require('../constants-BuIUKM2c.js');
12
+ const require_divider = require('../divider-Db3AhImD.js');
13
+ const require_external_link = require('../external-link-BMrkjNyi.js');
14
+ const require_internal_link = require('../internal-link-BLXTBMRq.js');
15
+ require('../customized-link-XNoMkeYw.js');
16
16
  const require_context = require('../context-I1lTR5SO.js');
17
17
  require('../constants-D8wNUvoZ.js');
18
18
  const require_icons = require('../icons-qP5oNB0W.js');
19
19
  const require_constants$4 = require('../constants-C2moxnps.js');
20
- require('../dropdown-menu-BAqmP8qa.js');
21
- const require_hamburger_menu = require('../hamburger-menu-Dy0hnv0l.js');
20
+ require('../dropdown-menu-tbV9rhnw.js');
21
+ const require_hamburger_menu = require('../hamburger-menu-qrLPGpHF.js');
22
22
  const require_logo = require('../logo-BTNfdxTv.js');
23
- const require_tab_bar = require('../tab-bar-Dv2TkUW1.js');
24
- require('../theme-W--MzZEH.js');
25
- require('../constants-BNxn_qJc.js');
23
+ require('../constants-BP47D2l7.js');
24
+ require('../theme-CIEkzycI.js');
25
+ const require_input = require('../input-czWOItrW.js');
26
+ const require_tab_bar = require('../tab-bar-Binq1EhQ.js');
27
+ const require_use_outside_click = require('../use-outside-click-436PXIeY.js');
28
+ require('../hooks-Mt5N4Z2W.js');
29
+ require('../theme-BOMyqC4d.js');
30
+ require('../constants-91DoZaeP.js');
26
31
  let react = require("react");
27
32
  react = require_chunk.__toESM(react);
28
33
  let clsx = require("clsx");
@@ -53,16 +58,50 @@ const ANIMATION = {
53
58
 
54
59
  //#endregion
55
60
  //#region src/header/components/top-row/icons.tsx
61
+ const SearchIcon = () => {
62
+ const [isSearchOpened, setSearchOpened] = (0, react.useState)(false);
63
+ const { releaseBranch, theme } = (0, react.useContext)(require_context.HeaderContext);
64
+ const closeSearchBox = () => {
65
+ setSearchOpened(false);
66
+ };
67
+ const ref = require_use_outside_click.useOutsideClick(closeSearchBox);
68
+ const handleClickSearch = (e) => {
69
+ e.preventDefault();
70
+ setSearchOpened(true);
71
+ if (!ref.current) return;
72
+ ref.current.getElementsByTagName("input")[0]?.focus();
73
+ };
74
+ const onSearch = (keywords) => {
75
+ setSearchOpened(false);
76
+ if (typeof window !== "undefined") window.location.href = `${require_internal_links.INTERNAL_LINKS.search}?q=${encodeURIComponent(keywords)}`;
77
+ };
78
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
79
+ className: "relative",
80
+ ref,
81
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.icon_button_default, {
82
+ iconComponent: require_icons.Search(releaseBranch),
83
+ theme,
84
+ onClick: handleClickSearch,
85
+ className: (0, clsx.default)("transition-opacity ease-in-out duration-[300ms]", isSearchOpened ? "opacity-0 pointer-events-none" : "opacity-100")
86
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
87
+ className: (0, clsx.default)("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"),
88
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_input.search_bar_default, {
89
+ placeholder: "關鍵字搜尋",
90
+ theme,
91
+ onClose: closeSearchBox,
92
+ onSearch,
93
+ releaseBranch
94
+ })
95
+ })]
96
+ }, "search");
97
+ };
56
98
  const Icons = ({ releaseBranch = require_release_branch.RELEASE_BRANCH.master, theme = require_theme.THEME.normal }) => {
57
99
  const { isLinkExternal } = (0, react.useContext)(require_context.HeaderContext);
58
100
  const LinkComponent = isLinkExternal ? require_external_link.external_link_default : require_internal_link.internal_link_default;
59
101
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
60
102
  className: "ml-[24px] flex flex-row gap-[16px]",
61
103
  children: [
62
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.icon_button_default, {
63
- iconComponent: require_icons.Search(releaseBranch),
64
- theme
65
- }),
104
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, {}),
66
105
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LinkComponent, {
67
106
  to: require_internal_links.INTERNAL_LINKS.myReading.index,
68
107
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_button.icon_button_default, {
@@ -435,7 +474,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
435
474
  const isAuthed = useAuthStore((s) => s.isAuthed);
436
475
  const { bgColor, topRowBgColor } = selectHeaderTheme(theme);
437
476
  const logoType = selectLogoType(theme);
438
- const { isHamburgerMenuOpen } = hamburgerContext;
477
+ const { isHamburgerMenuOpen, closeHamburgerMenu } = hamburgerContext;
439
478
  const [toUseNarrow, setToUseNarrow] = (0, react.useState)(false);
440
479
  const [hideHeader, setHideHeader] = (0, react.useState)(false);
441
480
  const lastKnownPageYOffset = (0, react.useRef)(0);
@@ -444,6 +483,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
444
483
  const readyY = (0, react.useRef)(0);
445
484
  const isTransforming = (0, react.useRef)(false);
446
485
  const transformTimer = (0, react.useRef)(null);
486
+ const outsideRef = require_use_outside_click.useOutsideClick(closeHamburgerMenu);
447
487
  const getScrollState = (0, react.useCallback)((scrollTop, scrollDirection) => {
448
488
  const isCurrentNarrow = toUseNarrow;
449
489
  const nextToUseNarrow = scrollTop > TRANSFORM_HEADER_THRESHOLD;
@@ -524,6 +564,7 @@ const Header = ({ releaseBranch, isLinkExternal, theme, pathname, referrerPath,
524
564
  })
525
565
  }),
526
566
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
567
+ ref: outsideRef,
527
568
  className: (0, clsx.default)(`fixed top-0 left-0 ${require_tab_bar.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"),
528
569
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_hamburger_menu.hamburger_menu_default, {})
529
570
  }),
@@ -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":"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"}
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 { HEADER_ACTION_LINKS, hamburger_menu_default } from "../hamburger-menu-b8Ck07ms.mjs";
19
+ import "../dropdown-menu-CuyS5r71.mjs";
20
+ import { HEADER_ACTION_LINKS, hamburger_menu_default } from "../hamburger-menu-Ca6QMgF9.mjs";
21
21
  import { logo_header_default } from "../logo-D68VZ-fc.mjs";
22
- import { ZIndex, tab_bar_default } from "../tab-bar-SYrjAH5q.mjs";
23
- import "../theme-DQCIQh_8.mjs";
24
- import "../constants--CDeoDub.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
  }),