type CourseId = string; type LessonId = string; type CheckId = string; type BlockId = string; /** Stable URN string returned by {@link buildLessonkitUrn}. */ type LessonkitUrn = string; type IdentityValidationIssue = { path: string; message: string; }; type IdentityValidationResult = { ok: true; id: string; } | { ok: false; issues: IdentityValidationIssue[]; }; type IdentityIdPath = "courseId" | "lessonId" | "checkId" | "blockId" | "id"; /** LessonKit id format: letter first, then alphanumeric, `_`, `-`; length 1–64. */ declare const ID_PATTERN: RegExp; declare const ID_MAX_LENGTH = 64; /** H5P-aligned interaction kinds for assessment telemetry and xAPI. */ type AssessmentInteractionType = "mcq" | "trueFalse" | "fillInBlanks" | "markTheWords" | "dragTheWords" | "dragAndDrop" | "assessmentSequence" | "findHotspot" | "findMultipleHotspots" | "summary" | "imagePairing" | "imageSequencing" | "essay" | "arithmeticQuiz" | "memoryGame" | "combinationLock" | "crossword" | "wordSearch" | "sortParagraphs" | "guessTheAnswer"; /** Serializable resume blob for a single assessment block. */ type AssessmentResumeState = Record; /** Behaviour flags aligned with H5P question types. */ type AssessmentBehaviour = { enableRetry?: boolean; enableSolutionsButton?: boolean; autoCheck?: boolean; }; /** Payload for xAPI mapping from assessment components. */ type AssessmentXAPIData = { checkId: CheckId; interactionType: AssessmentInteractionType; response?: string | string[] | boolean | Record; correct?: boolean; score?: number; maxScore?: number; }; /** * Imperative handle for scored blocks (H5P question-type contract analogue). * Parent containers (`AssessmentSequence`, future compounds) may call these methods. */ type AssessmentHandle = { getScore: () => number; getMaxScore: () => number; getAnswerGiven: () => boolean; resetTask: () => void; showSolutions: () => void; getXAPIData: () => AssessmentXAPIData; getCurrentState?: () => AssessmentResumeState; resume?: (state: AssessmentResumeState) => void; }; type AssessmentBaseProps = AssessmentBehaviour & { checkId: CheckId; passingScore?: number; }; /** * MCQ assessment props shared by React components and LMS packaging descriptors. * * @example * ```tsx * const props: McqAssessmentProps = { * checkId: "verify-sender", * question: "First step for a suspicious email?", * choices: ["Open attachment", "Verify sender"], * answer: "Verify sender", * passingScore: 1, * }; * ``` */ type McqAssessmentProps = AssessmentBaseProps & { kind?: "mcq"; question: string; choices: string[]; /** Single correct choice (required for backward compatibility). */ answer: string; /** When length > 1, enables multi-select checkbox mode. */ answers?: string[]; /** Randomize choice display order in the SPA (stable when `shuffleSeed` set). */ shuffleChoices?: boolean; /** Seed for deterministic shuffle; defaults to `checkId`. */ shuffleSeed?: string | number; /** Per-choice feedback announced on selection; keys match choice labels. */ choiceFeedback?: Record; }; type TelemetryEventName = "course_started" | "course_completed" | "lesson_started" | "lesson_completed" | "lesson_time_on_task" | "quiz_answered" | "quiz_completed" | "assessment_answered" | "assessment_completed" | "interaction" | "book_page_viewed" | "slide_viewed" | "compound_page_viewed" | "hotspot_opened" | "accordion_section_toggled" | "flashcard_flipped" | "image_slider_changed" | "video_cue_reached" | "video_segment_completed" | "memory_card_flipped" | "information_wall_search" | "parallax_slide_viewed" | "questionnaire_submitted" | "branch_node_viewed" | "branch_selected" | "image_juxtaposition_changed" | "timeline_event_viewed" | "image_sequence_changed" | "audio_recording_started" | "audio_recording_completed" | "qr_content_revealed" | "advent_door_opened" | "map_stage_viewed" | "map_exit_selected"; type TelemetryUser = { id?: string; email?: string; name?: string; [key: string]: unknown; }; type TelemetryEventBase = { timestamp: string; courseId: CourseId; /** Optional stable id for sink deduplication (e.g. deliver retry). */ id?: string; sessionId?: string; attemptId?: string; user?: TelemetryUser; }; type LessonLifecycleData = { lessonId: LessonId; durationMs?: number; success?: boolean; score?: number; maxScore?: number; }; type QuizAnsweredData = { checkId: CheckId; question: string; choice: string; correct: boolean; }; type QuizCompletedData = { checkId: CheckId; score?: number; maxScore?: number; passingScore?: number; }; type AssessmentAnsweredData = { checkId: CheckId; interactionType: AssessmentInteractionType; question?: string; response?: string | string[] | boolean | Record; correct?: boolean; }; type AssessmentCompletedData = { checkId: CheckId; interactionType: AssessmentInteractionType; score?: number; maxScore?: number; passingScore?: number; }; type InteractionData = { kind?: string; blockId?: BlockId; payload?: Record; [key: string]: unknown; }; type BookPageViewedData = { blockId: BlockId; pageIndex: number; pageTitle?: string; }; type SlideViewedData = { blockId: BlockId; slideIndex: number; slideTitle?: string; }; type CompoundPageViewedData = { blockId: BlockId; pageIndex: number; parentType?: string; }; type HotspotOpenedData = { blockId: BlockId; hotspotId: string; }; type AccordionSectionToggledData = { blockId: BlockId; sectionId: string; expanded: boolean; }; type FlashcardFlippedData = { blockId: BlockId; cardIndex: number; face: "front" | "back"; }; type ImageSliderChangedData = { blockId: BlockId; slideIndex: number; }; type VideoCueReachedData = { blockId: BlockId; cueIndex: number; atSeconds: number; cueLabel?: string; }; type VideoSegmentCompletedData = { blockId: BlockId; segmentIndex: number; atSeconds: number; segmentLabel?: string; }; type MemoryCardFlippedData = { blockId: BlockId; cardIndex: number; face: "front" | "back"; }; type InformationWallSearchData = { blockId: BlockId; query: string; resultCount: number; }; type ParallaxSlideViewedData = { blockId: BlockId; slideIndex: number; }; type QuestionnaireSubmittedData = { blockId: BlockId; fieldCount: number; }; type BranchNodeViewedData = { blockId: BlockId; nodeId: string; nodeIndex: number; nodeTitle?: string; }; type BranchSelectedData = { blockId: BlockId; fromNodeId: string; toNodeId: string; label: string; scoreWeight?: number; }; type ImageJuxtapositionChangedData = { blockId: BlockId; position: number; }; type TimelineEventViewedData = { blockId: BlockId; eventId: string; }; type ImageSequenceChangedData = { blockId: BlockId; frameIndex: number; }; type AudioRecordingData = { blockId: BlockId; }; type QrContentRevealedData = { blockId: BlockId; }; type AdventDoorOpenedData = { blockId: BlockId; doorId: string; day: number; }; type MapStageViewedData = { blockId: BlockId; stageId: string; stageIndex: number; stageLabel?: string; }; type MapExitSelectedData = { blockId: BlockId; fromStageId: string; toStageId: string; label: string; scoreWeight?: number; }; type TelemetryEvent = (TelemetryEventBase & { name: "course_started"; lessonId?: LessonId; data?: undefined; }) | (TelemetryEventBase & { name: "course_completed"; lessonId?: LessonId; data?: undefined; }) | (TelemetryEventBase & { name: "lesson_started"; lessonId: LessonId; data: LessonLifecycleData; }) | (TelemetryEventBase & { name: "lesson_completed"; lessonId: LessonId; data: LessonLifecycleData; }) | (TelemetryEventBase & { name: "lesson_time_on_task"; lessonId: LessonId; data: LessonLifecycleData; }) | (TelemetryEventBase & { name: "quiz_answered"; lessonId: LessonId; data: QuizAnsweredData; }) | (TelemetryEventBase & { name: "quiz_completed"; lessonId: LessonId; data: QuizCompletedData; }) | (TelemetryEventBase & { name: "assessment_answered"; lessonId: LessonId; data: AssessmentAnsweredData; }) | (TelemetryEventBase & { name: "assessment_completed"; lessonId: LessonId; data: AssessmentCompletedData; }) | (TelemetryEventBase & { name: "interaction"; lessonId?: LessonId; data?: InteractionData; }) | (TelemetryEventBase & { name: "book_page_viewed"; lessonId: LessonId; data: BookPageViewedData; }) | (TelemetryEventBase & { name: "slide_viewed"; lessonId: LessonId; data: SlideViewedData; }) | (TelemetryEventBase & { name: "compound_page_viewed"; lessonId: LessonId; data: CompoundPageViewedData; }) | (TelemetryEventBase & { name: "hotspot_opened"; lessonId?: LessonId; data: HotspotOpenedData; }) | (TelemetryEventBase & { name: "accordion_section_toggled"; lessonId?: LessonId; data: AccordionSectionToggledData; }) | (TelemetryEventBase & { name: "flashcard_flipped"; lessonId?: LessonId; data: FlashcardFlippedData; }) | (TelemetryEventBase & { name: "image_slider_changed"; lessonId?: LessonId; data: ImageSliderChangedData; }) | (TelemetryEventBase & { name: "video_cue_reached"; lessonId: LessonId; data: VideoCueReachedData; }) | (TelemetryEventBase & { name: "video_segment_completed"; lessonId: LessonId; data: VideoSegmentCompletedData; }) | (TelemetryEventBase & { name: "memory_card_flipped"; lessonId?: LessonId; data: MemoryCardFlippedData; }) | (TelemetryEventBase & { name: "information_wall_search"; lessonId?: LessonId; data: InformationWallSearchData; }) | (TelemetryEventBase & { name: "parallax_slide_viewed"; lessonId?: LessonId; data: ParallaxSlideViewedData; }) | (TelemetryEventBase & { name: "questionnaire_submitted"; lessonId: LessonId; data: QuestionnaireSubmittedData; }) | (TelemetryEventBase & { name: "branch_node_viewed"; lessonId: LessonId; data: BranchNodeViewedData; }) | (TelemetryEventBase & { name: "branch_selected"; lessonId: LessonId; data: BranchSelectedData; }) | (TelemetryEventBase & { name: "image_juxtaposition_changed"; lessonId?: LessonId; data: ImageJuxtapositionChangedData; }) | (TelemetryEventBase & { name: "timeline_event_viewed"; lessonId?: LessonId; data: TimelineEventViewedData; }) | (TelemetryEventBase & { name: "image_sequence_changed"; lessonId?: LessonId; data: ImageSequenceChangedData; }) | (TelemetryEventBase & { name: "audio_recording_started"; lessonId?: LessonId; data: AudioRecordingData; }) | (TelemetryEventBase & { name: "audio_recording_completed"; lessonId?: LessonId; data: AudioRecordingData; }) | (TelemetryEventBase & { name: "qr_content_revealed"; lessonId?: LessonId; data: QrContentRevealedData; }) | (TelemetryEventBase & { name: "advent_door_opened"; lessonId?: LessonId; data: AdventDoorOpenedData; }) | (TelemetryEventBase & { name: "map_stage_viewed"; lessonId: LessonId; data: MapStageViewedData; }) | (TelemetryEventBase & { name: "map_exit_selected"; lessonId: LessonId; data: MapExitSelectedData; }); /** Payload shape for a telemetry event name. */ type TelemetryDataFor = Extract extends { data?: infer D; } ? D : never; type TelemetrySink = (event: TelemetryEvent) => void | Promise; type TelemetryBatchSink = (events: TelemetryEvent[]) => void | Promise; type TrackingClient = { /** Returns false when the event was dropped (e.g. buffer cap or after dispose). */ track: (event: TelemetryEvent) => boolean; /** Delivers one event and resolves to true only when the sink accepted it (batch: includes flush). */ deliver?: (event: TelemetryEvent) => Promise; /** Resolves to true when all buffered events were delivered; false when a sink failure re-queued events. */ flush?: () => void | Promise; /** Best-effort synchronous flush for pagehide (keepalive batch sink when configured). */ flushOnExit?: () => void; dispose?: () => void | Promise; }; type StoragePort = { getItem: (key: string) => string | null; /** Returns false when the value could not be durably persisted (e.g. sessionStorage quota). */ setItem: (key: string, value: string) => boolean; removeItem?: (key: string) => void; /** @internal Test helper to clear in-memory fallback state. */ resetForTests?: () => void; }; type ClockPort = { nowMs: () => number; nowIso: () => string; }; type TimerPort = { setInterval: (fn: () => void, ms: number) => ReturnType; clearInterval: (id: ReturnType) => void; }; declare function createDefaultClock(): ClockPort; declare function createNoopStorage(): StoragePort; declare function resetStoragePortForTests(storage: StoragePort): void; declare function createSessionStoragePort(): StoragePort; declare function createGlobalTimer(): TimerPort; type BuildTelemetryEventContext = { courseId: CourseId; sessionId?: string; attemptId?: string; user?: TelemetryUser; timestamp?: string; }; type BuildTelemetryEventInput = (BuildTelemetryEventContext & { name: "course_started"; lessonId?: LessonId; data?: undefined; }) | (BuildTelemetryEventContext & { name: "course_completed"; lessonId?: LessonId; data?: undefined; }) | (BuildTelemetryEventContext & { name: "lesson_started"; lessonId?: LessonId; data?: LessonLifecycleData; }) | (BuildTelemetryEventContext & { name: "lesson_completed"; lessonId?: LessonId; data?: LessonLifecycleData; }) | (BuildTelemetryEventContext & { name: "lesson_time_on_task"; lessonId?: LessonId; data?: LessonLifecycleData; }) | (BuildTelemetryEventContext & { name: "quiz_answered"; lessonId?: LessonId; data: QuizAnsweredData; }) | (BuildTelemetryEventContext & { name: "quiz_completed"; lessonId?: LessonId; data: QuizCompletedData; }) | (BuildTelemetryEventContext & { name: "assessment_answered"; lessonId?: LessonId; data: AssessmentAnsweredData; }) | (BuildTelemetryEventContext & { name: "assessment_completed"; lessonId?: LessonId; data: AssessmentCompletedData; }) | (BuildTelemetryEventContext & { name: "interaction"; lessonId?: LessonId; data?: InteractionData; }) | (BuildTelemetryEventContext & { name: "book_page_viewed"; lessonId?: LessonId; data: BookPageViewedData; }) | (BuildTelemetryEventContext & { name: "slide_viewed"; lessonId?: LessonId; data: SlideViewedData; }) | (BuildTelemetryEventContext & { name: "compound_page_viewed"; lessonId?: LessonId; data: CompoundPageViewedData; }) | (BuildTelemetryEventContext & { name: "hotspot_opened"; lessonId?: LessonId; data: HotspotOpenedData; }) | (BuildTelemetryEventContext & { name: "accordion_section_toggled"; lessonId?: LessonId; data: AccordionSectionToggledData; }) | (BuildTelemetryEventContext & { name: "flashcard_flipped"; lessonId?: LessonId; data: FlashcardFlippedData; }) | (BuildTelemetryEventContext & { name: "image_slider_changed"; lessonId?: LessonId; data: ImageSliderChangedData; }) | (BuildTelemetryEventContext & { name: "video_cue_reached"; lessonId?: LessonId; data: VideoCueReachedData; }) | (BuildTelemetryEventContext & { name: "video_segment_completed"; lessonId?: LessonId; data: VideoSegmentCompletedData; }) | (BuildTelemetryEventContext & { name: "memory_card_flipped"; lessonId?: LessonId; data: MemoryCardFlippedData; }) | (BuildTelemetryEventContext & { name: "information_wall_search"; lessonId?: LessonId; data: InformationWallSearchData; }) | (BuildTelemetryEventContext & { name: "parallax_slide_viewed"; lessonId?: LessonId; data: ParallaxSlideViewedData; }) | (BuildTelemetryEventContext & { name: "questionnaire_submitted"; lessonId?: LessonId; data: QuestionnaireSubmittedData; }) | (BuildTelemetryEventContext & { name: "branch_node_viewed"; lessonId?: LessonId; data: BranchNodeViewedData; }) | (BuildTelemetryEventContext & { name: "branch_selected"; lessonId?: LessonId; data: BranchSelectedData; }) | (BuildTelemetryEventContext & { name: "image_juxtaposition_changed"; lessonId?: LessonId; data: ImageJuxtapositionChangedData; }) | (BuildTelemetryEventContext & { name: "timeline_event_viewed"; lessonId?: LessonId; data: TimelineEventViewedData; }) | (BuildTelemetryEventContext & { name: "image_sequence_changed"; lessonId?: LessonId; data: ImageSequenceChangedData; }) | (BuildTelemetryEventContext & { name: "audio_recording_started"; lessonId?: LessonId; data: AudioRecordingData; }) | (BuildTelemetryEventContext & { name: "audio_recording_completed"; lessonId?: LessonId; data: AudioRecordingData; }) | (BuildTelemetryEventContext & { name: "qr_content_revealed"; lessonId?: LessonId; data: QrContentRevealedData; }) | (BuildTelemetryEventContext & { name: "advent_door_opened"; lessonId?: LessonId; data: AdventDoorOpenedData; }) | (BuildTelemetryEventContext & { name: "map_stage_viewed"; lessonId?: LessonId; data: MapStageViewedData; }) | (BuildTelemetryEventContext & { name: "map_exit_selected"; lessonId?: LessonId; data: MapExitSelectedData; }); /** Reset dev-warning state (tests only). */ declare function resetTelemetryBuilderWarningsForTests(): void; /** * Build a typed telemetry event from a catalog event name and context. * Validates lesson-scoped events require `lessonId`. * * @example * ```ts * import { buildTelemetryEvent } from "@lessonkit/core"; * * const event = buildTelemetryEvent({ * name: "lesson_completed", * courseId: "sec-101", * lessonId: "phishing-101", * sessionId: "tab-abc", * }); * ``` */ declare function buildTelemetryEvent(opts: BuildTelemetryEventInput): TelemetryEvent; /** * Like `buildTelemetryEvent`, but returns null when lesson-scoped events lack `lessonId` * (with dev warnings for quiz/assessment events). */ declare function tryBuildTelemetryEvent(opts: BuildTelemetryEventInput): TelemetryEvent | null; type ProgressState = { activeLessonId?: LessonId; completedLessonIds: ReadonlySet; courseCompleted: boolean; }; type ProgressController = { getState: () => ProgressState; setActiveLesson: (lessonId: LessonId, startedAtMs: number) => { previousLessonId?: LessonId; }; completeLesson: (lessonId: LessonId, completedAtMs: number) => { durationMs?: number; didComplete: boolean; }; completeCourse: () => { didComplete: boolean; }; }; declare function createProgressController(): ProgressController; declare const SESSION_STORAGE_KEY = "lessonkit:sessionId"; type InvalidSessionIdContext = { /** The invalid id that was rejected. */ invalidId: string; /** Id actually used after fallback. */ fallbackId: string; /** Whether the invalid id came from config or from stored tab state. */ source: "provided" | "stored"; }; type ResolveSessionIdOptions = { /** Invoked when an invalid session id is replaced by a tab or generated id. */ onInvalidSessionId?: (ctx: InvalidSessionIdContext) => void; }; declare function getTabSessionId(storage: StoragePort): string | null; declare function resolveSessionId(storage: StoragePort, provided?: string, options?: ResolveSessionIdOptions): string; declare function hasCourseStarted(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function markCourseStarted(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function hasCourseStartedEmittedToTracking(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function markCourseStartedEmittedToTracking(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function hasCourseStartedPipelineDelivered(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function markCourseStartedPipelineDelivered(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function hasCourseStartedXapiSent(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; declare function markCourseStartedXapiSent(storage: StoragePort, sessionId: string, courseId?: CourseId): boolean; /** @internal Reset volatile session ids between tests. */ declare function resetSharedVolatileSessionIdForTests(): void; declare function migrateCourseStartedMark(storage: StoragePort, fromSessionId: string, toSessionId: string, courseId?: CourseId): void; /** Plugin category — aligns with roadmap extension areas. */ type LessonkitPluginKind = "analytics" | "lms" | "assessment" | "interaction" | "ai"; type LessonkitPluginContext = { courseId: CourseId; sessionId?: string; attemptId?: string; user?: TelemetryUser; }; type AssessmentScoreInput = { checkId: CheckId; lessonId?: LessonId; response: unknown; }; type AssessmentScoreResult = { score: number; maxScore?: number; passed?: boolean; feedback?: string; }; /** Metadata for custom interaction blocks (renderer wiring stays in app code until 1.0). */ type InteractionBlockRegistration = { blockType: string; catalogVersion?: string; description?: string; }; type PluginIdentity = { id: string; version: string; kind: LessonkitPluginKind; name?: string; }; /** Narrow telemetry plugin contract (ISP). */ type TelemetryPlugin = PluginIdentity & { onTelemetry?: (event: TelemetryEvent, ctx: LessonkitPluginContext) => TelemetryEvent | null; onTelemetryBatch?: (events: TelemetryEvent[], ctx: LessonkitPluginContext) => void; wrapTrackingSink?: (sink: TelemetrySink, ctx: LessonkitPluginContext) => TelemetrySink; }; /** Narrow lifecycle plugin contract (ISP). */ type LifecyclePlugin = PluginIdentity & { setup?: (ctx: LessonkitPluginContext) => void; dispose?: () => void; }; /** Narrow assessment plugin contract (ISP). */ type AssessmentPlugin = PluginIdentity & { kind: "assessment"; scoreAssessment?: (input: AssessmentScoreInput, ctx: LessonkitPluginContext) => AssessmentScoreResult | null; }; /** * Narrow interaction metadata plugin (ISP). * @experimental Not wired into PluginHost; reserved for a future release. */ type InteractionPlugin = PluginIdentity & { interactionBlocks?: InteractionBlockRegistration[]; }; /** * Combined plugin contract (v1). Prefer segregated types for new plugins. * @deprecated Prefer `TelemetryPlugin`, `AssessmentPlugin`, or `LifecyclePlugin` via `define*Plugin`. */ type LessonkitPlugin = PluginIdentity & Partial & Pick & Pick & Pick>; type PluginHost = { readonly plugins: readonly LessonkitPlugin[]; setupAll: (ctx: LessonkitPluginContext) => void; disposeAll: () => void; runTelemetry: (event: TelemetryEvent, ctx: LessonkitPluginContext) => TelemetryEvent | null; runTelemetryBatch: (events: TelemetryEvent[], ctx: LessonkitPluginContext) => TelemetryEvent[]; deliverTelemetryBatch: (events: TelemetryEvent[], ctx: LessonkitPluginContext) => TelemetryEvent[]; composeTrackingSink: (sink: TelemetrySink | undefined, ctx: LessonkitPluginContext | (() => LessonkitPluginContext)) => TelemetrySink | undefined; scoreAssessment: (input: AssessmentScoreInput, ctx: LessonkitPluginContext) => AssessmentScoreResult | null; }; /** Segregated plugin registry (ISP + SRP). */ type PluginRegistry = PluginHost; /** @internal Reset in-flight course_started guard between tests. */ declare function resetCourseStartedEmitFlightForTests(): void; type CourseLifecycleContext = { courseId: CourseId; sessionId: string; attemptId?: string; user?: TelemetryUser; storage: StoragePort; pluginHost: PluginRegistry | null; lxpackBridge: "auto" | "off"; }; type CourseLifecycleDeps = { emitCourseStartedEvent: (ctx: CourseLifecycleContext) => boolean; }; /** * Emit `course_started` once per tab session when tracking/xAPI are active. * Coalesces concurrent calls via an in-flight guard. */ declare function tryEmitCourseStarted(ctx: CourseLifecycleContext, deps: CourseLifecycleDeps, alreadyEmittedToSink: boolean): Promise<{ emitted: boolean; marked: boolean; }>; declare function buildCourseStartedTelemetryEvent(ctx: CourseLifecycleContext): TelemetryEvent; type LessonCompletionEmitter = (lessonId: LessonId, durationMs?: number) => void; /** * Mark a lesson complete in progress state and emit `lesson_completed` when newly completed. * * @example * ```ts * completeLessonWithTelemetry({ * progress, * lessonId: "lesson-1", * nowMs: Date.now(), * emitLessonCompleted: (id, durationMs) => track("lesson_completed", { lessonId: id, durationMs }), * }); * ``` */ declare function completeLessonWithTelemetry(opts: { progress: ProgressController; lessonId: LessonId; nowMs: number; emitLessonCompleted: LessonCompletionEmitter; }): boolean; /** * Complete the active lesson (if any), then mark the course complete and emit `course_completed`. * * @example * ```ts * completeCourseWithTelemetry({ * progress, * nowMs: Date.now(), * emitLessonCompleted: (id) => track("lesson_completed", { lessonId: id }), * emitCourseCompleted: () => track("course_completed", {}), * }); * ``` */ declare function completeCourseWithTelemetry(opts: { progress: ProgressController; nowMs: number; emitLessonCompleted: LessonCompletionEmitter; emitCourseCompleted: () => void; }): boolean; export { type InteractionPlugin as $, type AssessmentResumeState as A, type BlockId as B, type CourseId as C, type AssessmentInteractionType as D, type AssessmentXAPIData as E, type BookPageViewedData as F, type BranchNodeViewedData as G, type BranchSelectedData as H, type IdentityIdPath as I, type BuildTelemetryEventInput as J, type CompoundPageViewedData as K, type LessonId as L, type McqAssessmentProps as M, type CourseLifecycleContext as N, type CourseLifecycleDeps as O, type PluginRegistry as P, type FlashcardFlippedData as Q, type HotspotOpenedData as R, type StoragePort as S, type TelemetryEventName as T, ID_MAX_LENGTH as U, ID_PATTERN as V, type IdentityValidationIssue as W, type ImageSliderChangedData as X, type InformationWallSearchData as Y, type InteractionBlockRegistration as Z, type InteractionData as _, type CheckId as a, type InvalidSessionIdContext as a0, type LessonCompletionEmitter as a1, type LessonLifecycleData as a2, type LessonkitPluginKind as a3, type MemoryCardFlippedData as a4, type ParallaxSlideViewedData as a5, type PluginIdentity as a6, type QuestionnaireSubmittedData as a7, type QuizAnsweredData as a8, type QuizCompletedData as a9, resetSharedVolatileSessionIdForTests as aA, resetStoragePortForTests as aB, resetTelemetryBuilderWarningsForTests as aC, resolveSessionId as aD, tryBuildTelemetryEvent as aE, tryEmitCourseStarted as aF, resetCourseStartedEmitFlightForTests as aG, type ResolveSessionIdOptions as aa, SESSION_STORAGE_KEY as ab, type SlideViewedData as ac, type TelemetryEventBase as ad, type TimerPort as ae, type VideoCueReachedData as af, type VideoSegmentCompletedData as ag, buildCourseStartedTelemetryEvent as ah, buildTelemetryEvent as ai, completeCourseWithTelemetry as aj, completeLessonWithTelemetry as ak, createDefaultClock as al, createGlobalTimer as am, createNoopStorage as an, createProgressController as ao, createSessionStoragePort as ap, getTabSessionId as aq, hasCourseStarted as ar, hasCourseStartedEmittedToTracking as as, hasCourseStartedPipelineDelivered as at, hasCourseStartedXapiSent as au, markCourseStarted as av, markCourseStartedEmittedToTracking as aw, markCourseStartedPipelineDelivered as ax, markCourseStartedXapiSent as ay, migrateCourseStartedMark as az, type IdentityValidationResult as b, type LessonkitUrn as c, type TelemetrySink as d, type TelemetryBatchSink as e, type TrackingClient as f, type TelemetryEvent as g, type TelemetryUser as h, type LessonkitPlugin as i, type ProgressController as j, type PluginHost as k, type ProgressState as l, type TelemetryDataFor as m, type AssessmentScoreInput as n, type AssessmentScoreResult as o, type ClockPort as p, type AssessmentPlugin as q, type LifecyclePlugin as r, type TelemetryPlugin as s, type LessonkitPluginContext as t, type AccordionSectionToggledData as u, type AssessmentAnsweredData as v, type AssessmentBaseProps as w, type AssessmentBehaviour as x, type AssessmentCompletedData as y, type AssessmentHandle as z };