import { type HTMLAttributes } from 'react'; import type { SGnbHeader, SGnbType } from '../SGnb/gnb.config'; /** 메뉴 스타일: box(라운드) / belt(풀폭 행) — 자식 SGnb 의 메뉴 모양 */ export type SLayoutType = SGnbType; /** 레이아웃 구조: fix(좌측 GNB + 페이지 가로 분할) / full(풀폭 상단바 + 아래에 메뉴|페이지) */ export type SLayoutHeader = SGnbHeader; /** * 자식 GNB 가 SLayout 에 올리는 자기 치수·요구사항. * * SLayout 은 GNB 의 내부 상수(레일·메뉴 폭, 상단바 높이, 전환 길이)도 items·activeRail 도 모른다 — * 치수를 아는 쪽이 올리고 프레임은 받아 쓰기만 한다. GNB 내부 치수가 바뀌어도 프레임은 따라온다. */ export interface SLayoutNavState { /** * 펼친 GNB 컬럼 폭(px). 레일·메뉴 유무를 반영한 합이다. * 접힘은 SLayout 이 folded 로 따로 접으므로 여기엔 펼친 폭만 담는다. */ columnWidth: number; /** 상단바 높이(CSS 길이) — header="full" 그리드의 1행 높이가 된다. */ topHeight: string; /** 접힘 전환 길이(ms) — 페이지 열이 메뉴와 같은 길이로 미끄러지도록 맞춘다. */ foldMs: number; /** * 상단바가 레이아웃 전폭이어야 하는지. * 레일에 리프 아이템이 있으면 메뉴 폭이 출렁여 fix 상단바가 함께 흔들리므로 GNB 가 true 로 올린다. * true 면 header prop 과 무관하게 full 로 선다. */ requireFullHeader: boolean; /** * GNB 폭을 지금 드래그로 조절하는 중인지. * 참이면 메뉴 열의 폭 전환을 끈다 — 접힘용 전환(foldMs)이 그대로 걸려 있으면 * 열이 손보다 그 길이만큼 늦게 따라와 끌리는 느낌이 사라진다. */ resizing?: boolean; } export interface SLayoutContextValue { /** 메뉴 스타일 — 자식 SGnb 가 스타일을 맞추는 기준 */ type: SLayoutType; /** * 상단바 구조 — 자식 SGnb·SPage 가 배치를 맞추는 기준(유효 header). * 등록된 GNB 가 requireFullHeader 를 올리면 여기에도 full 로 반영된다. */ header: SLayoutHeader; /** GNB 좌측 레일 사용 여부 — 자식 SGnb 가 따른다 */ useRail: boolean; /** GNB 접힘 상태 */ folded: boolean; /** 접힘 상태 변경 */ setFolded: (folded: boolean) => void; /** * 자식 GNB 가 자기 치수·요구사항을 등록한다. 언마운트하거나 SLayout 밖으로 나가면 null 로 해제한다. * 페인트 전에 반영돼야 하므로 GNB 쪽에서 layout effect 로 호출한다. */ registerNav: (nav: SLayoutNavState | null) => void; } export declare const SLayoutContext: import("react").Context; /** * 레이아웃이 보장하는 최소 가로 폭(px). GNB 를 포함한 전체 기준이다. * 전용 토큰이 없어 상수로 둔다(GNB_MENU_WIDTH 와 같은 이유). * * 창이 이보다 좁아져도 프레임 자체는 창을 넘지 않는다 — 모자란 몫은 SPage 가 가로 스크롤로 삼킨다. * 그래서 GNB·상단바는 제자리에 남고 문서(창)에는 스크롤이 생기지 않는다. */ export declare const SLAYOUT_MIN_WIDTH = 1366; /** * SPage 가 자기 콘텐츠의 최소 폭을 계산할 때 읽는 변수. SLayout 이 프레임에 심는다. * SLayout 밖의 SPage 는 이 변수가 없어(폴백 0) 최소 폭 규칙이 걸리지 않는다. */ export declare const SLAYOUT_MIN_WIDTH_VAR = "--s-layout-min-width"; /** * SLayout 의 상태를 읽고 제어한다. `` 밖에서 호출하면 throw. * 외부 버튼으로 GNB 를 접거나, 현재 구조(header)·메뉴 스타일(type)에 따라 분기할 때 사용한다. */ export declare function useSLayout(): SLayoutContextValue; export interface SLayoutProps extends HTMLAttributes { /** 메뉴 스타일: box(라운드) / belt(풀폭 행). 자식 SGnb 가 이 값을 따른다. */ type?: SLayoutType; /** 레이아웃 구조: fix(가로 분할) / full(풀폭 상단바). 자식 SGnb·SPage 가 이 값을 따른다. */ header?: SLayoutHeader; /** * GNB 좌측 레일 사용 여부. 자식 SGnb 가 이 값을 따르고, 그만큼 넓어진 컬럼 폭을 되올린다. * 레일에 children 없는 아이템이 있으면 SGnb 가 full 상단바를 요구하고, 이 레이아웃도 그에 맞춰 full 그리드로 선다. */ useRail?: boolean; /** GNB 접힘 상태 (controlled) */ folded?: boolean; /** GNB 초기 접힘 상태 (uncontrolled) */ defaultFolded?: boolean; /** 접힘 상태 변경 */ onFoldedChange?: (folded: boolean) => void; } /** * SLayout — 앱 셸 프레임 겸 context provider. * header 가 배치를 결정하고 overflow:hidden 으로 스크롤 경계를 만든다. * 자식 SGnb·SPage 는 context 에서 type·header·folded 를 읽으므로 앱은 이 값들을 여기 한 곳에만 쓴다. * 높이는 기본 100%(부모를 채움) — 앱 루트로 쓸 땐 부모를 뷰포트 높이로 잡는다. * * 가로는 SLAYOUT_MIN_WIDTH 를 최소 폭으로 보장한다. 창이 그보다 좁아도 프레임은 창 폭을 그대로 받고, * 모자란 몫은 SPage 가 가로 스크롤로 삼킨다 — GNB·상단바는 제자리에 남고 문서엔 스크롤이 생기지 않는다. * * 치수는 자식이 소유한다: GNB 가 registerNav 로 컬럼 폭·상단바 높이·전환 길이를 올리고 * 이 프레임은 그 값으로 그리드를 깐다(SLayout 은 GNB 내부 상수를 import 하지 않는다). * * - header="fix": [GNB(자기 폭 소유) | 페이지] 가로 flex. 프레임이 폭에 관여하지 않는다. * - header="full": 이름 있는 영역으로 깐 그리드다. * "header header" ← 전폭 상단바 (1행, 높이 = 등록된 topHeight) * "nav page" ← 메뉴 열(등록된 columnWidth) | 페이지 * 접으면 nav 열을 0 으로 접어 페이지가 전폭을 쓴다. */ export declare const SLayout: import("react").ForwardRefExoticComponent>;