import type { LeviarObject } from 'leviar'; import type { NovelConfig, CharDefs, BgDefs, SceneNextTarget, EnvironmentsOf } from '../types/config'; import type { NovelModule } from '../define/defineCmdUI'; import type { SceneHookDescriptor } from '../define/defineCmdUI'; import type { DialogueStep } from '../types/dialogue'; import type { SceneContext } from '../core/SceneContext'; /** * `config.modules` 타입에서 `initial` 허용 값 구조를 추출합니다. * key: `keyof TModules`, value: 해당 `NovelModule`의 스키마(`TSchema`)의 `Partial` */ export type InitialOf = { [K in keyof TModules]?: TModules[K] extends NovelModule ? Partial : never; }; /** * `defineScene` 외부에서 `initial` 데이터를 공통 모듈로 분리할 때 사용하는 타입 추론 헬퍼입니다. * * @example * import config from '../novel.config' * import { defineInitial } from 'fumika' * * export const commonInitial = defineInitial(config)({ * dialogue: { text: { fontSize: 18 } } * }) */ export declare function defineInitial & { modules?: Record>; }>(config: TConfig): : InitialOf>)>(initial: TInitial & ([ TConfig['modules'] ] extends [undefined] ? unknown : { [K in keyof TInitial]: K extends keyof NonNullable ? unknown : never; })) => typeof initial; /** 씬 정의 결과물. Scene 실행기가 소비합니다. */ export interface SceneDefinition = Record, TLocalVars extends Record<`_${string}`, any> = Record> { readonly kind: 'dialogue'; name?: string; readonly dialogues: DialogueStep[]; readonly localVars?: TLocalVars; /** 씬 종료 시 자동으로 이동할 다음 씬. 문자열 또는 { scene, preserve } 객체. */ readonly nextScene?: string | { scene: string; preserve: boolean; }; /** * 씬 시작 시 자동으로 초기화할 모듈 데이터. * `novel.config`의 `modules` 키를 기반으로 타입이 추론됩니다. */ readonly initial?: Record; /** * 씬 스코프 훅 디스크립터. * `defineHook()`의 반환값을 전달하면 씬 시작 시 자동 등록, 씬 종료 시 자동 해제됩니다. */ readonly hooks?: SceneHookDescriptor; /** * 씬 스코프 액션 맵. * `element` 명령어의 `behaviors`에서 이름으로 참조하여 호출됩니다. * 각 콜백은 요소가 생성될 때 호출되며, 이벤트 리스너 등을 등록합니다. */ readonly actions?: Record void>; } import type { SceneNamesOf } from '../types/config'; /** * defineScene의 builder 함수에 주입되는 흐름제어 예약어 헬퍼. * 이 함수들은 빌드타임에 flat 배열로 컴파일되는 마커 객체를 반환합니다. */ export type SceneBuilders> = { /** 씬 내부 점프 위치를 정의합니다. */ label: (name: string) => DialogueStep; /** 라벨 위치로 실행 커서를 이동합니다. */ goto: (name: string) => DialogueStep; /** 다른 씬으로 전환합니다. */ next: (scene: SceneNamesOf, opts?: { preserve?: boolean; }) => DialogueStep; /** 다른 씬을 서브루틴으로 호출합니다. */ call: (scene: SceneNamesOf, opts?: { preserve?: boolean; restore?: boolean; }) => DialogueStep; /** 조건 분기. ifSteps / elseSteps 내부에 중첩 사용 가능. */ condition: (fn: ((vars: TVars & TLocalVars & TEnvs) => boolean) | boolean, ifSteps: DialogueStep[], elseSteps?: DialogueStep[]) => DialogueStep; /** 변수 값을 설정합니다. `$` 접두사는 환경변수, `_` 접두사는 지역변수, 그 외는 전역변수. */ set: (name: K, value: (TVars & TLocalVars & TEnvs)[K] | ((vars: TVars & TLocalVars & TEnvs) => (TVars & TLocalVars & TEnvs)[K])) => DialogueStep; }; type _SceneOptions, TConfig extends NovelConfig & { modules?: Record>; }, TLocalVars extends Record<`_${string}`, any>, TInitial extends ([TConfig['modules']] extends [undefined] ? Record : InitialOf>)> = { config: TConfig & { variables: TVars; }; variables?: keyof TLocalVars extends `_${string}` ? TLocalVars : never; /** 씬 시작 시 적용할 모듈 초기 데이터 (optional). config.modules 키/값 타입 추론. */ initial?: TInitial & ([ TConfig['modules'] ] extends [undefined] ? unknown : { [K in keyof TInitial]: K extends keyof NonNullable ? unknown : never; }); /** 씬 종료 시 자동으로 이동할 다음 씬. 문자열 또는 { scene, preserve } 객체. */ next?: SceneNextTarget; /** * 씬 스코프 훅 디스크립터. `defineHook(config)({ ... })`의 반환값. * 씬 시작 시 자동으로 훅이 등록되고, 씬 종료/전환 시 자동으로 해제됩니다. */ hooks?: SceneHookDescriptor; /** * 씬 스코프 액션 맵. * element의 behaviors에서 이름 문자열로 참조하여 호출됩니다. * * @example * actions: { * saveButton: (element, ctx) => { * element.on('click', () => { * const data = ctx.novel.save() * localStorage.setItem('save', JSON.stringify(data)) * }) * } * } */ actions?: Record>) => void>; }; type _SceneReturn = SceneDefinition; } ? A : Record, TLocalVars extends Record<`_${string}`, any> ? TLocalVars : Record>; /** * DialogueScene을 정의합니다. * * Curried builder 함수 형식을 사용합니다. * 두 번째 인자(함수)에 흐름제어 builder가 주입됩니다. * * @example * export default defineScene({ config, variables: { _tries: 0 } })( * ({ label, goto, next, call, condition, set }) => [ * label('start'), * { type: 'dialogue', text: '안녕!' }, * condition( * ({ _tries }) => _tries >= 3, * [goto('end')], * [set('_tries', 1)] * ), * label('end'), * next('scene-b'), * ] * ) */ export declare function defineScene, TConfig extends NovelConfig & { modules?: Record>; }, TLocalVars extends Record<`_${string}`, any> = Record, TInitial extends ([TConfig['modules']] extends [undefined] ? Record : InitialOf>) = ([TConfig['modules']] extends [undefined] ? Record : InitialOf>)>(options: _SceneOptions): (factory: (builders: SceneBuilders>) => DialogueStep[]) => _SceneReturn; export {};