@kids-reporter/routing-ui 0.1.0-alpha.1

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 (129) hide show
  1. package/.prettierignore +17 -0
  2. package/babel.config.cjs +31 -0
  3. package/dist/components/button.d.ts +23 -0
  4. package/dist/components/button.d.ts.map +1 -0
  5. package/dist/components/button.js +82 -0
  6. package/dist/components/button.js.map +1 -0
  7. package/dist/components/index.d.ts +3 -0
  8. package/dist/components/index.d.ts.map +1 -0
  9. package/dist/components/index.js +21 -0
  10. package/dist/components/index.js.map +1 -0
  11. package/dist/components/input.d.ts +20 -0
  12. package/dist/components/input.d.ts.map +1 -0
  13. package/dist/components/input.js +143 -0
  14. package/dist/components/input.js.map +1 -0
  15. package/dist/constants/default-values.d.ts +12 -0
  16. package/dist/constants/default-values.d.ts.map +1 -0
  17. package/dist/constants/default-values.js +148 -0
  18. package/dist/constants/default-values.js.map +1 -0
  19. package/dist/footer.d.ts +10 -0
  20. package/dist/footer.d.ts.map +1 -0
  21. package/dist/footer.js +144 -0
  22. package/dist/footer.js.map +1 -0
  23. package/dist/header/desktop-header.d.ts +14 -0
  24. package/dist/header/desktop-header.d.ts.map +1 -0
  25. package/dist/header/desktop-header.js +85 -0
  26. package/dist/header/desktop-header.js.map +1 -0
  27. package/dist/header/header-context.d.ts +16 -0
  28. package/dist/header/header-context.d.ts.map +1 -0
  29. package/dist/header/header-context.js +37 -0
  30. package/dist/header/header-context.js.map +1 -0
  31. package/dist/header/index.d.ts +12 -0
  32. package/dist/header/index.d.ts.map +1 -0
  33. package/dist/header/index.js +72 -0
  34. package/dist/header/index.js.map +1 -0
  35. package/dist/header/menu/header-menu-item-group.d.ts +7 -0
  36. package/dist/header/menu/header-menu-item-group.d.ts.map +1 -0
  37. package/dist/header/menu/header-menu-item-group.js +31 -0
  38. package/dist/header/menu/header-menu-item-group.js.map +1 -0
  39. package/dist/header/menu/header-menu-item.d.ts +9 -0
  40. package/dist/header/menu/header-menu-item.d.ts.map +1 -0
  41. package/dist/header/menu/header-menu-item.js +92 -0
  42. package/dist/header/menu/header-menu-item.js.map +1 -0
  43. package/dist/header/menu/index.d.ts +15 -0
  44. package/dist/header/menu/index.d.ts.map +1 -0
  45. package/dist/header/menu/index.js +170 -0
  46. package/dist/header/menu/index.js.map +1 -0
  47. package/dist/header/mobile-header.d.ts +9 -0
  48. package/dist/header/mobile-header.d.ts.map +1 -0
  49. package/dist/header/mobile-header.js +46 -0
  50. package/dist/header/mobile-header.js.map +1 -0
  51. package/dist/header/post-title-setter.d.ts +6 -0
  52. package/dist/header/post-title-setter.d.ts.map +1 -0
  53. package/dist/header/post-title-setter.js +22 -0
  54. package/dist/header/post-title-setter.js.map +1 -0
  55. package/dist/header/shared-components.d.ts +31 -0
  56. package/dist/header/shared-components.d.ts.map +1 -0
  57. package/dist/header/shared-components.js +256 -0
  58. package/dist/header/shared-components.js.map +1 -0
  59. package/dist/hooks/index.d.ts +4 -0
  60. package/dist/hooks/index.d.ts.map +1 -0
  61. package/dist/hooks/index.js +36 -0
  62. package/dist/hooks/index.js.map +1 -0
  63. package/dist/hooks/use-is-at-top.d.ts +3 -0
  64. package/dist/hooks/use-is-at-top.d.ts.map +1 -0
  65. package/dist/hooks/use-is-at-top.js +26 -0
  66. package/dist/hooks/use-is-at-top.js.map +1 -0
  67. package/dist/hooks/use-media-query.d.ts +7 -0
  68. package/dist/hooks/use-media-query.d.ts.map +1 -0
  69. package/dist/hooks/use-media-query.js +47 -0
  70. package/dist/hooks/use-media-query.js.map +1 -0
  71. package/dist/hooks/use-scroll-level.d.ts +11 -0
  72. package/dist/hooks/use-scroll-level.d.ts.map +1 -0
  73. package/dist/hooks/use-scroll-level.js +53 -0
  74. package/dist/hooks/use-scroll-level.js.map +1 -0
  75. package/dist/icons/index.d.ts +17 -0
  76. package/dist/icons/index.d.ts.map +1 -0
  77. package/dist/icons/index.js +341 -0
  78. package/dist/icons/index.js.map +1 -0
  79. package/dist/index.d.ts +10 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +101 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/styles.css +475 -0
  84. package/dist/types/index.d.ts +10 -0
  85. package/dist/types/index.d.ts.map +1 -0
  86. package/dist/types/index.js +6 -0
  87. package/dist/types/index.js.map +1 -0
  88. package/dist/utils/cn.d.ts +8 -0
  89. package/dist/utils/cn.d.ts.map +1 -0
  90. package/dist/utils/cn.js +27 -0
  91. package/dist/utils/cn.js.map +1 -0
  92. package/dist/utils/generate-social-media-config.d.ts +9 -0
  93. package/dist/utils/generate-social-media-config.d.ts.map +1 -0
  94. package/dist/utils/generate-social-media-config.js +55 -0
  95. package/dist/utils/generate-social-media-config.js.map +1 -0
  96. package/dist/utils/index.d.ts +3 -0
  97. package/dist/utils/index.d.ts.map +1 -0
  98. package/dist/utils/index.js +28 -0
  99. package/dist/utils/index.js.map +1 -0
  100. package/eslint.config.mjs +55 -0
  101. package/package.json +51 -0
  102. package/prettier.config.mjs +13 -0
  103. package/scripts/build.sh +18 -0
  104. package/src/components/button.tsx +108 -0
  105. package/src/components/index.tsx +2 -0
  106. package/src/components/input.tsx +171 -0
  107. package/src/constants/default-values.tsx +153 -0
  108. package/src/footer.tsx +151 -0
  109. package/src/header/desktop-header.tsx +128 -0
  110. package/src/header/header-context.tsx +56 -0
  111. package/src/header/index.tsx +96 -0
  112. package/src/header/menu/header-menu-item-group.tsx +37 -0
  113. package/src/header/menu/header-menu-item.tsx +132 -0
  114. package/src/header/menu/index.tsx +206 -0
  115. package/src/header/mobile-header.tsx +61 -0
  116. package/src/header/post-title-setter.tsx +22 -0
  117. package/src/header/shared-components.tsx +326 -0
  118. package/src/hooks/index.ts +3 -0
  119. package/src/hooks/use-is-at-top.ts +23 -0
  120. package/src/hooks/use-media-query.ts +57 -0
  121. package/src/hooks/use-scroll-level.ts +52 -0
  122. package/src/icons/index.tsx +358 -0
  123. package/src/index.ts +9 -0
  124. package/src/styles.css +475 -0
  125. package/src/types/index.ts +10 -0
  126. package/src/utils/cn.ts +41 -0
  127. package/src/utils/generate-social-media-config.ts +75 -0
  128. package/src/utils/index.ts +2 -0
  129. package/tsconfig.json +33 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-menu-item.js","names":["_cn","require","_headerContext","_jsxRuntime","HeaderMenuItem","label","href","subItems","external","showIcon","icon","isExpanded","contentClassName","onExpand","hasSubItems","length","context","useHeaderContext","closeMenu","handleExpand","content","jsxs","className","cn","children","jsx","width","height","viewBox","fill","d","stroke","strokeWidth","strokeLinecap","strokeLinejoin","onClick","map","subItem","index","target","rel","_default","exports","default"],"sources":["../../../src/header/menu/header-menu-item.tsx"],"sourcesContent":["import { MenuItem } from '../../types'\nimport { cn } from '../../utils/cn'\nimport { useHeaderContext } from '../header-context'\n\ntype HeaderMenuItemProps = {\n contentClassName?: string\n isExpanded?: boolean\n onExpand?: (label: string | null) => void\n} & MenuItem\n\nfunction HeaderMenuItem({\n label,\n href,\n subItems,\n external,\n showIcon,\n icon,\n isExpanded,\n contentClassName,\n onExpand,\n}: HeaderMenuItemProps) {\n const hasSubItems = subItems && subItems.length > 0\n const context = useHeaderContext()\n const closeMenu = context?.closeMenu\n\n const handleExpand = () => {\n if (hasSubItems) {\n onExpand?.(isExpanded ? null : label)\n }\n }\n\n const content = (\n <div\n className={cn(\n 'group flex w-full items-center justify-between text-neutral-900 transition-colors duration-100 group-hover:text-neutral-900',\n contentClassName\n )}\n >\n <div className=\"gap-2 flex items-center\">\n {showIcon && icon && (\n <div className=\"w-4 h-4 flex items-center justify-center\">{icon}</div>\n )}\n <span\n className={cn(\n 'prose-p1-bold',\n isExpanded && 'text-red-400 group-hover:text-red-400'\n )}\n >\n {label}\n </span>\n </div>\n\n {hasSubItems && (\n <div\n className={cn(\n 'w-6 h-6 flex items-center justify-center transition-transform',\n isExpanded && 'rotate-180 text-red-400 group-hover:text-red-400'\n )}\n >\n <svg width=\"14\" height=\"7\" viewBox=\"0 0 14 7\" fill=\"none\">\n <path\n d=\"M1 1L7 6L13 1\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </div>\n )}\n </div>\n )\n\n if (hasSubItems) {\n return (\n <div className=\"w-full\">\n <button\n onClick={handleExpand}\n className=\"px-6 tablet:px-8 py-2 flex w-full cursor-pointer items-center justify-between transition-colors duration-200 hover:bg-neutral-black/5 active:bg-neutral-black/10\"\n >\n {content}\n </button>\n <div\n className={cn(\n 'ease-in-out overflow-hidden transition-all duration-300',\n isExpanded ? 'max-h-96 opacity-100' : 'max-h-0 opacity-0'\n )}\n >\n {subItems.map((subItem, index) => (\n <a\n key={index}\n href={subItem.href}\n className=\"px-6 tablet:px-12 py-2 pl-12 prose-p2 font-medium block transition-colors duration-200 hover:bg-neutral-black/5 hover:text-neutral-900 active:bg-neutral-black/10\"\n onClick={closeMenu}\n >\n {subItem.label}\n </a>\n ))}\n </div>\n </div>\n )\n }\n\n if (external) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={\n 'px-6 tablet:px-8 py-2 block transition-colors duration-200 hover:bg-neutral-black/5 active:bg-neutral-black/10'\n }\n >\n {content}\n </a>\n )\n }\n\n return (\n <a\n href={href}\n className={\n 'px-6 tablet:px-8 py-2 block transition-colors duration-200 hover:bg-neutral-black/5 active:bg-neutral-black/10'\n }\n onClick={closeMenu}\n >\n {content}\n </a>\n )\n}\n\nexport default HeaderMenuItem\n"],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { MenuItem, SocialMediaHrefs } from '../../types';
2
+ type MenuProps = {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ keywords: string[];
6
+ menuItems: MenuItem[];
7
+ additionalMenuItems: MenuItem[];
8
+ socialMediaHrefs: SocialMediaHrefs;
9
+ donateUrl: string;
10
+ subscribeUrl: string;
11
+ searchPlaceholder: string;
12
+ };
13
+ declare function Menu({ isOpen, onClose, keywords, menuItems, additionalMenuItems, socialMediaHrefs, donateUrl, subscribeUrl, searchPlaceholder, }: MenuProps): import("react/jsx-runtime").JSX.Element;
14
+ export default Menu;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/header/menu/index.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAO7D,KAAK,SAAS,GAAG;IACf,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,EAAE,QAAQ,EAAE,CAAA;IACrB,mBAAmB,EAAE,QAAQ,EAAE,CAAA;IAC/B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAUD,iBAAS,IAAI,CAAC,EACZ,MAAM,EACN,OAAO,EACP,QAAQ,EACR,SAAS,EACT,mBAAmB,EACnB,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,iBAAiB,GAClB,EAAE,SAAS,2CA+JX;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+ var _image = _interopRequireDefault(require("next/image"));
10
+ var _react = require("react");
11
+ var _button = _interopRequireDefault(require("../../components/button"));
12
+ var _icons = require("../../icons");
13
+ var _cn = require("../../utils/cn");
14
+ var _generateSocialMediaConfig = require("../../utils/generate-social-media-config");
15
+ var _sharedComponents = require("../shared-components");
16
+ var _headerMenuItem = _interopRequireDefault(require("./header-menu-item"));
17
+ var _headerMenuItemGroup = _interopRequireDefault(require("./header-menu-item-group"));
18
+ var _jsxRuntime = require("react/jsx-runtime");
19
+ function Divider() {
20
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
21
+ className: "px-6 tablet:px-8 py-4 w-full",
22
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
23
+ className: "h-px w-full bg-neutral-300"
24
+ })
25
+ });
26
+ }
27
+ function Menu({
28
+ isOpen,
29
+ onClose,
30
+ keywords,
31
+ menuItems,
32
+ additionalMenuItems,
33
+ socialMediaHrefs,
34
+ donateUrl,
35
+ subscribeUrl,
36
+ searchPlaceholder
37
+ }) {
38
+ const socialMediaConfig = (0, _generateSocialMediaConfig.generateSocialMediaConfig)(socialMediaHrefs);
39
+ (0, _react.useEffect)(() => {
40
+ if (isOpen) {
41
+ document.body.classList.add('no-scroll');
42
+ } else {
43
+ document.body.classList.remove('no-scroll');
44
+ }
45
+ return () => {
46
+ document.body.classList.remove('no-scroll');
47
+ };
48
+ }, [isOpen]);
49
+ (0, _react.useEffect)(() => {
50
+ const handleEscape = e => {
51
+ if (e.key === 'Escape') {
52
+ onClose();
53
+ }
54
+ };
55
+ if (isOpen) {
56
+ document.addEventListener('keydown', handleEscape);
57
+ }
58
+ return () => {
59
+ document.removeEventListener('keydown', handleEscape);
60
+ };
61
+ }, [isOpen, onClose]);
62
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
63
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
64
+ className: (0, _cn.cn)('inset-0 fixed z-1001 bg-neutral-500/50 transition-opacity duration-300', isOpen ? 'opacity-100' : 'pointer-events-none opacity-0'),
65
+ onClick: onClose
66
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
67
+ className: (0, _cn.cn)('top-0 left-0 tablet:w-80 bg-white shadow-2xl ease-in-out scrollbar-thin tablet:pt-0 fixed z-1001 h-full w-full transform pt-(--mobile-header-height) transition-transform duration-300', isOpen ? 'translate-x-0' : '-translate-x-full'),
68
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
69
+ className: "flex h-full flex-col overflow-y-auto",
70
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
71
+ className: "px-6 tablet:px-8 py-4 mt-4 hidden items-center justify-between tablet:flex",
72
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
73
+ className: "flex items-center",
74
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
75
+ href: "/",
76
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_image.default, {
77
+ src: "/assets/images/brand-icon.svg",
78
+ alt: "\u5C11\u5E74\u5831\u5C0E\u8005 The Reporter for Kids",
79
+ className: "h-5",
80
+ height: 20,
81
+ width: 183,
82
+ loading: "eager"
83
+ })
84
+ })
85
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
86
+ onClick: onClose,
87
+ className: "w-8 h-8 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-colors duration-200 hover:text-neutral-800",
88
+ "aria-label": "\u95DC\u9589\u9078\u55AE",
89
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.ClearIcon, {})
90
+ })]
91
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
92
+ className: "px-6 tablet:px-8 pt-4 desktop:hidden",
93
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedComponents.SearchInputSection, {
94
+ mode: "inline",
95
+ tags: keywords,
96
+ searchPlaceholder: searchPlaceholder
97
+ })
98
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
99
+ className: "py-4 flex-1",
100
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_headerMenuItem.default, {
101
+ ...menuItems?.[0]
102
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
103
+ className: "py-2",
104
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_headerMenuItemGroup.default, {
105
+ isMenuOpen: isOpen,
106
+ menuItems: menuItems
107
+ })
108
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_headerMenuItem.default, {
109
+ ...additionalMenuItems?.[0],
110
+ contentClassName: "text-neutral-600 [&_span]:[font-family:var(--font-family-noto)] [&_span]:[font-size:var(--font-size-p2)] [&_span]:[font-weight:500] [&_span]:[line-height:var(--line-height-normal)] [&_span]:[letter-spacing:var(--letter-spacing-wide)] hover:text-neutral-900"
111
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
112
+ className: "py-2",
113
+ children: additionalMenuItems.slice(1).map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_headerMenuItem.default, {
114
+ label: item.label,
115
+ href: item.href,
116
+ external: item.external,
117
+ contentClassName: "text-neutral-600 [&_span]:[font-family:var(--font-family-noto)] [&_span]:[font-size:var(--font-size-p2)] [&_span]:[font-weight:500] [&_span]:[line-height:var(--line-height-normal)] [&_span]:[letter-spacing:var(--letter-spacing-wide)] hover:text-neutral-900"
118
+ }, index))
119
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(Divider, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
120
+ className: "px-6 tablet:px-8",
121
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
122
+ className: "gap-4 tablet:gap-0 px-4 flex items-center justify-center tablet:justify-between",
123
+ children: socialMediaConfig.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
124
+ href: item.href,
125
+ className: "text-neutral-900 transition-colors duration-200 hover:text-red-500",
126
+ target: "_blank",
127
+ rel: "noopener noreferrer",
128
+ "aria-label": item.label,
129
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
130
+ className: "w-6 h-6 flex items-center justify-center",
131
+ children: item.icon && /*#__PURE__*/(0, _jsxRuntime.jsx)(item.icon, {})
132
+ })
133
+ }, item.label))
134
+ })
135
+ })]
136
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
137
+ className: "px-6 tablet:px-8 py-6 tablet:pt-6 tablet:pb-8",
138
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
139
+ className: "gap-4 flex flex-col",
140
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, {
141
+ variant: "secondary",
142
+ size: 44,
143
+ asChild: true,
144
+ className: "w-full",
145
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
146
+ href: subscribeUrl,
147
+ target: "_blank",
148
+ rel: "noopener noreferrer",
149
+ children: "\u8A02\u95B1\u96FB\u5B50\u5831"
150
+ })
151
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.default, {
152
+ variant: "primary",
153
+ size: 44,
154
+ asChild: true,
155
+ className: "w-full",
156
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
157
+ href: donateUrl,
158
+ target: "_blank",
159
+ rel: "noopener noreferrer",
160
+ children: "\u8D0A\u52A9\u6211\u5011"
161
+ })
162
+ })]
163
+ })
164
+ })]
165
+ })
166
+ })]
167
+ });
168
+ }
169
+ var _default = exports.default = Menu;
170
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["_interopRequireDefault","require","Object","defineProperty","exports","value","default","_image","_react","_button","_icons","_cn","_generateSocialMediaConfig","_sharedComponents","_headerMenuItem","_headerMenuItemGroup","_jsxRuntime","Divider","jsx","className","children","Menu","isOpen","onClose","keywords","menuItems","additionalMenuItems","socialMediaHrefs","donateUrl","subscribeUrl","searchPlaceholder","socialMediaConfig","generateSocialMediaConfig","useEffect","document","body","classList","add","remove","handleEscape","e","key","addEventListener","removeEventListener","jsxs","Fragment","cn","onClick","href","src","alt","height","width","loading","ClearIcon","SearchInputSection","mode","tags","isMenuOpen","contentClassName","slice","map","item","index","label","external","target","rel","icon","variant","size","asChild","_default"],"sources":["../../../src/header/menu/index.tsx"],"sourcesContent":["'use client'\n\nimport Image from 'next/image'\nimport { useEffect } from 'react'\n\nimport Button from '../../components/button'\nimport { ClearIcon } from '../../icons'\nimport type { MenuItem, SocialMediaHrefs } from '../../types'\nimport { cn } from '../../utils/cn'\nimport { generateSocialMediaConfig } from '../../utils/generate-social-media-config'\nimport { SearchInputSection } from '../shared-components'\nimport HeaderMenuItem from './header-menu-item'\nimport HeaderMenuItemGroup from './header-menu-item-group'\n\ntype MenuProps = {\n isOpen: boolean\n onClose: () => void\n keywords: string[]\n menuItems: MenuItem[]\n additionalMenuItems: MenuItem[]\n socialMediaHrefs: SocialMediaHrefs\n donateUrl: string\n subscribeUrl: string\n searchPlaceholder: string\n}\n\nfunction Divider() {\n return (\n <div className=\"px-6 tablet:px-8 py-4 w-full\">\n <div className=\"h-px w-full bg-neutral-300\"></div>\n </div>\n )\n}\n\nfunction Menu({\n isOpen,\n onClose,\n keywords,\n menuItems,\n additionalMenuItems,\n socialMediaHrefs,\n donateUrl,\n subscribeUrl,\n searchPlaceholder,\n}: MenuProps) {\n const socialMediaConfig = generateSocialMediaConfig(socialMediaHrefs)\n\n useEffect(() => {\n if (isOpen) {\n document.body.classList.add('no-scroll')\n } else {\n document.body.classList.remove('no-scroll')\n }\n\n return () => {\n document.body.classList.remove('no-scroll')\n }\n }, [isOpen])\n\n useEffect(() => {\n const handleEscape = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose()\n }\n }\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape)\n }\n\n return () => {\n document.removeEventListener('keydown', handleEscape)\n }\n }, [isOpen, onClose])\n\n return (\n <>\n {/* Overlay */}\n <div\n className={cn(\n 'inset-0 fixed z-1001 bg-neutral-500/50 transition-opacity duration-300',\n isOpen ? 'opacity-100' : 'pointer-events-none opacity-0'\n )}\n onClick={onClose}\n />\n\n {/* Menu */}\n <div\n className={cn(\n 'top-0 left-0 tablet:w-80 bg-white shadow-2xl ease-in-out scrollbar-thin tablet:pt-0 fixed z-1001 h-full w-full transform pt-(--mobile-header-height) transition-transform duration-300',\n isOpen ? 'translate-x-0' : '-translate-x-full'\n )}\n >\n <div className=\"flex h-full flex-col overflow-y-auto\">\n <div className=\"px-6 tablet:px-8 py-4 mt-4 hidden items-center justify-between tablet:flex\">\n <div className=\"flex items-center\">\n <a href=\"/\">\n <Image\n src=\"/assets/images/brand-icon.svg\"\n alt=\"少年報導者 The Reporter for Kids\"\n className=\"h-5\"\n height={20}\n width={183}\n loading=\"eager\"\n />\n </a>\n </div>\n <button\n onClick={onClose}\n className=\"w-8 h-8 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-colors duration-200 hover:text-neutral-800\"\n aria-label=\"關閉選單\"\n >\n <ClearIcon />\n </button>\n </div>\n\n <div className=\"px-6 tablet:px-8 pt-4 desktop:hidden\">\n <SearchInputSection\n mode=\"inline\"\n tags={keywords}\n searchPlaceholder={searchPlaceholder}\n />\n </div>\n\n <div className=\"py-4 flex-1\">\n <HeaderMenuItem {...menuItems?.[0]} />\n\n <Divider />\n\n {/* Categories */}\n <div className=\"py-2\">\n <HeaderMenuItemGroup isMenuOpen={isOpen} menuItems={menuItems} />\n </div>\n\n <Divider />\n\n {/* Reading Settings */}\n <HeaderMenuItem\n {...additionalMenuItems?.[0]}\n contentClassName=\"text-neutral-600 [&_span]:[font-family:var(--font-family-noto)] [&_span]:[font-size:var(--font-size-p2)] [&_span]:[font-weight:500] [&_span]:[line-height:var(--line-height-normal)] [&_span]:[letter-spacing:var(--letter-spacing-wide)] hover:text-neutral-900\"\n />\n\n <Divider />\n\n {/* About Us Section */}\n <div className=\"py-2\">\n {additionalMenuItems.slice(1).map((item, index) => (\n <HeaderMenuItem\n key={index}\n label={item.label}\n href={item.href}\n external={item.external}\n contentClassName=\"text-neutral-600 [&_span]:[font-family:var(--font-family-noto)] [&_span]:[font-size:var(--font-size-p2)] [&_span]:[font-weight:500] [&_span]:[line-height:var(--line-height-normal)] [&_span]:[letter-spacing:var(--letter-spacing-wide)] hover:text-neutral-900\"\n />\n ))}\n </div>\n\n <Divider />\n\n {/* Social Media */}\n <div className=\"px-6 tablet:px-8\">\n <div className=\"gap-4 tablet:gap-0 px-4 flex items-center justify-center tablet:justify-between\">\n {socialMediaConfig.map((item) => (\n <a\n key={item.label}\n href={item.href}\n className=\"text-neutral-900 transition-colors duration-200 hover:text-red-500\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={item.label}\n >\n <div className=\"w-6 h-6 flex items-center justify-center\">\n {item.icon && <item.icon />}\n </div>\n </a>\n ))}\n </div>\n </div>\n </div>\n\n {/* Action Buttons */}\n <div className=\"px-6 tablet:px-8 py-6 tablet:pt-6 tablet:pb-8\">\n <div className=\"gap-4 flex flex-col\">\n <Button variant=\"secondary\" size={44} asChild className=\"w-full\">\n <a\n href={subscribeUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n 訂閱電子報\n </a>\n </Button>\n <Button variant=\"primary\" size={44} asChild className=\"w-full\">\n <a href={donateUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n 贊助我們\n </a>\n </Button>\n </div>\n </div>\n </div>\n </div>\n </>\n )\n}\n\nexport default Menu\n"],"mappings":";AAAA,YAAY;;AAAA,IAAAA,sBAAA,GAAAC,OAAA;AAAAC,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAAAD,OAAA,CAAAE,OAAA;AAEZ,IAAAC,MAAA,GAAAP,sBAAA,CAAAC,OAAA;AACA,IAAAO,MAAA,GAAAP,OAAA;AAEA,IAAAQ,OAAA,GAAAT,sBAAA,CAAAC,OAAA;AACA,IAAAS,MAAA,GAAAT,OAAA;AAEA,IAAAU,GAAA,GAAAV,OAAA;AACA,IAAAW,0BAAA,GAAAX,OAAA;AACA,IAAAY,iBAAA,GAAAZ,OAAA;AACA,IAAAa,eAAA,GAAAd,sBAAA,CAAAC,OAAA;AACA,IAAAc,oBAAA,GAAAf,sBAAA,CAAAC,OAAA;AAA0D,IAAAe,WAAA,GAAAf,OAAA;AAc1D,SAASgB,OAAOA,CAAA,EAAG;EACjB,oBACE,IAAAD,WAAA,CAAAE,GAAA;IAAKC,SAAS,EAAC,8BAA8B;IAAAC,QAAA,eAC3C,IAAAJ,WAAA,CAAAE,GAAA;MAAKC,SAAS,EAAC;IAA4B,CAAM;EAAC,CAC/C,CAAC;AAEV;AAEA,SAASE,IAAIA,CAAC;EACZC,MAAM;EACNC,OAAO;EACPC,QAAQ;EACRC,SAAS;EACTC,mBAAmB;EACnBC,gBAAgB;EAChBC,SAAS;EACTC,YAAY;EACZC;AACS,CAAC,EAAE;EACZ,MAAMC,iBAAiB,GAAG,IAAAC,oDAAyB,EAACL,gBAAgB,CAAC;EAErE,IAAAM,gBAAS,EAAC,MAAM;IACd,IAAIX,MAAM,EAAE;MACVY,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACC,GAAG,CAAC,WAAW,CAAC;IAC1C,CAAC,MAAM;MACLH,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACE,MAAM,CAAC,WAAW,CAAC;IAC7C;IAEA,OAAO,MAAM;MACXJ,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACE,MAAM,CAAC,WAAW,CAAC;IAC7C,CAAC;EACH,CAAC,EAAE,CAAChB,MAAM,CAAC,CAAC;EAEZ,IAAAW,gBAAS,EAAC,MAAM;IACd,MAAMM,YAAY,GAAIC,CAAgB,IAAK;MACzC,IAAIA,CAAC,CAACC,GAAG,KAAK,QAAQ,EAAE;QACtBlB,OAAO,CAAC,CAAC;MACX;IACF,CAAC;IAED,IAAID,MAAM,EAAE;MACVY,QAAQ,CAACQ,gBAAgB,CAAC,SAAS,EAAEH,YAAY,CAAC;IACpD;IAEA,OAAO,MAAM;MACXL,QAAQ,CAACS,mBAAmB,CAAC,SAAS,EAAEJ,YAAY,CAAC;IACvD,CAAC;EACH,CAAC,EAAE,CAACjB,MAAM,EAAEC,OAAO,CAAC,CAAC;EAErB,oBACE,IAAAP,WAAA,CAAA4B,IAAA,EAAA5B,WAAA,CAAA6B,QAAA;IAAAzB,QAAA,gBAEE,IAAAJ,WAAA,CAAAE,GAAA;MACEC,SAAS,EAAE,IAAA2B,MAAE,EACX,wEAAwE,EACxExB,MAAM,GAAG,aAAa,GAAG,+BAC3B,CAAE;MACFyB,OAAO,EAAExB;IAAQ,CAClB,CAAC,eAGF,IAAAP,WAAA,CAAAE,GAAA;MACEC,SAAS,EAAE,IAAA2B,MAAE,EACX,wLAAwL,EACxLxB,MAAM,GAAG,eAAe,GAAG,mBAC7B,CAAE;MAAAF,QAAA,eAEF,IAAAJ,WAAA,CAAA4B,IAAA;QAAKzB,SAAS,EAAC,sCAAsC;QAAAC,QAAA,gBACnD,IAAAJ,WAAA,CAAA4B,IAAA;UAAKzB,SAAS,EAAC,4EAA4E;UAAAC,QAAA,gBACzF,IAAAJ,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,mBAAmB;YAAAC,QAAA,eAChC,IAAAJ,WAAA,CAAAE,GAAA;cAAG8B,IAAI,EAAC,GAAG;cAAA5B,QAAA,eACT,IAAAJ,WAAA,CAAAE,GAAA,EAACX,MAAA,CAAAD,OAAK;gBACJ2C,GAAG,EAAC,+BAA+B;gBACnCC,GAAG,EAAC,sDAA6B;gBACjC/B,SAAS,EAAC,KAAK;gBACfgC,MAAM,EAAE,EAAG;gBACXC,KAAK,EAAE,GAAI;gBACXC,OAAO,EAAC;cAAO,CAChB;YAAC,CACD;UAAC,CACD,CAAC,eACN,IAAArC,WAAA,CAAAE,GAAA;YACE6B,OAAO,EAAExB,OAAQ;YACjBJ,SAAS,EAAC,6IAA6I;YACvJ,cAAW,0BAAM;YAAAC,QAAA,eAEjB,IAAAJ,WAAA,CAAAE,GAAA,EAACR,MAAA,CAAA4C,SAAS,IAAE;UAAC,CACP,CAAC;QAAA,CACN,CAAC,eAEN,IAAAtC,WAAA,CAAAE,GAAA;UAAKC,SAAS,EAAC,sCAAsC;UAAAC,QAAA,eACnD,IAAAJ,WAAA,CAAAE,GAAA,EAACL,iBAAA,CAAA0C,kBAAkB;YACjBC,IAAI,EAAC,QAAQ;YACbC,IAAI,EAAEjC,QAAS;YACfM,iBAAiB,EAAEA;UAAkB,CACtC;QAAC,CACC,CAAC,eAEN,IAAAd,WAAA,CAAA4B,IAAA;UAAKzB,SAAS,EAAC,aAAa;UAAAC,QAAA,gBAC1B,IAAAJ,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAR,OAAc;YAAA,GAAKmB,SAAS,GAAG,CAAC;UAAC,CAAG,CAAC,eAEtC,IAAAT,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,MAAM;YAAAC,QAAA,eACnB,IAAAJ,WAAA,CAAAE,GAAA,EAACH,oBAAA,CAAAT,OAAmB;cAACoD,UAAU,EAAEpC,MAAO;cAACG,SAAS,EAAEA;YAAU,CAAE;UAAC,CAC9D,CAAC,eAEN,IAAAT,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAR,OAAc;YAAA,GACToB,mBAAmB,GAAG,CAAC,CAAC;YAC5BiC,gBAAgB,EAAC;UAAkQ,CACpR,CAAC,eAEF,IAAA3C,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,MAAM;YAAAC,QAAA,EAClBM,mBAAmB,CAACkC,KAAK,CAAC,CAAC,CAAC,CAACC,GAAG,CAAC,CAACC,IAAI,EAAEC,KAAK,kBAC5C,IAAA/C,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAR,OAAc;cAEb0D,KAAK,EAAEF,IAAI,CAACE,KAAM;cAClBhB,IAAI,EAAEc,IAAI,CAACd,IAAK;cAChBiB,QAAQ,EAAEH,IAAI,CAACG,QAAS;cACxBN,gBAAgB,EAAC;YAAkQ,GAJ9QI,KAKN,CACF;UAAC,CACC,CAAC,eAEN,IAAA/C,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,kBAAkB;YAAAC,QAAA,eAC/B,IAAAJ,WAAA,CAAAE,GAAA;cAAKC,SAAS,EAAC,iFAAiF;cAAAC,QAAA,EAC7FW,iBAAiB,CAAC8B,GAAG,CAAEC,IAAI,iBAC1B,IAAA9C,WAAA,CAAAE,GAAA;gBAEE8B,IAAI,EAAEc,IAAI,CAACd,IAAK;gBAChB7B,SAAS,EAAC,oEAAoE;gBAC9E+C,MAAM,EAAC,QAAQ;gBACfC,GAAG,EAAC,qBAAqB;gBACzB,cAAYL,IAAI,CAACE,KAAM;gBAAA5C,QAAA,eAEvB,IAAAJ,WAAA,CAAAE,GAAA;kBAAKC,SAAS,EAAC,0CAA0C;kBAAAC,QAAA,EACtD0C,IAAI,CAACM,IAAI,iBAAI,IAAApD,WAAA,CAAAE,GAAA,EAAC4C,IAAI,CAACM,IAAI,IAAE;gBAAC,CACxB;cAAC,GATDN,IAAI,CAACE,KAUT,CACJ;YAAC,CACC;UAAC,CACH,CAAC;QAAA,CACH,CAAC,eAGN,IAAAhD,WAAA,CAAAE,GAAA;UAAKC,SAAS,EAAC,+CAA+C;UAAAC,QAAA,eAC5D,IAAAJ,WAAA,CAAA4B,IAAA;YAAKzB,SAAS,EAAC,qBAAqB;YAAAC,QAAA,gBAClC,IAAAJ,WAAA,CAAAE,GAAA,EAACT,OAAA,CAAAH,OAAM;cAAC+D,OAAO,EAAC,WAAW;cAACC,IAAI,EAAE,EAAG;cAACC,OAAO;cAACpD,SAAS,EAAC,QAAQ;cAAAC,QAAA,eAC9D,IAAAJ,WAAA,CAAAE,GAAA;gBACE8B,IAAI,EAAEnB,YAAa;gBACnBqC,MAAM,EAAC,QAAQ;gBACfC,GAAG,EAAC,qBAAqB;gBAAA/C,QAAA,EAC1B;cAED,CAAG;YAAC,CACE,CAAC,eACT,IAAAJ,WAAA,CAAAE,GAAA,EAACT,OAAA,CAAAH,OAAM;cAAC+D,OAAO,EAAC,SAAS;cAACC,IAAI,EAAE,EAAG;cAACC,OAAO;cAACpD,SAAS,EAAC,QAAQ;cAAAC,QAAA,eAC5D,IAAAJ,WAAA,CAAAE,GAAA;gBAAG8B,IAAI,EAAEpB,SAAU;gBAACsC,MAAM,EAAC,QAAQ;gBAACC,GAAG,EAAC,qBAAqB;gBAAA/C,QAAA,EAAC;cAE9D,CAAG;YAAC,CACE,CAAC;UAAA,CACN;QAAC,CACH,CAAC;MAAA,CACH;IAAC,CACH,CAAC;EAAA,CACN,CAAC;AAEP;AAAC,IAAAoD,QAAA,GAAApE,OAAA,CAAAE,OAAA,GAEce,IAAI"}
@@ -0,0 +1,9 @@
1
+ type MobileHeaderProps = {
2
+ onHamburgerOverlayOpen: () => void;
3
+ onCloseMenu: () => void;
4
+ showCloseButtonWhenMenuOpen: boolean;
5
+ isMenuOpen: boolean;
6
+ };
7
+ export declare function MobileHeader({ onHamburgerOverlayOpen, onCloseMenu, showCloseButtonWhenMenuOpen, isMenuOpen, }: MobileHeaderProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
9
+ //# sourceMappingURL=mobile-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-header.d.ts","sourceRoot":"","sources":["../../src/header/mobile-header.tsx"],"names":[],"mappings":"AAMA,KAAK,iBAAiB,GAAG;IACvB,sBAAsB,EAAE,MAAM,IAAI,CAAA;IAClC,WAAW,EAAE,MAAM,IAAI,CAAA;IACvB,2BAA2B,EAAE,OAAO,CAAA;IACpC,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,sBAAsB,EACtB,WAAW,EACX,2BAA2B,EAC3B,UAAU,GACX,EAAE,iBAAiB,2CA0CnB"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.MobileHeader = MobileHeader;
8
+ var _icons = require("../icons");
9
+ var _cn = require("../utils/cn");
10
+ var _sharedComponents = require("./shared-components");
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ function MobileHeader({
13
+ onHamburgerOverlayOpen,
14
+ onCloseMenu,
15
+ showCloseButtonWhenMenuOpen,
16
+ isMenuOpen
17
+ }) {
18
+ const showCloseButton = showCloseButtonWhenMenuOpen && isMenuOpen;
19
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
20
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
21
+ className: "h-(--mobile-header-height) desktop:hidden"
22
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
23
+ className: (0, _cn.cn)('px-6 tablet:px-8 ease-in-out top-0 translate-y-0 pointer-events-auto fixed z-1002 w-full bg-neutral-white opacity-100 transition-all duration-300 tablet:z-1000 desktop:hidden'),
24
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
25
+ className: "py-4 flex items-center justify-between",
26
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedComponents.LogoLink, {}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
27
+ className: "gap-4 flex items-center",
28
+ children: [!showCloseButton && /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
29
+ href: "/login",
30
+ className: "w-8 h-8 flex items-center justify-center rounded-full text-red-400 transition-colors duration-200 hover:text-red-500",
31
+ "aria-label": "\u767B\u5165",
32
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.LoginIcon, {})
33
+ }), showCloseButton ? /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
34
+ onClick: onCloseMenu,
35
+ className: "w-8 h-8 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-colors duration-200 hover:text-neutral-800",
36
+ "aria-label": "\u95DC\u9589\u9078\u55AE",
37
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.ClearIcon, {})
38
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedComponents.HamburgerButton, {
39
+ onHamburgerOverlayOpen: onHamburgerOverlayOpen
40
+ })]
41
+ })]
42
+ })
43
+ })]
44
+ });
45
+ }
46
+ //# sourceMappingURL=mobile-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-header.js","names":["Object","defineProperty","exports","value","MobileHeader","_icons","require","_cn","_sharedComponents","_jsxRuntime","onHamburgerOverlayOpen","onCloseMenu","showCloseButtonWhenMenuOpen","isMenuOpen","showCloseButton","jsxs","Fragment","children","jsx","className","cn","LogoLink","href","LoginIcon","onClick","ClearIcon","HamburgerButton"],"sources":["../../src/header/mobile-header.tsx"],"sourcesContent":["'use client'\n\nimport { ClearIcon, LoginIcon } from '../icons'\nimport { cn } from '../utils/cn'\nimport { HamburgerButton, LogoLink } from './shared-components'\n\ntype MobileHeaderProps = {\n onHamburgerOverlayOpen: () => void\n onCloseMenu: () => void\n showCloseButtonWhenMenuOpen: boolean\n isMenuOpen: boolean\n}\n\nexport function MobileHeader({\n onHamburgerOverlayOpen,\n onCloseMenu,\n showCloseButtonWhenMenuOpen,\n isMenuOpen,\n}: MobileHeaderProps) {\n const showCloseButton = showCloseButtonWhenMenuOpen && isMenuOpen\n\n return (\n <>\n <div className=\"h-(--mobile-header-height) desktop:hidden\"></div>\n <div\n className={cn(\n 'px-6 tablet:px-8 ease-in-out top-0 translate-y-0 pointer-events-auto fixed z-1002 w-full bg-neutral-white opacity-100 transition-all duration-300 tablet:z-1000 desktop:hidden'\n )}\n >\n <div className=\"py-4 flex items-center justify-between\">\n <LogoLink />\n\n <div className=\"gap-4 flex items-center\">\n {!showCloseButton && (\n <a\n href=\"/login\"\n className=\"w-8 h-8 flex items-center justify-center rounded-full text-red-400 transition-colors duration-200 hover:text-red-500\"\n aria-label=\"登入\"\n >\n <LoginIcon />\n </a>\n )}\n {showCloseButton ? (\n <button\n onClick={onCloseMenu}\n className=\"w-8 h-8 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-colors duration-200 hover:text-neutral-800\"\n aria-label=\"關閉選單\"\n >\n <ClearIcon />\n </button>\n ) : (\n <HamburgerButton\n onHamburgerOverlayOpen={onHamburgerOverlayOpen}\n />\n )}\n </div>\n </div>\n </div>\n </>\n )\n}\n"],"mappings":";AAAA,YAAY;;AAAAA,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAAAD,OAAA,CAAAE,YAAA,GAAAA,YAAA;AAEZ,IAAAC,MAAA,GAAAC,OAAA;AACA,IAAAC,GAAA,GAAAD,OAAA;AACA,IAAAE,iBAAA,GAAAF,OAAA;AAA+D,IAAAG,WAAA,GAAAH,OAAA;AASxD,SAASF,YAAYA,CAAC;EAC3BM,sBAAsB;EACtBC,WAAW;EACXC,2BAA2B;EAC3BC;AACiB,CAAC,EAAE;EACpB,MAAMC,eAAe,GAAGF,2BAA2B,IAAIC,UAAU;EAEjE,oBACE,IAAAJ,WAAA,CAAAM,IAAA,EAAAN,WAAA,CAAAO,QAAA;IAAAC,QAAA,gBACE,IAAAR,WAAA,CAAAS,GAAA;MAAKC,SAAS,EAAC;IAA2C,CAAM,CAAC,eACjE,IAAAV,WAAA,CAAAS,GAAA;MACEC,SAAS,EAAE,IAAAC,MAAE,EACX,gLACF,CAAE;MAAAH,QAAA,eAEF,IAAAR,WAAA,CAAAM,IAAA;QAAKI,SAAS,EAAC,wCAAwC;QAAAF,QAAA,gBACrD,IAAAR,WAAA,CAAAS,GAAA,EAACV,iBAAA,CAAAa,QAAQ,IAAE,CAAC,eAEZ,IAAAZ,WAAA,CAAAM,IAAA;UAAKI,SAAS,EAAC,yBAAyB;UAAAF,QAAA,GACrC,CAACH,eAAe,iBACf,IAAAL,WAAA,CAAAS,GAAA;YACEI,IAAI,EAAC,QAAQ;YACbH,SAAS,EAAC,sHAAsH;YAChI,cAAW,cAAI;YAAAF,QAAA,eAEf,IAAAR,WAAA,CAAAS,GAAA,EAACb,MAAA,CAAAkB,SAAS,IAAE;UAAC,CACZ,CACJ,EACAT,eAAe,gBACd,IAAAL,WAAA,CAAAS,GAAA;YACEM,OAAO,EAAEb,WAAY;YACrBQ,SAAS,EAAC,6IAA6I;YACvJ,cAAW,0BAAM;YAAAF,QAAA,eAEjB,IAAAR,WAAA,CAAAS,GAAA,EAACb,MAAA,CAAAoB,SAAS,IAAE;UAAC,CACP,CAAC,gBAET,IAAAhB,WAAA,CAAAS,GAAA,EAACV,iBAAA,CAAAkB,eAAe;YACdhB,sBAAsB,EAAEA;UAAuB,CAChD,CACF;QAAA,CACE,CAAC;MAAA,CACH;IAAC,CACH,CAAC;EAAA,CACN,CAAC;AAEP"}
@@ -0,0 +1,6 @@
1
+ type PostTitleSetterProps = {
2
+ postTitle?: string;
3
+ };
4
+ declare function PostTitleSetter({ postTitle }: PostTitleSetterProps): null;
5
+ export default PostTitleSetter;
6
+ //# sourceMappingURL=post-title-setter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-title-setter.d.ts","sourceRoot":"","sources":["../../src/header/post-title-setter.tsx"],"names":[],"mappings":"AAMA,KAAK,oBAAoB,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,EAAE,oBAAoB,QAS3D;AAED,eAAe,eAAe,CAAA"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = require("react");
9
+ var _headerContext = require("./header-context");
10
+ function PostTitleSetter({
11
+ postTitle
12
+ }) {
13
+ const context = (0, _headerContext.useHeaderContext)();
14
+ const setPostTitle = context?.setPostTitle;
15
+ (0, _react.useEffect)(() => {
16
+ setPostTitle?.(postTitle);
17
+ return () => setPostTitle?.(undefined);
18
+ }, [postTitle, setPostTitle]);
19
+ return null;
20
+ }
21
+ var _default = exports.default = PostTitleSetter;
22
+ //# sourceMappingURL=post-title-setter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-title-setter.js","names":["Object","defineProperty","exports","value","default","_react","require","_headerContext","PostTitleSetter","postTitle","context","useHeaderContext","setPostTitle","useEffect","undefined","_default"],"sources":["../../src/header/post-title-setter.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport { useHeaderContext } from './header-context'\n\ntype PostTitleSetterProps = {\n postTitle?: string\n}\n\nfunction PostTitleSetter({ postTitle }: PostTitleSetterProps) {\n const context = useHeaderContext()\n const setPostTitle = context?.setPostTitle\n useEffect(() => {\n setPostTitle?.(postTitle)\n return () => setPostTitle?.(undefined)\n }, [postTitle, setPostTitle])\n\n return null\n}\n\nexport default PostTitleSetter\n"],"mappings":";AAAA,YAAY;;AAAAA,MAAA,CAAAC,cAAA,CAAAC,OAAA;EAAAC,KAAA;AAAA;AAAAD,OAAA,CAAAE,OAAA;AAEZ,IAAAC,MAAA,GAAAC,OAAA;AAEA,IAAAC,cAAA,GAAAD,OAAA;AAMA,SAASE,eAAeA,CAAC;EAAEC;AAAgC,CAAC,EAAE;EAC5D,MAAMC,OAAO,GAAG,IAAAC,+BAAgB,EAAC,CAAC;EAClC,MAAMC,YAAY,GAAGF,OAAO,EAAEE,YAAY;EAC1C,IAAAC,gBAAS,EAAC,MAAM;IACdD,YAAY,GAAGH,SAAS,CAAC;IACzB,OAAO,MAAMG,YAAY,GAAGE,SAAS,CAAC;EACxC,CAAC,EAAE,CAACL,SAAS,EAAEG,YAAY,CAAC,CAAC;EAE7B,OAAO,IAAI;AACb;AAAC,IAAAG,QAAA,GAAAb,OAAA,CAAAE,OAAA,GAEcI,eAAe"}
@@ -0,0 +1,31 @@
1
+ import type { MenuItem } from '../types';
2
+ export declare function LogoLink({ compactMode }: {
3
+ compactMode?: boolean;
4
+ }): import("react/jsx-runtime").JSX.Element;
5
+ type SearchInputSectionProps = {
6
+ mode: 'popover';
7
+ isSearchOpen: boolean;
8
+ tags: string[];
9
+ searchPlaceholder: string;
10
+ } | {
11
+ mode: 'inline';
12
+ tags: string[];
13
+ searchPlaceholder: string;
14
+ };
15
+ export declare function SearchInputSection(props: SearchInputSectionProps): import("react/jsx-runtime").JSX.Element;
16
+ export declare function ActionButtons({ hideCtaButtons, tags, searchPlaceholder, subscribeUrl, }: {
17
+ hideCtaButtons?: boolean;
18
+ tags: string[];
19
+ searchPlaceholder: string;
20
+ subscribeUrl: string;
21
+ }): import("react/jsx-runtime").JSX.Element;
22
+ export declare function BottomNavigation({ onHamburgerOverlayOpen, menuItems, }: {
23
+ onHamburgerOverlayOpen: () => void;
24
+ menuItems: MenuItem[];
25
+ }): import("react/jsx-runtime").JSX.Element;
26
+ export declare function HamburgerButton({ onHamburgerOverlayOpen, small, }: {
27
+ onHamburgerOverlayOpen: () => void;
28
+ small?: boolean;
29
+ }): import("react/jsx-runtime").JSX.Element;
30
+ export {};
31
+ //# sourceMappingURL=shared-components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-components.d.ts","sourceRoot":"","sources":["../../src/header/shared-components.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AA2ExC,wBAAgB,QAAQ,CAAC,EAAE,WAAmB,EAAE,EAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,2CAgB1E;AAED,KAAK,uBAAuB,GACxB;IACE,IAAI,EAAE,SAAS,CAAA;IACf,YAAY,EAAE,OAAO,CAAA;IACrB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAA;CAC1B,GACD;IACE,IAAI,EAAE,QAAQ,CAAA;IACd,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAEL,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,2CAwEhE;AAED,wBAAgB,aAAa,CAAC,EAC5B,cAAsB,EACtB,IAAI,EACJ,iBAAiB,EACjB,YAAY,GACb,EAAE;IACD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;CACrB,2CAkEA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,sBAAsB,EACtB,SAAS,GACV,EAAE;IACD,sBAAsB,EAAE,MAAM,IAAI,CAAA;IAClC,SAAS,EAAE,QAAQ,EAAE,CAAA;CACtB,2CA4BA;AAED,wBAAgB,eAAe,CAAC,EAC9B,sBAAsB,EACtB,KAAa,GACd,EAAE;IACD,sBAAsB,EAAE,MAAM,IAAI,CAAA;IAClC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB,2CAYA"}
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+ 'use client';
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.ActionButtons = ActionButtons;
9
+ exports.BottomNavigation = BottomNavigation;
10
+ exports.HamburgerButton = HamburgerButton;
11
+ exports.LogoLink = LogoLink;
12
+ exports.SearchInputSection = SearchInputSection;
13
+ var _classVarianceAuthority = require("class-variance-authority");
14
+ var _image = _interopRequireDefault(require("next/image"));
15
+ var _react = require("react");
16
+ var _components = require("../components");
17
+ var _icons = require("../icons");
18
+ var _cn = require("../utils/cn");
19
+ var _jsxRuntime = require("react/jsx-runtime");
20
+ const searchFormVariants = (0, _classVarianceAuthority.cva)('ease-in-out h-full transition-all duration-300', {
21
+ variants: {
22
+ mode: {
23
+ inline: 'h-11 w-full',
24
+ popover: 'top-0 -right-4 w-66 absolute overflow-hidden opacity-0'
25
+ },
26
+ isSearchOpen: {
27
+ true: '',
28
+ false: ''
29
+ }
30
+ },
31
+ compoundVariants: [{
32
+ mode: 'popover',
33
+ isSearchOpen: true,
34
+ class: 'w-66 pointer-events-auto opacity-100'
35
+ }, {
36
+ mode: 'popover',
37
+ isSearchOpen: false,
38
+ class: 'pointer-events-none'
39
+ }]
40
+ });
41
+ const searchDropdownVariants = (0, _classVarianceAuthority.cva)('rounded-xl mt-2 w-66 ease-in-out h-0 p-0 z-50 bg-neutral-white opacity-0 transition-all duration-200', {
42
+ variants: {
43
+ mode: {
44
+ inline: '',
45
+ popover: 'top-12 -right-4 shadow-custom p-4 absolute'
46
+ },
47
+ isSearchOpen: {
48
+ true: '',
49
+ false: ''
50
+ },
51
+ isFocused: {
52
+ true: '',
53
+ false: ''
54
+ }
55
+ },
56
+ compoundVariants: [{
57
+ mode: 'popover',
58
+ isSearchOpen: true,
59
+ isFocused: true,
60
+ class: 'p-4 h-min opacity-100'
61
+ }, {
62
+ mode: 'popover',
63
+ isSearchOpen: false,
64
+ class: 'pointer-events-none'
65
+ }, {
66
+ mode: 'inline',
67
+ isFocused: true,
68
+ class: 'translate-y-0 pt-6 mt-0 bg-neutral-transparent h-min w-full opacity-100'
69
+ }, {
70
+ mode: 'inline',
71
+ isFocused: false,
72
+ class: '-translate-y-3 pointer-events-none w-full'
73
+ }]
74
+ });
75
+ function LogoLink({
76
+ compactMode = false
77
+ }) {
78
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
79
+ href: "/",
80
+ className: "flex items-center",
81
+ rel: "home",
82
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_image.default, {
83
+ src: "/assets/images/brand-icon.svg",
84
+ alt: "\u5C11\u5E74\u5831\u5C0E\u8005 The Reporter for Kids",
85
+ loading: "eager",
86
+ className: (0, _cn.cn)('h-5 tablet:h-6 desktop:h-8 ease-in-out w-auto transition-all duration-500', compactMode && 'desktop:h-[26px]'),
87
+ width: 293,
88
+ height: 32
89
+ })
90
+ });
91
+ }
92
+ function SearchInputSection(props) {
93
+ const ref = (0, _react.useRef)(null);
94
+ const [isFocused, setIsFocused] = (0, _react.useState)(false);
95
+ const [searchValue, setSearchValue] = (0, _react.useState)('');
96
+ const mode = props.mode;
97
+ const isSearchOpen = mode === 'popover' && props.isSearchOpen;
98
+ const tags = props.tags;
99
+ const searchPlaceholder = props.searchPlaceholder;
100
+ (0, _react.useEffect)(() => {
101
+ if (mode === 'inline') {
102
+ return;
103
+ }
104
+ if (isSearchOpen) {
105
+ ref.current?.focus();
106
+ setIsFocused(true);
107
+ document.body.classList.add('no-scroll');
108
+ return;
109
+ }
110
+ setIsFocused(false);
111
+ document.body.classList.remove('no-scroll');
112
+ }, [mode, isSearchOpen]);
113
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
114
+ onFocus: () => setIsFocused(true),
115
+ onBlur: () => setIsFocused(false),
116
+ className: mode === 'inline' ? 'relative w-full' : 'h-11',
117
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("form", {
118
+ role: "search",
119
+ method: "get",
120
+ action: "/search",
121
+ className: searchFormVariants({
122
+ mode,
123
+ isSearchOpen: mode === 'popover' ? isSearchOpen : undefined
124
+ }),
125
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Input, {
126
+ placeholder: searchPlaceholder,
127
+ name: "q",
128
+ title: "Search for...",
129
+ "aria-label": "Search for...",
130
+ className: "w-[99%]",
131
+ inputRef: ref,
132
+ onChange: setSearchValue,
133
+ value: searchValue
134
+ })
135
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
136
+ className: searchDropdownVariants({
137
+ mode,
138
+ isSearchOpen: mode === 'popover' ? isSearchOpen : undefined,
139
+ isFocused
140
+ }),
141
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h3", {
142
+ className: "prose-p3 font-bold mb-3 text-neutral-700",
143
+ children: "\u71B1\u9580\u641C\u5C0B"
144
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
145
+ className: "gap-2.5 flex flex-wrap",
146
+ children: tags.map(keyword => /*#__PURE__*/(0, _jsxRuntime.jsxs)("a", {
147
+ className: "px-3 py-1 prose-p2 font-bold cursor-pointer rounded-full bg-neutral-200 text-neutral-900 transition-colors duration-200 hover:bg-red-500 hover:text-neutral-white",
148
+ href: `/search?q=${encodeURIComponent(keyword)}`,
149
+ children: ["#", keyword]
150
+ }, keyword))
151
+ })]
152
+ })]
153
+ });
154
+ }
155
+ function ActionButtons({
156
+ hideCtaButtons = false,
157
+ tags,
158
+ searchPlaceholder,
159
+ subscribeUrl
160
+ }) {
161
+ const [isSearchOpen, setIsSearchOpen] = (0, _react.useState)(false);
162
+ const containerRef = (0, _react.useRef)(null);
163
+ const buttonRef = (0, _react.useRef)(null);
164
+ (0, _react.useEffect)(() => {
165
+ const handleClickOutside = event => {
166
+ const containerElement = containerRef.current;
167
+ const buttonElement = buttonRef.current;
168
+ if (!containerElement || !buttonElement) return;
169
+ if (!containerElement.contains(event.target) && !buttonElement.contains(event.target)) {
170
+ setIsSearchOpen(false);
171
+ }
172
+ };
173
+ document.addEventListener('mousedown', handleClickOutside);
174
+ return () => {
175
+ document.removeEventListener('mousedown', handleClickOutside);
176
+ };
177
+ }, []);
178
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
179
+ className: "relative flex items-center",
180
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
181
+ className: "mr-6 relative flex items-center",
182
+ ref: containerRef,
183
+ children: [!hideCtaButtons && !isSearchOpen && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
184
+ className: "gap-4 flex items-center",
185
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
186
+ variant: "secondary",
187
+ size: 32,
188
+ asChild: true,
189
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
190
+ href: "/about#post",
191
+ children: "\u6295\u7A3F"
192
+ })
193
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Button, {
194
+ variant: "primary",
195
+ size: 32,
196
+ asChild: true,
197
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
198
+ href: subscribeUrl,
199
+ target: "_blank",
200
+ rel: "noopener noreferrer",
201
+ children: "\u8A02\u95B1"
202
+ })
203
+ })]
204
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(SearchInputSection, {
205
+ isSearchOpen: isSearchOpen,
206
+ mode: "popover",
207
+ tags: tags,
208
+ searchPlaceholder: searchPlaceholder
209
+ })]
210
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
211
+ className: "w-8 h-8 mr-4 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-all duration-200 hover:text-neutral-800",
212
+ "aria-label": "\u641C\u5C0B",
213
+ onClick: () => setIsSearchOpen(!isSearchOpen),
214
+ ref: buttonRef,
215
+ children: isSearchOpen ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.ClearIcon, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.SearchIcon, {})
216
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
217
+ className: "w-8 h-8 flex cursor-pointer items-center justify-center rounded-full text-neutral-600 transition-all duration-200 hover:text-neutral-800",
218
+ "aria-label": "\u8A2D\u5B9A",
219
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.SettingsIcon, {})
220
+ })]
221
+ });
222
+ }
223
+ function BottomNavigation({
224
+ onHamburgerOverlayOpen,
225
+ menuItems
226
+ }) {
227
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
228
+ className: "py-2 px-4 flex w-full items-center justify-between border-y border-neutral-border",
229
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(HamburgerButton, {
230
+ onHamburgerOverlayOpen: onHamburgerOverlayOpen,
231
+ small: true
232
+ }), menuItems.reduce((acc, item, index) => {
233
+ return [...acc, /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
234
+ className: "flex items-center",
235
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
236
+ href: item.href,
237
+ className: "py-1 prose-p1 font-bold! h-6 flex items-center text-neutral-900 transition-colors hover:text-red-400",
238
+ children: item.label
239
+ })
240
+ }, item.label), ...(index < menuItems.length - 1 ? [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
241
+ className: "h-4 mx-2 w-px bg-neutral-border"
242
+ }, `separator-${index}`)] : [])];
243
+ }, [])]
244
+ });
245
+ }
246
+ function HamburgerButton({
247
+ onHamburgerOverlayOpen,
248
+ small = false
249
+ }) {
250
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("button", {
251
+ className: (0, _cn.cn)('rounded-sm ease-in-out flex cursor-pointer items-center justify-center transition-all duration-300 hover:[&>svg>path:nth-child(1)]:fill-blue-500 hover:[&>svg>path:nth-child(2)]:fill-red-500 hover:[&>svg>path:nth-child(3)]:fill-yellow-500 hover:[&>svg>rect:nth-child(1)]:fill-blue-500 hover:[&>svg>rect:nth-child(2)]:fill-red-500 hover:[&>svg>rect:nth-child(3)]:fill-yellow-500', small ? 'w-6 h-6' : 'w-8 h-8'),
252
+ onClick: onHamburgerOverlayOpen,
253
+ children: small ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.HamburgerIconSmall, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.HamburgerIcon, {})
254
+ });
255
+ }
256
+ //# sourceMappingURL=shared-components.js.map