@kids-reporter/routing-ui 0.1.16 → 0.1.18
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.
- package/dist/header/menu/index.d.ts.map +1 -1
- package/dist/header/menu/index.js +5 -10
- package/dist/header/menu/index.js.map +1 -1
- package/dist/header/shared-components.d.ts.map +1 -1
- package/dist/header/shared-components.js +5 -2
- package/dist/header/shared-components.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-body-scroll-lock.d.ts +6 -0
- package/dist/hooks/use-body-scroll-lock.d.ts.map +1 -0
- package/dist/hooks/use-body-scroll-lock.js +28 -0
- package/dist/hooks/use-body-scroll-lock.js.map +1 -0
- package/dist/styles.css +4 -1
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/cn.js +1 -2
- package/dist/utils/cn.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/header/menu/index.tsx"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
8
8
|
exports.default = void 0;
|
|
9
9
|
var _react = require("react");
|
|
10
10
|
var _button = _interopRequireDefault(require("../../components/button"));
|
|
11
|
+
var _hooks = require("../../hooks");
|
|
11
12
|
var _icons = require("../../icons");
|
|
12
13
|
var _cn = require("../../utils/cn");
|
|
13
14
|
var _generateSocialMediaConfig = require("../../utils/generate-social-media-config");
|
|
@@ -35,16 +36,10 @@ function Menu({
|
|
|
35
36
|
searchPlaceholder
|
|
36
37
|
}) {
|
|
37
38
|
const socialMediaConfig = (0, _generateSocialMediaConfig.generateSocialMediaConfig)(socialMediaHrefs);
|
|
38
|
-
(0,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
document.body.classList.remove('no-scroll');
|
|
43
|
-
}
|
|
44
|
-
return () => {
|
|
45
|
-
document.body.classList.remove('no-scroll');
|
|
46
|
-
};
|
|
47
|
-
}, [isOpen]);
|
|
39
|
+
(0, _hooks.useBodyScrollLock)({
|
|
40
|
+
toLock: isOpen,
|
|
41
|
+
lockID: 'header-menu'
|
|
42
|
+
});
|
|
48
43
|
(0, _react.useEffect)(() => {
|
|
49
44
|
const handleEscape = e => {
|
|
50
45
|
if (e.key === 'Escape') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["_interopRequireDefault","require","Object","defineProperty","exports","value","default","_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","slice","contentClassName","map","item","label","external","target","rel","icon","variant","size","asChild","_default"],"sources":["../../../src/header/menu/index.tsx"],"sourcesContent":["'use client'\n\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-overlay 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 tablet:pt-0 fixed z-overlay h-full scrollbar-thin 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 <img\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 {/* Categories */}\n <div className=\"py-2\">\n <HeaderMenuItemGroup\n isMenuOpen={isOpen}\n menuItems={menuItems.slice(1)}\n />\n </div>\n\n <Divider />\n\n {/* My Reading */}\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 {/* Reading Settings */}\n <HeaderMenuItem\n {...additionalMenuItems?.[1]}\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(2).map((item) => (\n <HeaderMenuItem\n key={item.label}\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,GAAAN,OAAA;AAEA,IAAAO,OAAA,GAAAR,sBAAA,CAAAC,OAAA;AACA,IAAAQ,MAAA,GAAAR,OAAA;AAEA,IAAAS,GAAA,GAAAT,OAAA;AACA,IAAAU,0BAAA,GAAAV,OAAA;AACA,IAAAW,iBAAA,GAAAX,OAAA;AACA,IAAAY,eAAA,GAAAb,sBAAA,CAAAC,OAAA;AACA,IAAAa,oBAAA,GAAAd,sBAAA,CAAAC,OAAA;AAA0D,IAAAc,WAAA,GAAAd,OAAA;AAc1D,SAASe,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,2EAA2E,EAC3ExB,MAAM,GAAG,aAAa,GAAG,+BAC3B,CAAE;MACFyB,OAAO,EAAExB;IAAQ,CAClB,CAAC,eAGF,IAAAP,WAAA,CAAAE,GAAA;MACEC,SAAS,EAAE,IAAA2B,MAAE,EACX,2LAA2L,EAC3LxB,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;gBACE+B,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,CAAAP,OAAc;YAAA,GAAKkB,SAAS,GAAG,CAAC;UAAC,CAAG,CAAC,eAEtC,IAAAT,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAEX,IAAAD,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,MAAM;YAAAC,QAAA,eACnB,IAAAJ,WAAA,CAAAE,GAAA,EAACH,oBAAA,CAAAR,OAAmB;cAClBmD,UAAU,EAAEpC,MAAO;cACnBG,SAAS,EAAEA,SAAS,CAACkC,KAAK,CAAC,CAAC;YAAE,CAC/B;UAAC,CACC,CAAC,eAEN,IAAA3C,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAP,OAAc;YAAA,GACTmB,mBAAmB,GAAG,CAAC,CAAC;YAC5BkC,gBAAgB,EAAC;UAAkQ,CACpR,CAAC,eAEF,IAAA5C,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAP,OAAc;YAAA,GACTmB,mBAAmB,GAAG,CAAC,CAAC;YAC5BkC,gBAAgB,EAAC;UAAkQ,CACpR,CAAC,eAEF,IAAA5C,WAAA,CAAAE,GAAA,EAACD,OAAO,IAAE,CAAC,eAGX,IAAAD,WAAA,CAAAE,GAAA;YAAKC,SAAS,EAAC,MAAM;YAAAC,QAAA,EAClBM,mBAAmB,CAACiC,KAAK,CAAC,CAAC,CAAC,CAACE,GAAG,CAAEC,IAAI,iBACrC,IAAA9C,WAAA,CAAAE,GAAA,EAACJ,eAAA,CAAAP,OAAc;cAEbwD,KAAK,EAAED,IAAI,CAACC,KAAM;cAClBf,IAAI,EAAEc,IAAI,CAACd,IAAK;cAChBgB,QAAQ,EAAEF,IAAI,CAACE,QAAS;cACxBJ,gBAAgB,EAAC;YAAkQ,GAJ9QE,IAAI,CAACC,KAKX,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;gBAC9E8C,MAAM,EAAC,QAAQ;gBACfC,GAAG,EAAC,qBAAqB;gBACzB,cAAYJ,IAAI,CAACC,KAAM;gBAAA3C,QAAA,eAEvB,IAAAJ,WAAA,CAAAE,GAAA;kBAAKC,SAAS,EAAC,0CAA0C;kBAAAC,QAAA,EACtD0C,IAAI,CAACK,IAAI,iBAAI,IAAAnD,WAAA,CAAAE,GAAA,EAAC4C,IAAI,CAACK,IAAI,IAAE;gBAAC,CACxB;cAAC,GATDL,IAAI,CAACC,KAUT,CACJ;YAAC,CACC;UAAC,CACH,CAAC;QAAA,CACH,CAAC,eAGN,IAAA/C,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,CAAAF,OAAM;cAAC6D,OAAO,EAAC,WAAW;cAACC,IAAI,EAAE,EAAG;cAACC,OAAO;cAACnD,SAAS,EAAC,QAAQ;cAAAC,QAAA,eAC9D,IAAAJ,WAAA,CAAAE,GAAA;gBACE8B,IAAI,EAAEnB,YAAa;gBACnBoC,MAAM,EAAC,QAAQ;gBACfC,GAAG,EAAC,qBAAqB;gBAAA9C,QAAA,EAC1B;cAED,CAAG;YAAC,CACE,CAAC,eACT,IAAAJ,WAAA,CAAAE,GAAA,EAACT,OAAA,CAAAF,OAAM;cAAC6D,OAAO,EAAC,SAAS;cAACC,IAAI,EAAE,EAAG;cAACC,OAAO;cAACnD,SAAS,EAAC,QAAQ;cAAAC,QAAA,eAC5D,IAAAJ,WAAA,CAAAE,GAAA;gBAAG8B,IAAI,EAAEpB,SAAU;gBAACqC,MAAM,EAAC,QAAQ;gBAACC,GAAG,EAAC,qBAAqB;gBAAA9C,QAAA,EAAC;cAE9D,CAAG;YAAC,CACE,CAAC;UAAA,CACN;QAAC,CACH,CAAC;MAAA,CACH;IAAC,CACH,CAAC;EAAA,CACN,CAAC;AAEP;AAAC,IAAAmD,QAAA,GAAAlE,OAAA,CAAAE,OAAA,GAEcc,IAAI","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["_interopRequireDefault","require","Object","defineProperty","exports","value","default","_react","_button","_hooks","_icons","_cn","_generateSocialMediaConfig","_sharedComponents","_headerMenuItem","_headerMenuItemGroup","_jsxRuntime","Divider","jsx","className","children","Menu","isOpen","onClose","keywords","menuItems","additionalMenuItems","socialMediaHrefs","donateUrl","subscribeUrl","searchPlaceholder","socialMediaConfig","generateSocialMediaConfig","useBodyScrollLock","toLock","lockID","useEffect","handleEscape","e","key","document","addEventListener","removeEventListener","jsxs","Fragment","cn","onClick","href","src","alt","height","width","loading","ClearIcon","SearchInputSection","mode","tags","isMenuOpen","slice","contentClassName","map","item","label","external","target","rel","icon","variant","size","asChild","_default"],"sources":["../../../src/header/menu/index.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport Button from '../../components/button'\nimport { useBodyScrollLock } from '../../hooks'\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 useBodyScrollLock({\n toLock: isOpen,\n lockID: 'header-menu',\n })\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-overlay 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 tablet:pt-0 fixed z-overlay h-full scrollbar-thin 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 <img\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 {/* Categories */}\n <div className=\"py-2\">\n <HeaderMenuItemGroup\n isMenuOpen={isOpen}\n menuItems={menuItems.slice(1)}\n />\n </div>\n\n <Divider />\n\n {/* My Reading */}\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 {/* Reading Settings */}\n <HeaderMenuItem\n {...additionalMenuItems?.[1]}\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(2).map((item) => (\n <HeaderMenuItem\n key={item.label}\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":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-components.d.ts","sourceRoot":"","sources":["../../src/header/shared-components.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shared-components.d.ts","sourceRoot":"","sources":["../../src/header/shared-components.tsx"],"names":[],"mappings":"AAYA,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,2CA4EhE;AAED,wBAAgB,aAAa,CAAC,EAC5B,cAAsB,EACtB,IAAI,EACJ,iBAAiB,EACjB,YAAY,EACZ,SAAS,GACV,EAAE;IACD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,2CA4DA;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"}
|
|
@@ -12,6 +12,7 @@ exports.SearchInputSection = SearchInputSection;
|
|
|
12
12
|
var _classVarianceAuthority = require("class-variance-authority");
|
|
13
13
|
var _react = require("react");
|
|
14
14
|
var _components = require("../components");
|
|
15
|
+
var _hooks = require("../hooks");
|
|
15
16
|
var _icons = require("../icons");
|
|
16
17
|
var _cn = require("../utils/cn");
|
|
17
18
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -95,6 +96,10 @@ function SearchInputSection(props) {
|
|
|
95
96
|
const isSearchOpen = mode === 'popover' && props.isSearchOpen;
|
|
96
97
|
const tags = props.tags;
|
|
97
98
|
const searchPlaceholder = props.searchPlaceholder;
|
|
99
|
+
(0, _hooks.useBodyScrollLock)({
|
|
100
|
+
toLock: mode === 'popover' && isSearchOpen,
|
|
101
|
+
lockID: 'header-search-input'
|
|
102
|
+
});
|
|
98
103
|
(0, _react.useEffect)(() => {
|
|
99
104
|
if (mode === 'inline') {
|
|
100
105
|
return;
|
|
@@ -102,11 +107,9 @@ function SearchInputSection(props) {
|
|
|
102
107
|
if (isSearchOpen) {
|
|
103
108
|
ref.current?.focus();
|
|
104
109
|
setIsFocused(true);
|
|
105
|
-
document.body.classList.add('no-scroll');
|
|
106
110
|
return;
|
|
107
111
|
}
|
|
108
112
|
setIsFocused(false);
|
|
109
|
-
document.body.classList.remove('no-scroll');
|
|
110
113
|
}, [mode, isSearchOpen]);
|
|
111
114
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
112
115
|
onFocus: () => setIsFocused(true),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared-components.js","names":["Object","defineProperty","exports","value","ActionButtons","BottomNavigation","HamburgerButton","LogoLink","SearchInputSection","_classVarianceAuthority","require","_react","_components","_icons","_cn","_jsxRuntime","searchFormVariants","cva","variants","mode","inline","popover","isSearchOpen","true","false","compoundVariants","class","searchDropdownVariants","isFocused","compactMode","jsx","href","className","rel","children","src","alt","loading","cn","width","height","props","ref","useRef","setIsFocused","useState","searchValue","setSearchValue","tags","searchPlaceholder","useEffect","current","focus","document","body","classList","add","remove","jsxs","onFocus","onBlur","role","method","action","undefined","Input","placeholder","name","title","inputRef","onChange","map","keyword","encodeURIComponent","hideCtaButtons","subscribeUrl","joinUsUrl","setIsSearchOpen","containerRef","buttonRef","handleClickOutside","event","containerElement","buttonElement","contains","target","addEventListener","removeEventListener","Button","variant","size","asChild","onClick","ClearIcon","SearchIcon","onHamburgerOverlayOpen","menuItems","small","reduce","acc","item","index","label","length","HamburgerIconSmall","HamburgerIcon"],"sources":["../../src/header/shared-components.tsx"],"sourcesContent":["'use client'\nimport { cva } from 'class-variance-authority'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { Button, Input } from '../components'\nimport {\n ClearIcon,\n HamburgerIcon,\n HamburgerIconSmall,\n SearchIcon,\n} from '../icons'\nimport type { MenuItem } from '../types'\nimport { cn } from '../utils/cn'\n\nconst searchFormVariants = cva(\n 'ease-in-out h-full transition-all duration-300',\n {\n variants: {\n mode: {\n inline: 'h-11 w-full',\n popover: 'top-0 -right-4 w-66 absolute overflow-hidden opacity-0',\n },\n isSearchOpen: {\n true: '',\n false: '',\n },\n },\n compoundVariants: [\n {\n mode: 'popover',\n isSearchOpen: true,\n class: 'w-66 pointer-events-auto opacity-100',\n },\n {\n mode: 'popover',\n isSearchOpen: false,\n class: 'pointer-events-none',\n },\n ],\n }\n)\n\nconst searchDropdownVariants = cva(\n 'rounded-xl mt-2 w-66 ease-in-out h-0 p-0 z-50 bg-neutral-white opacity-0 transition-all duration-200',\n {\n variants: {\n mode: {\n inline: '',\n popover: 'top-12 -right-4 shadow-custom p-4 absolute',\n },\n isSearchOpen: {\n true: '',\n false: '',\n },\n isFocused: {\n true: '',\n false: '',\n },\n },\n compoundVariants: [\n {\n mode: 'popover',\n isSearchOpen: true,\n isFocused: true,\n class: 'p-4 h-min opacity-100',\n },\n {\n mode: 'popover',\n isSearchOpen: false,\n class: 'pointer-events-none',\n },\n {\n mode: 'inline',\n isFocused: true,\n class:\n 'translate-y-0 pt-6 mt-0 bg-neutral-transparent h-min w-full opacity-100',\n },\n {\n mode: 'inline',\n isFocused: false,\n class: '-translate-y-3 pointer-events-none w-full',\n },\n ],\n }\n)\n\nexport function LogoLink({ compactMode = false }: { compactMode?: boolean }) {\n return (\n <a href=\"/\" className=\"flex items-center\" rel=\"home\">\n <img\n src=\"/assets/images/brand-icon.svg\"\n alt=\"少年報導者 The Reporter for Kids\"\n loading=\"eager\"\n className={cn(\n 'h-5 tablet:h-6 desktop:h-8 ease-in-out w-auto transition-all duration-500',\n compactMode && 'desktop:h-[26px]'\n )}\n width={293}\n height={32}\n />\n </a>\n )\n}\n\ntype SearchInputSectionProps =\n | {\n mode: 'popover'\n isSearchOpen: boolean\n tags: string[]\n searchPlaceholder: string\n }\n | {\n mode: 'inline'\n tags: string[]\n searchPlaceholder: string\n }\n\nexport function SearchInputSection(props: SearchInputSectionProps) {\n const ref = useRef<HTMLInputElement>(null)\n const [isFocused, setIsFocused] = useState(false)\n const [searchValue, setSearchValue] = useState('')\n\n const mode = props.mode\n const isSearchOpen = mode === 'popover' && props.isSearchOpen\n const tags = props.tags\n const searchPlaceholder = props.searchPlaceholder\n\n useEffect(() => {\n if (mode === 'inline') {\n return\n }\n if (isSearchOpen) {\n ref.current?.focus()\n setIsFocused(true)\n document.body.classList.add('no-scroll')\n return\n }\n setIsFocused(false)\n document.body.classList.remove('no-scroll')\n }, [mode, isSearchOpen])\n\n return (\n <div\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className={mode === 'inline' ? 'relative w-full' : 'h-11'}\n >\n <form\n role=\"search\"\n method=\"get\"\n action=\"/search\"\n className={searchFormVariants({\n mode,\n isSearchOpen: mode === 'popover' ? isSearchOpen : undefined,\n })}\n >\n <Input\n placeholder={searchPlaceholder}\n name=\"q\"\n title=\"Search for...\"\n aria-label=\"Search for...\"\n className=\"w-[99%]\"\n inputRef={ref}\n onChange={setSearchValue}\n value={searchValue}\n mode=\"search\"\n />\n </form>\n <div\n className={searchDropdownVariants({\n mode,\n isSearchOpen: mode === 'popover' ? isSearchOpen : undefined,\n isFocused,\n })}\n >\n <h3 className=\"font-bold mb-3 prose-p3 text-neutral-700\">熱門搜尋</h3>\n <div className=\"gap-2.5 flex flex-wrap\">\n {tags.map((keyword) => (\n <a\n key={keyword}\n className=\"px-3 py-1 font-bold cursor-pointer rounded-full bg-neutral-200 prose-p2 text-neutral-900 transition-colors duration-200 hover:bg-red-500 hover:text-neutral-white\"\n href={`/search?q=${encodeURIComponent(keyword)}`}\n >\n #{keyword}\n </a>\n ))}\n </div>\n </div>\n </div>\n )\n}\n\nexport function ActionButtons({\n hideCtaButtons = false,\n tags,\n searchPlaceholder,\n subscribeUrl,\n joinUsUrl,\n}: {\n hideCtaButtons?: boolean\n tags: string[]\n searchPlaceholder: string\n subscribeUrl: string\n joinUsUrl: string\n}) {\n const [isSearchOpen, setIsSearchOpen] = useState(false)\n\n const containerRef = useRef<HTMLDivElement>(null)\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n const containerElement = containerRef.current\n const buttonElement = buttonRef.current\n if (!containerElement || !buttonElement) return\n if (\n !containerElement.contains(event.target as Node) &&\n !buttonElement.contains(event.target as Node)\n ) {\n setIsSearchOpen(false)\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [])\n\n return (\n <div className=\"relative flex items-center\">\n <div className=\"mr-6 relative flex items-center\" ref={containerRef}>\n {/* CTA Buttons - Base layer */}\n {!hideCtaButtons && !isSearchOpen && (\n <div className=\"gap-4 flex items-center\">\n <Button variant=\"secondary\" size={32} asChild>\n <a href={joinUsUrl}>加入我們</a>\n </Button>\n <Button variant=\"primary\" size={32} asChild>\n <a href={subscribeUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n 訂閱\n </a>\n </Button>\n </div>\n )}\n\n <SearchInputSection\n isSearchOpen={isSearchOpen}\n mode=\"popover\"\n tags={tags}\n searchPlaceholder={searchPlaceholder}\n />\n </div>\n\n <button\n 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\"\n aria-label=\"搜尋\"\n onClick={() => setIsSearchOpen(!isSearchOpen)}\n ref={buttonRef}\n >\n {isSearchOpen ? <ClearIcon /> : <SearchIcon />}\n </button>\n </div>\n )\n}\n\nexport function BottomNavigation({\n onHamburgerOverlayOpen,\n menuItems,\n}: {\n onHamburgerOverlayOpen: () => void\n menuItems: MenuItem[]\n}) {\n return (\n <div className=\"py-2 px-4 flex w-full items-center justify-between border-y border-neutral-border\">\n <HamburgerButton onHamburgerOverlayOpen={onHamburgerOverlayOpen} small />\n\n {menuItems.reduce((acc, item, index) => {\n return [\n ...acc,\n <div key={item.label} className=\"flex items-center\">\n <a\n href={item.href}\n className=\"py-1 font-bold! h-6 flex items-center prose-p1 text-neutral-900 transition-colors hover:text-red-400\"\n >\n {item.label}\n </a>\n </div>,\n ...(index < menuItems.length - 1\n ? [\n <div\n key={`separator-${index}`}\n className=\"h-4 mx-2 w-px bg-neutral-border\"\n />,\n ]\n : []),\n ]\n }, [] as React.ReactNode[])}\n </div>\n )\n}\n\nexport function HamburgerButton({\n onHamburgerOverlayOpen,\n small = false,\n}: {\n onHamburgerOverlayOpen: () => void\n small?: boolean\n}) {\n return (\n <button\n className={cn(\n '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',\n small ? 'w-6 h-6' : 'w-8 h-8'\n )}\n onClick={onHamburgerOverlayOpen}\n >\n {small ? <HamburgerIconSmall /> : <HamburgerIcon />}\n </button>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"shared-components.js","names":["Object","defineProperty","exports","value","ActionButtons","BottomNavigation","HamburgerButton","LogoLink","SearchInputSection","_classVarianceAuthority","require","_react","_components","_hooks","_icons","_cn","_jsxRuntime","searchFormVariants","cva","variants","mode","inline","popover","isSearchOpen","true","false","compoundVariants","class","searchDropdownVariants","isFocused","compactMode","jsx","href","className","rel","children","src","alt","loading","cn","width","height","props","ref","useRef","setIsFocused","useState","searchValue","setSearchValue","tags","searchPlaceholder","useBodyScrollLock","toLock","lockID","useEffect","current","focus","jsxs","onFocus","onBlur","role","method","action","undefined","Input","placeholder","name","title","inputRef","onChange","map","keyword","encodeURIComponent","hideCtaButtons","subscribeUrl","joinUsUrl","setIsSearchOpen","containerRef","buttonRef","handleClickOutside","event","containerElement","buttonElement","contains","target","document","addEventListener","removeEventListener","Button","variant","size","asChild","onClick","ClearIcon","SearchIcon","onHamburgerOverlayOpen","menuItems","small","reduce","acc","item","index","label","length","HamburgerIconSmall","HamburgerIcon"],"sources":["../../src/header/shared-components.tsx"],"sourcesContent":["'use client'\nimport { cva } from 'class-variance-authority'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { Button, Input } from '../components'\nimport { useBodyScrollLock } from '../hooks'\nimport {\n ClearIcon,\n HamburgerIcon,\n HamburgerIconSmall,\n SearchIcon,\n} from '../icons'\nimport type { MenuItem } from '../types'\nimport { cn } from '../utils/cn'\n\nconst searchFormVariants = cva(\n 'ease-in-out h-full transition-all duration-300',\n {\n variants: {\n mode: {\n inline: 'h-11 w-full',\n popover: 'top-0 -right-4 w-66 absolute overflow-hidden opacity-0',\n },\n isSearchOpen: {\n true: '',\n false: '',\n },\n },\n compoundVariants: [\n {\n mode: 'popover',\n isSearchOpen: true,\n class: 'w-66 pointer-events-auto opacity-100',\n },\n {\n mode: 'popover',\n isSearchOpen: false,\n class: 'pointer-events-none',\n },\n ],\n }\n)\n\nconst searchDropdownVariants = cva(\n 'rounded-xl mt-2 w-66 ease-in-out h-0 p-0 z-50 bg-neutral-white opacity-0 transition-all duration-200',\n {\n variants: {\n mode: {\n inline: '',\n popover: 'top-12 -right-4 shadow-custom p-4 absolute',\n },\n isSearchOpen: {\n true: '',\n false: '',\n },\n isFocused: {\n true: '',\n false: '',\n },\n },\n compoundVariants: [\n {\n mode: 'popover',\n isSearchOpen: true,\n isFocused: true,\n class: 'p-4 h-min opacity-100',\n },\n {\n mode: 'popover',\n isSearchOpen: false,\n class: 'pointer-events-none',\n },\n {\n mode: 'inline',\n isFocused: true,\n class:\n 'translate-y-0 pt-6 mt-0 bg-neutral-transparent h-min w-full opacity-100',\n },\n {\n mode: 'inline',\n isFocused: false,\n class: '-translate-y-3 pointer-events-none w-full',\n },\n ],\n }\n)\n\nexport function LogoLink({ compactMode = false }: { compactMode?: boolean }) {\n return (\n <a href=\"/\" className=\"flex items-center\" rel=\"home\">\n <img\n src=\"/assets/images/brand-icon.svg\"\n alt=\"少年報導者 The Reporter for Kids\"\n loading=\"eager\"\n className={cn(\n 'h-5 tablet:h-6 desktop:h-8 ease-in-out w-auto transition-all duration-500',\n compactMode && 'desktop:h-[26px]'\n )}\n width={293}\n height={32}\n />\n </a>\n )\n}\n\ntype SearchInputSectionProps =\n | {\n mode: 'popover'\n isSearchOpen: boolean\n tags: string[]\n searchPlaceholder: string\n }\n | {\n mode: 'inline'\n tags: string[]\n searchPlaceholder: string\n }\n\nexport function SearchInputSection(props: SearchInputSectionProps) {\n const ref = useRef<HTMLInputElement>(null)\n const [isFocused, setIsFocused] = useState(false)\n const [searchValue, setSearchValue] = useState('')\n\n const mode = props.mode\n const isSearchOpen = mode === 'popover' && props.isSearchOpen\n const tags = props.tags\n const searchPlaceholder = props.searchPlaceholder\n\n useBodyScrollLock({\n toLock: mode === 'popover' && isSearchOpen,\n lockID: 'header-search-input',\n })\n\n useEffect(() => {\n if (mode === 'inline') {\n return\n }\n if (isSearchOpen) {\n ref.current?.focus()\n setIsFocused(true)\n return\n }\n setIsFocused(false)\n }, [mode, isSearchOpen])\n\n return (\n <div\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n className={mode === 'inline' ? 'relative w-full' : 'h-11'}\n >\n <form\n role=\"search\"\n method=\"get\"\n action=\"/search\"\n className={searchFormVariants({\n mode,\n isSearchOpen: mode === 'popover' ? isSearchOpen : undefined,\n })}\n >\n <Input\n placeholder={searchPlaceholder}\n name=\"q\"\n title=\"Search for...\"\n aria-label=\"Search for...\"\n className=\"w-[99%]\"\n inputRef={ref}\n onChange={setSearchValue}\n value={searchValue}\n mode=\"search\"\n />\n </form>\n <div\n className={searchDropdownVariants({\n mode,\n isSearchOpen: mode === 'popover' ? isSearchOpen : undefined,\n isFocused,\n })}\n >\n <h3 className=\"font-bold mb-3 prose-p3 text-neutral-700\">熱門搜尋</h3>\n <div className=\"gap-2.5 flex flex-wrap\">\n {tags.map((keyword) => (\n <a\n key={keyword}\n className=\"px-3 py-1 font-bold cursor-pointer rounded-full bg-neutral-200 prose-p2 text-neutral-900 transition-colors duration-200 hover:bg-red-500 hover:text-neutral-white\"\n href={`/search?q=${encodeURIComponent(keyword)}`}\n >\n #{keyword}\n </a>\n ))}\n </div>\n </div>\n </div>\n )\n}\n\nexport function ActionButtons({\n hideCtaButtons = false,\n tags,\n searchPlaceholder,\n subscribeUrl,\n joinUsUrl,\n}: {\n hideCtaButtons?: boolean\n tags: string[]\n searchPlaceholder: string\n subscribeUrl: string\n joinUsUrl: string\n}) {\n const [isSearchOpen, setIsSearchOpen] = useState(false)\n\n const containerRef = useRef<HTMLDivElement>(null)\n const buttonRef = useRef<HTMLButtonElement>(null)\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n const containerElement = containerRef.current\n const buttonElement = buttonRef.current\n if (!containerElement || !buttonElement) return\n if (\n !containerElement.contains(event.target as Node) &&\n !buttonElement.contains(event.target as Node)\n ) {\n setIsSearchOpen(false)\n }\n }\n\n document.addEventListener('mousedown', handleClickOutside)\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [])\n\n return (\n <div className=\"relative flex items-center\">\n <div className=\"mr-6 relative flex items-center\" ref={containerRef}>\n {/* CTA Buttons - Base layer */}\n {!hideCtaButtons && !isSearchOpen && (\n <div className=\"gap-4 flex items-center\">\n <Button variant=\"secondary\" size={32} asChild>\n <a href={joinUsUrl}>加入我們</a>\n </Button>\n <Button variant=\"primary\" size={32} asChild>\n <a href={subscribeUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n 訂閱\n </a>\n </Button>\n </div>\n )}\n\n <SearchInputSection\n isSearchOpen={isSearchOpen}\n mode=\"popover\"\n tags={tags}\n searchPlaceholder={searchPlaceholder}\n />\n </div>\n\n <button\n 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\"\n aria-label=\"搜尋\"\n onClick={() => setIsSearchOpen(!isSearchOpen)}\n ref={buttonRef}\n >\n {isSearchOpen ? <ClearIcon /> : <SearchIcon />}\n </button>\n </div>\n )\n}\n\nexport function BottomNavigation({\n onHamburgerOverlayOpen,\n menuItems,\n}: {\n onHamburgerOverlayOpen: () => void\n menuItems: MenuItem[]\n}) {\n return (\n <div className=\"py-2 px-4 flex w-full items-center justify-between border-y border-neutral-border\">\n <HamburgerButton onHamburgerOverlayOpen={onHamburgerOverlayOpen} small />\n\n {menuItems.reduce((acc, item, index) => {\n return [\n ...acc,\n <div key={item.label} className=\"flex items-center\">\n <a\n href={item.href}\n className=\"py-1 font-bold! h-6 flex items-center prose-p1 text-neutral-900 transition-colors hover:text-red-400\"\n >\n {item.label}\n </a>\n </div>,\n ...(index < menuItems.length - 1\n ? [\n <div\n key={`separator-${index}`}\n className=\"h-4 mx-2 w-px bg-neutral-border\"\n />,\n ]\n : []),\n ]\n }, [] as React.ReactNode[])}\n </div>\n )\n}\n\nexport function HamburgerButton({\n onHamburgerOverlayOpen,\n small = false,\n}: {\n onHamburgerOverlayOpen: () => void\n small?: boolean\n}) {\n return (\n <button\n className={cn(\n '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',\n small ? 'w-6 h-6' : 'w-8 h-8'\n )}\n onClick={onHamburgerOverlayOpen}\n >\n {small ? <HamburgerIconSmall /> : <HamburgerIcon />}\n </button>\n )\n}\n"],"mappings":"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","ignoreList":[]}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AACrE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -10,6 +10,12 @@ Object.defineProperty(exports, "ScrollLevel", {
|
|
|
10
10
|
return _useScrollLevel.ScrollLevel;
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
|
+
Object.defineProperty(exports, "useBodyScrollLock", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _useBodyScrollLock.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
13
19
|
Object.defineProperty(exports, "useIsAtTop", {
|
|
14
20
|
enumerable: true,
|
|
15
21
|
get: function () {
|
|
@@ -28,6 +34,7 @@ Object.defineProperty(exports, "useScrollLevel", {
|
|
|
28
34
|
return _useScrollLevel.default;
|
|
29
35
|
}
|
|
30
36
|
});
|
|
37
|
+
var _useBodyScrollLock = _interopRequireDefault(require("./use-body-scroll-lock"));
|
|
31
38
|
var _useIsAtTop = _interopRequireDefault(require("./use-is-at-top"));
|
|
32
39
|
var _useMediaQuery = _interopRequireDefault(require("./use-media-query"));
|
|
33
40
|
var _useScrollLevel = _interopRequireWildcard(require("./use-scroll-level"));
|
package/dist/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["
|
|
1
|
+
{"version":3,"file":"index.js","names":["_useBodyScrollLock","_interopRequireDefault","require","_useIsAtTop","_useMediaQuery","_useScrollLevel","_interopRequireWildcard","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor"],"sources":["../../src/hooks/index.ts"],"sourcesContent":["export { default as useBodyScrollLock } from './use-body-scroll-lock'\nexport { default as useIsAtTop } from './use-is-at-top'\nexport { default as useMediaQuery } from './use-media-query'\nexport { ScrollLevel, default as useScrollLevel } from './use-scroll-level'\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,kBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,WAAA,GAAAF,sBAAA,CAAAC,OAAA;AACA,IAAAE,cAAA,GAAAH,sBAAA,CAAAC,OAAA;AACA,IAAAG,eAAA,GAAAC,uBAAA,CAAAJ,OAAA;AAA2E,SAAAI,wBAAAC,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAH,uBAAA,YAAAA,CAAAC,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-body-scroll-lock.d.ts","sourceRoot":"","sources":["../../src/hooks/use-body-scroll-lock.ts"],"names":[],"mappings":"AAEA,iBAAS,iBAAiB,CAAC,EACzB,MAAM,EACN,MAAW,GACZ,EAAE;IACD,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,QAiBA;AAED,eAAe,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
function useBodyScrollLock({
|
|
9
|
+
toLock,
|
|
10
|
+
lockID = ''
|
|
11
|
+
}) {
|
|
12
|
+
(0, _react.useEffect)(() => {
|
|
13
|
+
const className = lockID ? `no-scroll--${lockID}` : `no-scroll`;
|
|
14
|
+
if (toLock) {
|
|
15
|
+
document.body.classList.add(className);
|
|
16
|
+
document.documentElement.classList.add(className);
|
|
17
|
+
} else {
|
|
18
|
+
document.body.classList.remove(className);
|
|
19
|
+
document.documentElement.classList.remove(className);
|
|
20
|
+
}
|
|
21
|
+
return () => {
|
|
22
|
+
document.body.classList.remove(className);
|
|
23
|
+
document.documentElement.classList.remove(className);
|
|
24
|
+
};
|
|
25
|
+
}, [toLock, lockID]);
|
|
26
|
+
}
|
|
27
|
+
var _default = exports.default = useBodyScrollLock;
|
|
28
|
+
//# sourceMappingURL=use-body-scroll-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-body-scroll-lock.js","names":["_react","require","useBodyScrollLock","toLock","lockID","useEffect","className","document","body","classList","add","documentElement","remove","_default","exports","default"],"sources":["../../src/hooks/use-body-scroll-lock.ts"],"sourcesContent":["import { useEffect } from 'react'\n\nfunction useBodyScrollLock({\n toLock,\n lockID = '',\n}: {\n toLock: boolean\n lockID?: string\n}) {\n useEffect(() => {\n const className = lockID ? `no-scroll--${lockID}` : `no-scroll`\n\n if (toLock) {\n document.body.classList.add(className)\n document.documentElement.classList.add(className)\n } else {\n document.body.classList.remove(className)\n document.documentElement.classList.remove(className)\n }\n\n return () => {\n document.body.classList.remove(className)\n document.documentElement.classList.remove(className)\n }\n }, [toLock, lockID])\n}\n\nexport default useBodyScrollLock\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,SAASC,iBAAiBA,CAAC;EACzBC,MAAM;EACNC,MAAM,GAAG;AAIX,CAAC,EAAE;EACD,IAAAC,gBAAS,EAAC,MAAM;IACd,MAAMC,SAAS,GAAGF,MAAM,GAAG,cAAcA,MAAM,EAAE,GAAG,WAAW;IAE/D,IAAID,MAAM,EAAE;MACVI,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACC,GAAG,CAACJ,SAAS,CAAC;MACtCC,QAAQ,CAACI,eAAe,CAACF,SAAS,CAACC,GAAG,CAACJ,SAAS,CAAC;IACnD,CAAC,MAAM;MACLC,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACG,MAAM,CAACN,SAAS,CAAC;MACzCC,QAAQ,CAACI,eAAe,CAACF,SAAS,CAACG,MAAM,CAACN,SAAS,CAAC;IACtD;IAEA,OAAO,MAAM;MACXC,QAAQ,CAACC,IAAI,CAACC,SAAS,CAACG,MAAM,CAACN,SAAS,CAAC;MACzCC,QAAQ,CAACI,eAAe,CAACF,SAAS,CAACG,MAAM,CAACN,SAAS,CAAC;IACtD,CAAC;EACH,CAAC,EAAE,CAACH,MAAM,EAAEC,MAAM,CAAC,CAAC;AACtB;AAAC,IAAAS,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAEcb,iBAAiB","ignoreList":[]}
|
package/dist/styles.css
CHANGED
package/dist/utils/cn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/utils/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/utils/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,MAAM,MAAM,CAAA;AAgCvC;;;;GAIG;AACH,eAAO,MAAM,EAAE,GAAI,GAAG,QAAQ,UAAU,EAAE,KAAG,MAE5C,CAAA"}
|
package/dist/utils/cn.js
CHANGED
|
@@ -9,8 +9,7 @@ var _tailwindMerge = require("tailwind-merge");
|
|
|
9
9
|
const twMerge = (0, _tailwindMerge.extendTailwindMerge)({
|
|
10
10
|
extend: {
|
|
11
11
|
classGroups: {
|
|
12
|
-
|
|
13
|
-
'font-size': ['prose-p1', 'prose-p1-bold', 'prose-p2', 'prose-p2-bold', 'prose-p3', 'prose-p3-bold', 'prose-p4', 'prose-p4-bold', 'prose-h1-large', 'prose-h2-large', 'prose-h3-large', 'prose-h4-large', 'prose-h5-large', 'prose-h6-large', 'prose-h1-small', 'prose-h2-small', 'prose-h3-small', 'prose-h4-small', 'prose-h5-small', 'prose-h6-small']
|
|
12
|
+
'prose-typography': ['prose-p1', 'prose-p1-bold', 'prose-p2', 'prose-p2-bold', 'prose-p3', 'prose-p3-bold', 'prose-p4', 'prose-p4-bold', 'prose-h1-large', 'prose-h2-large', 'prose-h3-large', 'prose-h4-large', 'prose-h5-large', 'prose-h6-large', 'prose-h1-small', 'prose-h2-small', 'prose-h3-small', 'prose-h4-small', 'prose-h5-small', 'prose-h6-small']
|
|
14
13
|
}
|
|
15
14
|
}
|
|
16
15
|
});
|
package/dist/utils/cn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cn.js","names":["_clsx","require","_tailwindMerge","twMerge","extendTailwindMerge","extend","classGroups","cn","inputs","clsx","exports"],"sources":["../../src/utils/cn.ts"],"sourcesContent":["import { ClassValue, clsx } from 'clsx'\nimport { extendTailwindMerge } from 'tailwind-merge'\n\nconst twMerge = extendTailwindMerge({\n extend: {\n classGroups: {\n
|
|
1
|
+
{"version":3,"file":"cn.js","names":["_clsx","require","_tailwindMerge","twMerge","extendTailwindMerge","extend","classGroups","cn","inputs","clsx","exports"],"sources":["../../src/utils/cn.ts"],"sourcesContent":["import { ClassValue, clsx } from 'clsx'\nimport { extendTailwindMerge } from 'tailwind-merge'\n\nconst twMerge = extendTailwindMerge<'prose-typography'>({\n extend: {\n classGroups: {\n 'prose-typography': [\n 'prose-p1',\n 'prose-p1-bold',\n 'prose-p2',\n 'prose-p2-bold',\n 'prose-p3',\n 'prose-p3-bold',\n 'prose-p4',\n 'prose-p4-bold',\n 'prose-h1-large',\n 'prose-h2-large',\n 'prose-h3-large',\n 'prose-h4-large',\n 'prose-h5-large',\n 'prose-h6-large',\n 'prose-h1-small',\n 'prose-h2-small',\n 'prose-h3-small',\n 'prose-h4-small',\n 'prose-h5-small',\n 'prose-h6-small',\n ],\n },\n },\n})\n\n/**\n * Combines clsx and tailwind-merge for optimal class merging.\n * @param inputs - Class names or conditional class values.\n * @returns A single string with merged class names.\n */\nexport const cn = (...inputs: ClassValue[]): string => {\n return twMerge(clsx(inputs))\n}\n"],"mappings":";;;;;;AAAA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AAEA,MAAME,OAAO,GAAG,IAAAC,kCAAmB,EAAqB;EACtDC,MAAM,EAAE;IACNC,WAAW,EAAE;MACX,kBAAkB,EAAE,CAClB,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB;IAEpB;EACF;AACF,CAAC,CAAC;;AAEF;AACA;AACA;AACA;AACA;AACO,MAAMC,EAAE,GAAGA,CAAC,GAAGC,MAAoB,KAAa;EACrD,OAAOL,OAAO,CAAC,IAAAM,UAAI,EAACD,MAAM,CAAC,CAAC;AAC9B,CAAC;AAAAE,OAAA,CAAAH,EAAA,GAAAA,EAAA","ignoreList":[]}
|