@yeongseoksong/framework 1.6.0 → 1.6.2

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/ui/index.cjs CHANGED
@@ -219,7 +219,6 @@ __export(ui_exports, {
219
219
  module.exports = __toCommonJS(ui_exports);
220
220
 
221
221
  // ui/atom/Logo.tsx
222
- var import_image = __toESM(require("next/image"));
223
222
  var import_link = __toESM(require("next/link"));
224
223
  var import_core = require("@mantine/core");
225
224
 
@@ -237,21 +236,7 @@ function Logo(_props) {
237
236
  const { size } = (0, import_core.useProps)("Logo", { size: "md" }, _props);
238
237
  const theme2 = (0, import_core.useMantineTheme)();
239
238
  const resolved = theme2.other.logoSizes[size];
240
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/", style: { display: "inline-flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
241
- import_image.default,
242
- {
243
- src: LOGO_SRC,
244
- alt: LOGO_ALT,
245
- width: resolved.width,
246
- height: resolved.height,
247
- style: {
248
- width: (0, import_core.rem)(resolved.width),
249
- height: "auto",
250
- objectFit: "contain"
251
- },
252
- priority: true
253
- }
254
- ) });
239
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: "/", style: { display: "inline-flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Image, { src: LOGO_SRC, alt: LOGO_ALT, w: (0, import_core.rem)(resolved.width), h: "auto", fit: "contain", fetchPriority: "high" }) });
255
240
  }
256
241
 
257
242
  // ui/atom/Tabs.tsx
@@ -1729,6 +1714,7 @@ function SdBreadcrumb(_a4) {
1729
1714
  const navItems = navItemsProp != null ? navItemsProp : navFromContext;
1730
1715
  const pathname = (0, import_navigation.usePathname)();
1731
1716
  const trail = buildTrail(navItems, (_a5 = currentHref != null ? currentHref : pathname) != null ? _a5 : "");
1717
+ if (navItems.length === 0) return;
1732
1718
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_core27.Box, __spreadProps(__spreadValues({}, boxProps), { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
1733
1719
  import_core27.Breadcrumbs,
1734
1720
  {
@@ -1855,7 +1841,7 @@ function MobileNav({ opened, close, topItems, childrenOf, loginFlag }) {
1855
1841
  loginFlag && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Stack, { gap: "xs", mt: "md", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
1856
1842
  ] }) });
1857
1843
  }
1858
- function MegaHeader({ navItems, loginFlag }) {
1844
+ function MegaHeader({ navItems, loginFlag, logoSize }) {
1859
1845
  const [opened, { toggle, close }] = (0, import_hooks.useDisclosure)();
1860
1846
  const { topItems, childrenOf, hasAnyChildren } = useNavTree(navItems);
1861
1847
  const { hovered, ref: hoverRef } = (0, import_hooks.useHover)();
@@ -1875,7 +1861,7 @@ function MegaHeader({ navItems, loginFlag }) {
1875
1861
  transition: "box-shadow 0.15s"
1876
1862
  },
1877
1863
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SdContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_core29.Group, { justify: "space-between", align: "flex-start", wrap: "nowrap", children: [
1878
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Group, { h: BAR_HEIGHT, align: "center", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, {}) }),
1864
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Group, { h: BAR_HEIGHT, align: "center", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, { size: logoSize }) }),
1879
1865
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Group, { gap: "xl", align: "flex-start", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
1880
1866
  const kids = childrenOf(item.id);
1881
1867
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_core29.Stack, { gap: 0, align: "center", children: [
@@ -1934,12 +1920,12 @@ function MegaHeader({ navItems, loginFlag }) {
1934
1920
  function renderMenuLeaf(item) {
1935
1921
  return item.href ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Menu.Item, { component: "a", href: item.href, children: item.label }, item.id) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Menu.Label, { children: item.label }, item.id);
1936
1922
  }
1937
- function SimpleHeader({ navItems, loginFlag }) {
1923
+ function SimpleHeader({ navItems, loginFlag, logoSize }) {
1938
1924
  const [opened, { toggle, close }] = (0, import_hooks.useDisclosure)();
1939
1925
  const { topItems, childrenOf } = useNavTree(navItems);
1940
1926
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
1941
1927
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Box, { bg: "var(--mantine-color-body)", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SdContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_core29.Group, { h: BAR_HEIGHT, justify: "space-between", align: "center", wrap: "nowrap", children: [
1942
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, {}),
1928
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, { size: logoSize }),
1943
1929
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Group, { gap: "xl", align: "center", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
1944
1930
  const kids = childrenOf(item.id);
1945
1931
  if (kids.length === 0) {
@@ -2000,12 +1986,12 @@ function SimpleHeader({ navItems, loginFlag }) {
2000
1986
  )
2001
1987
  ] });
2002
1988
  }
2003
- function PanelHeader({ navItems, loginFlag }) {
1989
+ function PanelHeader({ navItems, loginFlag, logoSize }) {
2004
1990
  const [opened, { toggle, close }] = (0, import_hooks.useDisclosure)();
2005
1991
  const { topItems, childrenOf } = useNavTree(navItems);
2006
1992
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
2007
1993
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Box, { bg: "var(--mantine-color-body)", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(SdContainer, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_core29.Group, { h: BAR_HEIGHT, justify: "space-between", align: "center", wrap: "nowrap", children: [
2008
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, {}),
1994
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Logo, { size: logoSize }),
2009
1995
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_core29.Group, { gap: "xl", align: "center", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
2010
1996
  const kids = childrenOf(item.id);
2011
1997
  if (kids.length === 0) {
@@ -2131,11 +2117,11 @@ function FooterCompanyInfo({ company }) {
2131
2117
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(InfoCell, { label: "Email", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SdLink.Sub, { href: `mailto:${company.email}`, children: company.email }) })
2132
2118
  ] });
2133
2119
  }
2134
- function SdFooter({ company, navItems, policyLinks, description }) {
2120
+ function SdFooter({ company, navItems, policyLinks, description, logoSize = "sm" }) {
2135
2121
  const visibleNav = filterAndSort(navItems);
2136
2122
  const visiblePolicy = filterAndSort(policyLinks);
2137
2123
  return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_core30.Box, { component: "footer", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SdContainer, { py: "lg", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_core30.Stack, { children: [
2138
- /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Logo, { size: "sm" }),
2124
+ /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Logo, { size: logoSize }),
2139
2125
  description && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(SdText.Sub, { children: description }),
2140
2126
  /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_core30.Flex, { direction: { base: "column", md: "row" }, gap: 48, align: "flex-start", children: [
2141
2127
  /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_core30.Box, { flex: { base: "0 0 auto", md: "1 1 0" }, w: { base: "100%", md: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(FooterCompanyInfo, { company }) }),
@@ -2412,9 +2398,13 @@ function LoginForm({
2412
2398
  children
2413
2399
  ] }) });
2414
2400
  }
2415
- function FormHeader({ title, description }) {
2401
+ function FormHeader({
2402
+ title,
2403
+ description,
2404
+ logoSize = "sm"
2405
+ }) {
2416
2406
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_core35.Stack, { gap: "lg", children: [
2417
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Logo, { size: "sm" }),
2407
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Logo, { size: logoSize }),
2418
2408
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(SdTextBox.Card, { title, description: description != null ? description : "" })
2419
2409
  ] });
2420
2410
  }
@@ -2422,14 +2412,16 @@ function Card7(_a4) {
2422
2412
  var _b = _a4, {
2423
2413
  title = "\uB85C\uADF8\uC778",
2424
2414
  description = "%c \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD558\uB824\uBA74 \uB85C\uADF8\uC778\uD574 \uC8FC\uC138\uC694.",
2425
- mih = "100svh"
2415
+ mih = "100svh",
2416
+ logoSize
2426
2417
  } = _b, formProps = __objRest(_b, [
2427
2418
  "title",
2428
2419
  "description",
2429
- "mih"
2420
+ "mih",
2421
+ "logoSize"
2430
2422
  ]);
2431
2423
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_core35.Center, { mih, bg: "slate.0", p: "md", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_core35.Paper, { w: "100%", maw: 420, p: { base: "lg", sm: "xl" }, radius: "lg", withBorder: true, shadow: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_core35.Stack, { gap: "xl", children: [
2432
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormHeader, { title, description }),
2424
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormHeader, { title, description, logoSize }),
2433
2425
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(LoginForm, __spreadValues({}, formProps))
2434
2426
  ] }) }) });
2435
2427
  }
@@ -2439,13 +2431,15 @@ function Split(_a4) {
2439
2431
  description = "\uACC4\uC815 \uC815\uBCF4\uB97C \uC785\uB825\uD574 \uC8FC\uC138\uC694.",
2440
2432
  brandTitle = "%c",
2441
2433
  brandDescription = "\uD558\uB098\uC758 \uACC4\uC815\uC73C\uB85C \uBAA8\uB4E0 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD558\uC138\uC694.",
2442
- mih = "100svh"
2434
+ mih = "100svh",
2435
+ logoSize
2443
2436
  } = _b, formProps = __objRest(_b, [
2444
2437
  "title",
2445
2438
  "description",
2446
2439
  "brandTitle",
2447
2440
  "brandDescription",
2448
- "mih"
2441
+ "mih",
2442
+ "logoSize"
2449
2443
  ]);
2450
2444
  return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_core35.SimpleGrid, { cols: { base: 1, md: 2 }, spacing: 0, mih, children: [
2451
2445
  /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
@@ -2471,7 +2465,7 @@ function Split(_a4) {
2471
2465
  }
2472
2466
  ),
2473
2467
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_core35.Center, { p: { base: "md", sm: "xl" }, bg: "white", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_core35.Stack, { gap: "xl", w: "100%", maw: 400, children: [
2474
- /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormHeader, { title, description }),
2468
+ /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(FormHeader, { title, description, logoSize }),
2475
2469
  /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(LoginForm, __spreadValues({}, formProps))
2476
2470
  ] }) })
2477
2471
  ] });
@@ -2545,13 +2539,15 @@ function MainLayout({
2545
2539
  navItems,
2546
2540
  companyInfo,
2547
2541
  loginFlag,
2548
- headerVariant = "mega"
2542
+ headerVariant = "mega",
2543
+ headerLogoSize,
2544
+ footerLogoSize
2549
2545
  }) {
2550
2546
  const Header = headers[headerVariant];
2551
2547
  return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_core37.AppShell, { header: { height: 60 }, children: [
2552
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_core37.AppShell.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Header, { navItems, loginFlag }) }),
2548
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_core37.AppShell.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Header, { navItems, loginFlag, logoSize: headerLogoSize }) }),
2553
2549
  /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_core37.AppShell.Main, { children }),
2554
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SdFooter, { company: companyInfo, navItems })
2550
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(SdFooter, { company: companyInfo, navItems, logoSize: footerLogoSize })
2555
2551
  ] });
2556
2552
  }
2557
2553
 
@@ -2567,9 +2563,8 @@ function Content({
2567
2563
  breadcrumb = true,
2568
2564
  currentHref
2569
2565
  }) {
2570
- const showBreadcrumb = breadcrumb && !!navItems && navItems.length > 0;
2571
2566
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(SdContainer, { py: "xl", children: [
2572
- showBreadcrumb && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(SdBreadcrumb, { navItems, currentHref, mb: "lg" }),
2567
+ breadcrumb && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(SdBreadcrumb, { navItems, currentHref, mb: "lg" }),
2573
2568
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_core38.Stack, { gap: "xl", children })
2574
2569
  ] });
2575
2570
  }
@@ -2895,11 +2890,11 @@ var theme = (0, import_core39.createTheme)({
2895
2890
  },
2896
2891
  other: {
2897
2892
  logoSizes: {
2898
- xs: { width: 72, height: 22 },
2899
- sm: { width: 96, height: 29 },
2900
- md: { width: 120, height: 36 },
2901
- lg: { width: 160, height: 48 },
2902
- xl: { width: 200, height: 60 }
2893
+ xs: { width: 72 },
2894
+ sm: { width: 96 },
2895
+ md: { width: 120 },
2896
+ lg: { width: 160 },
2897
+ xl: { width: 200 }
2903
2898
  },
2904
2899
  surfaceSubtle: "#f8fafc",
2905
2900
  surfaceDark: "#0f172a",
@@ -919,7 +919,7 @@ interface SdBreadcrumbProps extends BoxProps {
919
919
  * 조상 크럼은 클릭 가능한 링크(`SdLink.Sub`), 마지막(현재 페이지) 크럼은 href 없는
920
920
  * `SdLink.Body`라 링크가 아닌 강조 텍스트(`SdText.Body`)로 폴백해 현재 위치를 나타낸다.
921
921
  */
922
- declare function SdBreadcrumb({ navItems: navItemsProp, currentHref, homeHref, homeLabel, ...boxProps }: SdBreadcrumbProps): react_jsx_runtime.JSX.Element;
922
+ declare function SdBreadcrumb({ navItems: navItemsProp, currentHref, homeHref, homeLabel, ...boxProps }: SdBreadcrumbProps): react_jsx_runtime.JSX.Element | undefined;
923
923
 
924
924
  interface HeroCarouselProps {
925
925
  slides: HeroSlide[];
@@ -930,25 +930,27 @@ declare function HeroCarousel({ slides, children }: HeroCarouselProps): react_js
930
930
  interface HeaderProps {
931
931
  navItems: NavItem[];
932
932
  loginFlag?: boolean;
933
+ /** 로고 크기. 미지정 시 Logo의 theme 기본값(`md`)을 그대로 따른다. */
934
+ logoSize?: MantineSize;
933
935
  }
934
936
  /**
935
937
  * Mega 변형(기본) — 헤더 전체가 아래로 확장되며 하위 링크가 상위 항목 아래 컬럼으로
936
938
  * 한꺼번에 노출되는 메가 메뉴.
937
939
  */
938
- declare function MegaHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
940
+ declare function MegaHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
939
941
  /**
940
942
  * Simple 변형 — 헤더 바 높이는 고정이고, 자식을 가진 상위 항목마다
941
943
  * Mantine `Menu`가 하나씩 붙어 개별 드롭다운으로 열린다.
942
944
  * 바가 자라지 않으므로 AppShell.Header 높이를 그대로 쓰는 레이아웃에 적합하다.
943
945
  */
944
- declare function SimpleHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
946
+ declare function SimpleHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
945
947
  /**
946
948
  * Panel 변형 — Simple처럼 바 높이는 60px로 고정하고 상위 항목마다 Mantine `Menu`가 붙지만,
947
949
  * 드롭다운 내부는 Mega와 동일한 그룹 레이아웃으로 편다: 손자가 없는 자식은 단일 링크,
948
950
  * 손자가 있는 자식은 그룹 제목(`SdLink.Body`) 아래로 손자를 `SdLink.Sub`로 얹는다.
949
951
  * Simple의 개별 드롭다운 안정성 + Mega의 풍부한 그룹 구성이 함께 필요할 때 쓴다.
950
952
  */
951
- declare function PanelHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
953
+ declare function PanelHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
952
954
  declare const SdHeader: typeof MegaHeader & {
953
955
  Mega: typeof MegaHeader;
954
956
  Simple: typeof SimpleHeader;
@@ -963,8 +965,10 @@ interface SdFooterProps {
963
965
  navItems?: NavItem[];
964
966
  policyLinks?: NavItem[];
965
967
  description?: string;
968
+ /** 로고 크기. 기본 `sm`. */
969
+ logoSize?: MantineSize;
966
970
  }
967
- declare function SdFooter({ company, navItems, policyLinks, description }: SdFooterProps): react_jsx_runtime.JSX.Element;
971
+ declare function SdFooter({ company, navItems, policyLinks, description, logoSize }: SdFooterProps): react_jsx_runtime.JSX.Element;
968
972
 
969
973
  interface SdFeatureSectionProps extends Omit<BoxProps, 'title'> {
970
974
  label?: string;
@@ -1052,13 +1056,15 @@ interface SdLoginViewProps {
1052
1056
  children?: ReactNode;
1053
1057
  /** 화면 최소 높이. 카탈로그처럼 좁은 프레임에 담을 때 줄인다. */
1054
1058
  mih?: string | number;
1059
+ /** 로고 크기. 기본 `sm`. */
1060
+ logoSize?: MantineSize;
1055
1061
  }
1056
- declare function Card({ title, description, mih, ...formProps }: SdLoginViewProps): react_jsx_runtime.JSX.Element;
1062
+ declare function Card({ title, description, mih, logoSize, ...formProps }: SdLoginViewProps): react_jsx_runtime.JSX.Element;
1057
1063
  interface SdLoginSplitProps extends SdLoginViewProps {
1058
1064
  brandTitle?: ReactNode;
1059
1065
  brandDescription?: ReactNode;
1060
1066
  }
1061
- declare function Split({ title, description, brandTitle, brandDescription, mih, ...formProps }: SdLoginSplitProps): react_jsx_runtime.JSX.Element;
1067
+ declare function Split({ title, description, brandTitle, brandDescription, mih, logoSize, ...formProps }: SdLoginSplitProps): react_jsx_runtime.JSX.Element;
1062
1068
  declare const SdLoginView: {
1063
1069
  /** 중앙 정렬 카드 — 기본 로그인 화면 */
1064
1070
  Card: typeof Card;
@@ -1096,13 +1102,16 @@ declare const SdResultError: ({ title, description, primaryAction, secondaryActi
1096
1102
 
1097
1103
  /** 헤더 변형 선택자 — SdHeader의 네임스페이스 키와 1:1로 대응한다. */
1098
1104
  type HeaderVariant = 'mega' | 'simple' | 'panel';
1099
- declare function MainLayout({ children, navItems, companyInfo, loginFlag, headerVariant, }: {
1105
+ declare function MainLayout({ children, navItems, companyInfo, loginFlag, headerVariant, headerLogoSize, footerLogoSize, }: {
1100
1106
  children: React.ReactNode;
1101
1107
  navItems: NavItem[];
1102
1108
  companyInfo: CompanyInfo;
1103
1109
  loginFlag?: boolean;
1104
1110
  /** 기본 `mega` — hover 시 헤더가 확장되는 메가 메뉴. `simple`은 바 높이 고정 + 개별 드롭다운. `panel`은 바 높이 고정 + 드롭다운 내부를 Mega식 그룹 컬럼으로. */
1105
1111
  headerVariant?: HeaderVariant;
1112
+ /** 헤더 로고 크기. 미지정 시 Logo의 theme 기본값(`md`)을 그대로 따른다. */
1113
+ headerLogoSize?: MantineSize;
1114
+ footerLogoSize?: MantineSize;
1106
1115
  }): react_jsx_runtime.JSX.Element;
1107
1116
 
1108
1117
  /**
@@ -919,7 +919,7 @@ interface SdBreadcrumbProps extends BoxProps {
919
919
  * 조상 크럼은 클릭 가능한 링크(`SdLink.Sub`), 마지막(현재 페이지) 크럼은 href 없는
920
920
  * `SdLink.Body`라 링크가 아닌 강조 텍스트(`SdText.Body`)로 폴백해 현재 위치를 나타낸다.
921
921
  */
922
- declare function SdBreadcrumb({ navItems: navItemsProp, currentHref, homeHref, homeLabel, ...boxProps }: SdBreadcrumbProps): react_jsx_runtime.JSX.Element;
922
+ declare function SdBreadcrumb({ navItems: navItemsProp, currentHref, homeHref, homeLabel, ...boxProps }: SdBreadcrumbProps): react_jsx_runtime.JSX.Element | undefined;
923
923
 
924
924
  interface HeroCarouselProps {
925
925
  slides: HeroSlide[];
@@ -930,25 +930,27 @@ declare function HeroCarousel({ slides, children }: HeroCarouselProps): react_js
930
930
  interface HeaderProps {
931
931
  navItems: NavItem[];
932
932
  loginFlag?: boolean;
933
+ /** 로고 크기. 미지정 시 Logo의 theme 기본값(`md`)을 그대로 따른다. */
934
+ logoSize?: MantineSize;
933
935
  }
934
936
  /**
935
937
  * Mega 변형(기본) — 헤더 전체가 아래로 확장되며 하위 링크가 상위 항목 아래 컬럼으로
936
938
  * 한꺼번에 노출되는 메가 메뉴.
937
939
  */
938
- declare function MegaHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
940
+ declare function MegaHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
939
941
  /**
940
942
  * Simple 변형 — 헤더 바 높이는 고정이고, 자식을 가진 상위 항목마다
941
943
  * Mantine `Menu`가 하나씩 붙어 개별 드롭다운으로 열린다.
942
944
  * 바가 자라지 않으므로 AppShell.Header 높이를 그대로 쓰는 레이아웃에 적합하다.
943
945
  */
944
- declare function SimpleHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
946
+ declare function SimpleHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
945
947
  /**
946
948
  * Panel 변형 — Simple처럼 바 높이는 60px로 고정하고 상위 항목마다 Mantine `Menu`가 붙지만,
947
949
  * 드롭다운 내부는 Mega와 동일한 그룹 레이아웃으로 편다: 손자가 없는 자식은 단일 링크,
948
950
  * 손자가 있는 자식은 그룹 제목(`SdLink.Body`) 아래로 손자를 `SdLink.Sub`로 얹는다.
949
951
  * Simple의 개별 드롭다운 안정성 + Mega의 풍부한 그룹 구성이 함께 필요할 때 쓴다.
950
952
  */
951
- declare function PanelHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
953
+ declare function PanelHeader({ navItems, loginFlag, logoSize }: HeaderProps): react_jsx_runtime.JSX.Element;
952
954
  declare const SdHeader: typeof MegaHeader & {
953
955
  Mega: typeof MegaHeader;
954
956
  Simple: typeof SimpleHeader;
@@ -963,8 +965,10 @@ interface SdFooterProps {
963
965
  navItems?: NavItem[];
964
966
  policyLinks?: NavItem[];
965
967
  description?: string;
968
+ /** 로고 크기. 기본 `sm`. */
969
+ logoSize?: MantineSize;
966
970
  }
967
- declare function SdFooter({ company, navItems, policyLinks, description }: SdFooterProps): react_jsx_runtime.JSX.Element;
971
+ declare function SdFooter({ company, navItems, policyLinks, description, logoSize }: SdFooterProps): react_jsx_runtime.JSX.Element;
968
972
 
969
973
  interface SdFeatureSectionProps extends Omit<BoxProps, 'title'> {
970
974
  label?: string;
@@ -1052,13 +1056,15 @@ interface SdLoginViewProps {
1052
1056
  children?: ReactNode;
1053
1057
  /** 화면 최소 높이. 카탈로그처럼 좁은 프레임에 담을 때 줄인다. */
1054
1058
  mih?: string | number;
1059
+ /** 로고 크기. 기본 `sm`. */
1060
+ logoSize?: MantineSize;
1055
1061
  }
1056
- declare function Card({ title, description, mih, ...formProps }: SdLoginViewProps): react_jsx_runtime.JSX.Element;
1062
+ declare function Card({ title, description, mih, logoSize, ...formProps }: SdLoginViewProps): react_jsx_runtime.JSX.Element;
1057
1063
  interface SdLoginSplitProps extends SdLoginViewProps {
1058
1064
  brandTitle?: ReactNode;
1059
1065
  brandDescription?: ReactNode;
1060
1066
  }
1061
- declare function Split({ title, description, brandTitle, brandDescription, mih, ...formProps }: SdLoginSplitProps): react_jsx_runtime.JSX.Element;
1067
+ declare function Split({ title, description, brandTitle, brandDescription, mih, logoSize, ...formProps }: SdLoginSplitProps): react_jsx_runtime.JSX.Element;
1062
1068
  declare const SdLoginView: {
1063
1069
  /** 중앙 정렬 카드 — 기본 로그인 화면 */
1064
1070
  Card: typeof Card;
@@ -1096,13 +1102,16 @@ declare const SdResultError: ({ title, description, primaryAction, secondaryActi
1096
1102
 
1097
1103
  /** 헤더 변형 선택자 — SdHeader의 네임스페이스 키와 1:1로 대응한다. */
1098
1104
  type HeaderVariant = 'mega' | 'simple' | 'panel';
1099
- declare function MainLayout({ children, navItems, companyInfo, loginFlag, headerVariant, }: {
1105
+ declare function MainLayout({ children, navItems, companyInfo, loginFlag, headerVariant, headerLogoSize, footerLogoSize, }: {
1100
1106
  children: React.ReactNode;
1101
1107
  navItems: NavItem[];
1102
1108
  companyInfo: CompanyInfo;
1103
1109
  loginFlag?: boolean;
1104
1110
  /** 기본 `mega` — hover 시 헤더가 확장되는 메가 메뉴. `simple`은 바 높이 고정 + 개별 드롭다운. `panel`은 바 높이 고정 + 드롭다운 내부를 Mega식 그룹 컬럼으로. */
1105
1111
  headerVariant?: HeaderVariant;
1112
+ /** 헤더 로고 크기. 미지정 시 Logo의 theme 기본값(`md`)을 그대로 따른다. */
1113
+ headerLogoSize?: MantineSize;
1114
+ footerLogoSize?: MantineSize;
1106
1115
  }): react_jsx_runtime.JSX.Element;
1107
1116
 
1108
1117
  /**
package/dist/ui/index.mjs CHANGED
@@ -32,9 +32,8 @@ var __objRest = (source, exclude) => {
32
32
  };
33
33
 
34
34
  // ui/atom/Logo.tsx
35
- import Image from "next/image";
36
35
  import Link from "next/link";
37
- import { rem, useProps, useMantineTheme } from "@mantine/core";
36
+ import { Image, rem, useProps, useMantineTheme } from "@mantine/core";
38
37
 
39
38
  // util/env.util.ts
40
39
  var _a;
@@ -50,21 +49,7 @@ function Logo(_props) {
50
49
  const { size } = useProps("Logo", { size: "md" }, _props);
51
50
  const theme2 = useMantineTheme();
52
51
  const resolved = theme2.other.logoSizes[size];
53
- return /* @__PURE__ */ jsx(Link, { href: "/", style: { display: "inline-flex", alignItems: "center" }, children: /* @__PURE__ */ jsx(
54
- Image,
55
- {
56
- src: LOGO_SRC,
57
- alt: LOGO_ALT,
58
- width: resolved.width,
59
- height: resolved.height,
60
- style: {
61
- width: rem(resolved.width),
62
- height: "auto",
63
- objectFit: "contain"
64
- },
65
- priority: true
66
- }
67
- ) });
52
+ return /* @__PURE__ */ jsx(Link, { href: "/", style: { display: "inline-flex", alignItems: "center" }, children: /* @__PURE__ */ jsx(Image, { src: LOGO_SRC, alt: LOGO_ALT, w: rem(resolved.width), h: "auto", fit: "contain", fetchPriority: "high" }) });
68
53
  }
69
54
 
70
55
  // ui/atom/Tabs.tsx
@@ -1584,6 +1569,7 @@ function SdBreadcrumb(_a4) {
1584
1569
  const navItems = navItemsProp != null ? navItemsProp : navFromContext;
1585
1570
  const pathname = usePathname();
1586
1571
  const trail = buildTrail(navItems, (_a5 = currentHref != null ? currentHref : pathname) != null ? _a5 : "");
1572
+ if (navItems.length === 0) return;
1587
1573
  return /* @__PURE__ */ jsx29(Box11, __spreadProps(__spreadValues({}, boxProps), { children: /* @__PURE__ */ jsxs15(
1588
1574
  Breadcrumbs,
1589
1575
  {
@@ -1710,7 +1696,7 @@ function MobileNav({ opened, close, topItems, childrenOf, loginFlag }) {
1710
1696
  loginFlag && /* @__PURE__ */ jsx31(Stack16, { gap: "xs", mt: "md", children: /* @__PURE__ */ jsx31(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
1711
1697
  ] }) });
1712
1698
  }
1713
- function MegaHeader({ navItems, loginFlag }) {
1699
+ function MegaHeader({ navItems, loginFlag, logoSize }) {
1714
1700
  const [opened, { toggle, close }] = useDisclosure();
1715
1701
  const { topItems, childrenOf, hasAnyChildren } = useNavTree(navItems);
1716
1702
  const { hovered, ref: hoverRef } = useHover();
@@ -1730,7 +1716,7 @@ function MegaHeader({ navItems, loginFlag }) {
1730
1716
  transition: "box-shadow 0.15s"
1731
1717
  },
1732
1718
  children: /* @__PURE__ */ jsx31(SdContainer, { children: /* @__PURE__ */ jsxs17(Group10, { justify: "space-between", align: "flex-start", wrap: "nowrap", children: [
1733
- /* @__PURE__ */ jsx31(Group10, { h: BAR_HEIGHT, align: "center", children: /* @__PURE__ */ jsx31(Logo, {}) }),
1719
+ /* @__PURE__ */ jsx31(Group10, { h: BAR_HEIGHT, align: "center", children: /* @__PURE__ */ jsx31(Logo, { size: logoSize }) }),
1734
1720
  /* @__PURE__ */ jsx31(Group10, { gap: "xl", align: "flex-start", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
1735
1721
  const kids = childrenOf(item.id);
1736
1722
  return /* @__PURE__ */ jsxs17(Stack16, { gap: 0, align: "center", children: [
@@ -1789,12 +1775,12 @@ function MegaHeader({ navItems, loginFlag }) {
1789
1775
  function renderMenuLeaf(item) {
1790
1776
  return item.href ? /* @__PURE__ */ jsx31(Menu.Item, { component: "a", href: item.href, children: item.label }, item.id) : /* @__PURE__ */ jsx31(Menu.Label, { children: item.label }, item.id);
1791
1777
  }
1792
- function SimpleHeader({ navItems, loginFlag }) {
1778
+ function SimpleHeader({ navItems, loginFlag, logoSize }) {
1793
1779
  const [opened, { toggle, close }] = useDisclosure();
1794
1780
  const { topItems, childrenOf } = useNavTree(navItems);
1795
1781
  return /* @__PURE__ */ jsxs17(Fragment4, { children: [
1796
1782
  /* @__PURE__ */ jsx31(Box13, { bg: "var(--mantine-color-body)", children: /* @__PURE__ */ jsx31(SdContainer, { children: /* @__PURE__ */ jsxs17(Group10, { h: BAR_HEIGHT, justify: "space-between", align: "center", wrap: "nowrap", children: [
1797
- /* @__PURE__ */ jsx31(Logo, {}),
1783
+ /* @__PURE__ */ jsx31(Logo, { size: logoSize }),
1798
1784
  /* @__PURE__ */ jsx31(Group10, { gap: "xl", align: "center", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
1799
1785
  const kids = childrenOf(item.id);
1800
1786
  if (kids.length === 0) {
@@ -1855,12 +1841,12 @@ function SimpleHeader({ navItems, loginFlag }) {
1855
1841
  )
1856
1842
  ] });
1857
1843
  }
1858
- function PanelHeader({ navItems, loginFlag }) {
1844
+ function PanelHeader({ navItems, loginFlag, logoSize }) {
1859
1845
  const [opened, { toggle, close }] = useDisclosure();
1860
1846
  const { topItems, childrenOf } = useNavTree(navItems);
1861
1847
  return /* @__PURE__ */ jsxs17(Fragment4, { children: [
1862
1848
  /* @__PURE__ */ jsx31(Box13, { bg: "var(--mantine-color-body)", children: /* @__PURE__ */ jsx31(SdContainer, { children: /* @__PURE__ */ jsxs17(Group10, { h: BAR_HEIGHT, justify: "space-between", align: "center", wrap: "nowrap", children: [
1863
- /* @__PURE__ */ jsx31(Logo, {}),
1849
+ /* @__PURE__ */ jsx31(Logo, { size: logoSize }),
1864
1850
  /* @__PURE__ */ jsx31(Group10, { gap: "xl", align: "center", wrap: "nowrap", visibleFrom: "sm", children: topItems.map((item) => {
1865
1851
  const kids = childrenOf(item.id);
1866
1852
  if (kids.length === 0) {
@@ -1994,11 +1980,11 @@ function FooterCompanyInfo({ company }) {
1994
1980
  /* @__PURE__ */ jsx32(InfoCell, { label: "Email", children: /* @__PURE__ */ jsx32(SdLink.Sub, { href: `mailto:${company.email}`, children: company.email }) })
1995
1981
  ] });
1996
1982
  }
1997
- function SdFooter({ company, navItems, policyLinks, description }) {
1983
+ function SdFooter({ company, navItems, policyLinks, description, logoSize = "sm" }) {
1998
1984
  const visibleNav = filterAndSort(navItems);
1999
1985
  const visiblePolicy = filterAndSort(policyLinks);
2000
1986
  return /* @__PURE__ */ jsx32(Box14, { component: "footer", children: /* @__PURE__ */ jsx32(SdContainer, { py: "lg", children: /* @__PURE__ */ jsxs18(Stack17, { children: [
2001
- /* @__PURE__ */ jsx32(Logo, { size: "sm" }),
1987
+ /* @__PURE__ */ jsx32(Logo, { size: logoSize }),
2002
1988
  description && /* @__PURE__ */ jsx32(SdText.Sub, { children: description }),
2003
1989
  /* @__PURE__ */ jsxs18(Flex, { direction: { base: "column", md: "row" }, gap: 48, align: "flex-start", children: [
2004
1990
  /* @__PURE__ */ jsx32(Box14, { flex: { base: "0 0 auto", md: "1 1 0" }, w: { base: "100%", md: "auto" }, children: /* @__PURE__ */ jsx32(FooterCompanyInfo, { company }) }),
@@ -2282,9 +2268,13 @@ function LoginForm({
2282
2268
  children
2283
2269
  ] }) });
2284
2270
  }
2285
- function FormHeader({ title, description }) {
2271
+ function FormHeader({
2272
+ title,
2273
+ description,
2274
+ logoSize = "sm"
2275
+ }) {
2286
2276
  return /* @__PURE__ */ jsxs23(Stack22, { gap: "lg", children: [
2287
- /* @__PURE__ */ jsx37(Logo, { size: "sm" }),
2277
+ /* @__PURE__ */ jsx37(Logo, { size: logoSize }),
2288
2278
  /* @__PURE__ */ jsx37(SdTextBox.Card, { title, description: description != null ? description : "" })
2289
2279
  ] });
2290
2280
  }
@@ -2292,14 +2282,16 @@ function Card7(_a4) {
2292
2282
  var _b = _a4, {
2293
2283
  title = "\uB85C\uADF8\uC778",
2294
2284
  description = "%c \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD558\uB824\uBA74 \uB85C\uADF8\uC778\uD574 \uC8FC\uC138\uC694.",
2295
- mih = "100svh"
2285
+ mih = "100svh",
2286
+ logoSize
2296
2287
  } = _b, formProps = __objRest(_b, [
2297
2288
  "title",
2298
2289
  "description",
2299
- "mih"
2290
+ "mih",
2291
+ "logoSize"
2300
2292
  ]);
2301
2293
  return /* @__PURE__ */ jsx37(Center5, { mih, bg: "slate.0", p: "md", children: /* @__PURE__ */ jsx37(Paper, { w: "100%", maw: 420, p: { base: "lg", sm: "xl" }, radius: "lg", withBorder: true, shadow: "sm", children: /* @__PURE__ */ jsxs23(Stack22, { gap: "xl", children: [
2302
- /* @__PURE__ */ jsx37(FormHeader, { title, description }),
2294
+ /* @__PURE__ */ jsx37(FormHeader, { title, description, logoSize }),
2303
2295
  /* @__PURE__ */ jsx37(LoginForm, __spreadValues({}, formProps))
2304
2296
  ] }) }) });
2305
2297
  }
@@ -2309,13 +2301,15 @@ function Split(_a4) {
2309
2301
  description = "\uACC4\uC815 \uC815\uBCF4\uB97C \uC785\uB825\uD574 \uC8FC\uC138\uC694.",
2310
2302
  brandTitle = "%c",
2311
2303
  brandDescription = "\uD558\uB098\uC758 \uACC4\uC815\uC73C\uB85C \uBAA8\uB4E0 \uC11C\uBE44\uC2A4\uB97C \uC774\uC6A9\uD558\uC138\uC694.",
2312
- mih = "100svh"
2304
+ mih = "100svh",
2305
+ logoSize
2313
2306
  } = _b, formProps = __objRest(_b, [
2314
2307
  "title",
2315
2308
  "description",
2316
2309
  "brandTitle",
2317
2310
  "brandDescription",
2318
- "mih"
2311
+ "mih",
2312
+ "logoSize"
2319
2313
  ]);
2320
2314
  return /* @__PURE__ */ jsxs23(SimpleGrid7, { cols: { base: 1, md: 2 }, spacing: 0, mih, children: [
2321
2315
  /* @__PURE__ */ jsxs23(
@@ -2341,7 +2335,7 @@ function Split(_a4) {
2341
2335
  }
2342
2336
  ),
2343
2337
  /* @__PURE__ */ jsx37(Center5, { p: { base: "md", sm: "xl" }, bg: "white", children: /* @__PURE__ */ jsxs23(Stack22, { gap: "xl", w: "100%", maw: 400, children: [
2344
- /* @__PURE__ */ jsx37(FormHeader, { title, description }),
2338
+ /* @__PURE__ */ jsx37(FormHeader, { title, description, logoSize }),
2345
2339
  /* @__PURE__ */ jsx37(LoginForm, __spreadValues({}, formProps))
2346
2340
  ] }) })
2347
2341
  ] });
@@ -2415,13 +2409,15 @@ function MainLayout({
2415
2409
  navItems,
2416
2410
  companyInfo,
2417
2411
  loginFlag,
2418
- headerVariant = "mega"
2412
+ headerVariant = "mega",
2413
+ headerLogoSize,
2414
+ footerLogoSize
2419
2415
  }) {
2420
2416
  const Header = headers[headerVariant];
2421
2417
  return /* @__PURE__ */ jsxs25(AppShell, { header: { height: 60 }, children: [
2422
- /* @__PURE__ */ jsx39(AppShell.Header, { children: /* @__PURE__ */ jsx39(Header, { navItems, loginFlag }) }),
2418
+ /* @__PURE__ */ jsx39(AppShell.Header, { children: /* @__PURE__ */ jsx39(Header, { navItems, loginFlag, logoSize: headerLogoSize }) }),
2423
2419
  /* @__PURE__ */ jsx39(AppShell.Main, { children }),
2424
- /* @__PURE__ */ jsx39(SdFooter, { company: companyInfo, navItems })
2420
+ /* @__PURE__ */ jsx39(SdFooter, { company: companyInfo, navItems, logoSize: footerLogoSize })
2425
2421
  ] });
2426
2422
  }
2427
2423
 
@@ -2437,9 +2433,8 @@ function Content({
2437
2433
  breadcrumb = true,
2438
2434
  currentHref
2439
2435
  }) {
2440
- const showBreadcrumb = breadcrumb && !!navItems && navItems.length > 0;
2441
2436
  return /* @__PURE__ */ jsxs26(SdContainer, { py: "xl", children: [
2442
- showBreadcrumb && /* @__PURE__ */ jsx40(SdBreadcrumb, { navItems, currentHref, mb: "lg" }),
2437
+ breadcrumb && /* @__PURE__ */ jsx40(SdBreadcrumb, { navItems, currentHref, mb: "lg" }),
2443
2438
  /* @__PURE__ */ jsx40(Stack24, { gap: "xl", children })
2444
2439
  ] });
2445
2440
  }
@@ -2765,11 +2760,11 @@ var theme = createTheme({
2765
2760
  },
2766
2761
  other: {
2767
2762
  logoSizes: {
2768
- xs: { width: 72, height: 22 },
2769
- sm: { width: 96, height: 29 },
2770
- md: { width: 120, height: 36 },
2771
- lg: { width: 160, height: 48 },
2772
- xl: { width: 200, height: 60 }
2763
+ xs: { width: 72 },
2764
+ sm: { width: 96 },
2765
+ md: { width: 120 },
2766
+ lg: { width: 160 },
2767
+ xl: { width: 200 }
2773
2768
  },
2774
2769
  surfaceSubtle: "#f8fafc",
2775
2770
  surfaceDark: "#0f172a",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeongseoksong/framework",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],