Skip to content

Core API Reference

The @survey-kit/core package provides the survey engine: renderers, state management and types.

Installation

npm install @survey-kit/core

Hooks

useSurvey

Main hook for managing survey state and navigation. Internally organised as a directory module with co-located helper files for testability and clarity.

import { useSurvey } from '@survey-kit/core'

const survey = useSurvey({ config, onSubmit })

Parameters:

Param Type Description
config SurveyConfig Survey configuration object
onSubmit (answers) => void Callback when survey is submitted

Returns:

interface UseSurveyReturn {
  // State
  state: SurveyState
  currentPage: SurveyPage | undefined
  currentQuestion: SurveyQuestion | null
  currentStage: SurveyStage | null
  currentGroup: SurveyGroup | null

  // Navigation flags
  isFirstPage: boolean
  isLastPage: boolean

  // Progress (percentage values 0–100)
  progress: number // within current group
  stageProgress: number // across visible stages
  groupProgress: number // within current stage
  overallProgress: number // across all visible pages

  // Navigation methods
  nextPage: () => void
  prevPage: () => void
  goToStage: (stageId: string) => void
  submitSurvey: () => Promise<void>

  // Answer management
  setAnswer: (questionId: string, value: unknown) => void
  getAnswerValue: (questionId: string) => unknown
  validateQuestion: (question: SurveyQuestion) => string[]

  // Completion checks
  isPageComplete: (pageId: string) => boolean
  isGroupComplete: (groupId: string) => boolean
  isStageComplete: (stageId: string) => boolean
  getPageCompletionStatus: (pageId: string) => PageCompletionStatus

  // Visibility helpers
  getLatestAccessiblePageIndex: () => number
  getVisiblePages: () => SurveyPage[]
  getVisibleQuestions: (page: SurveyPage) => SurveyQuestion[]
  getVisibleStages: () => SurveyStage[]
  getVisibleGroups: (stage: SurveyStage) => SurveyGroup[]

  // Access control
  canNavigateToStage: (stageId: string) => boolean
  canNavigateToGroup: (groupId: string) => boolean

  // Per-entity progress (completion-based)
  getStageProgress: (stageId: string) => number
  getGroupProgress: (groupId: string) => number
}

Hook Architecture

The useSurvey hook follows a directory module pattern. The main entry point (index.ts) contains only React orchestration — useState, useEffect, useMemo, and useCallback calls. All pure logic is delegated to co-located helper files:

hooks/useSurvey/
├── index.ts          # Orchestration — wires React primitives to helpers
├── state.ts          # Initial state, localStorage persistence, URL sync
├── visibility.ts     # Conditional filtering of stages/groups/pages/questions
├── navigation.ts     # Next-page resolution, skip logic, access checks
├── completion.ts     # Page/group/stage completeness checks
└── progress.ts       # Position-based and completion-based progress
Module Responsibility
state.ts getInitialState, saveToStorage, updateUrlWithPage, event dispatching, flattenAnswers
visibility.ts getVisibleStages, getVisibleGroupsForStage, getVisiblePagesForGroup, getVisibleQuestionsForPage, getAllVisiblePages
navigation.ts resolveNextPage, resolveGoToStagePageIndex, checkCanNavigateToStage, checkCanNavigateToGroup, computeLatestAccessiblePageIndex
completion.ts checkPageComplete, checkGroupComplete, checkStageComplete, computePageCompletionStatus
progress.ts calculatePageProgress, calculateGroupProgress, calculateStageProgress, calculateOverallProgress, getStageProgressByCompletion, getGroupProgressByCompletion

Every helper is a pure function (no React dependency) that can be unit-tested in isolation. The hook simply pipes state and derived values through these helpers.


Components

SurveyRenderer

Form-based survey renderer displaying one page at a time.

import { SurveyRenderer } from '@survey-kit/core'
;<SurveyRenderer
  config={surveyConfig}
  components={components}
  onSubmit={handleSubmit}
  layout="default"
/>

Props:

Prop Type Required Description
config SurveyConfig Yes Survey configuration
components object Yes UI components from registry
onSubmit (answers) => void Yes Submission callback
layout string No Layout variant

ChatSurveyRenderer

Chat-style survey renderer with messaging UI. The renderer does not call your API by itself: implement onSubmit the same way as for SurveyRenderer (e.g. persist answers to your backend).

import { ChatSurveyRenderer } from '@survey-kit/core'
;<ChatSurveyRenderer
  config={surveyConfig}
  components={chatComponents}
  onSubmit={handleSubmit}
  typingDelay={{ min: 500, max: 1000 }}
/>

Props:

Prop Type Required Description
config SurveyConfig Yes Survey configuration
components object Yes Chat UI components
onSubmit (answers) => void Yes Submission handler—your code persists answers (no built-in network request)
typingDelay { min, max } No Typing indicator delay (ms)

LayoutRenderer

Wraps SurveyRenderer with header, sidebar and footer.

import { LayoutRenderer, SurveyRenderer } from '@survey-kit/core'
;<LayoutRenderer
  layoutConfig={layoutConfig}
  surveyConfig={surveyConfig}
  components={components}
  onAction={handleAction}
>
  <SurveyRenderer
    config={surveyConfig}
    components={components}
    onSubmit={handleSubmit}
  />
</LayoutRenderer>

DashboardRenderer

Renderer for administrative dashboards, supporting various chart types. When config.surveyFilter is set, pass SimpleDropdown in components and wire surveyFilterValue / onSurveyFilterChange; the survey scope control appears only if both surveyFilter and onSurveyFilterChange are provided.

import { DashboardRenderer } from '@survey-kit/core'
import {
  TrendLineChart,
  DropoffBarChart,
  Card,
  Heading,
  SimpleDropdown,
} from '@survey-kit/registry'

const components = {
  TrendLineChart,
  DropoffBarChart,
  Card,
  Heading,
  SimpleDropdown,
}

;<DashboardRenderer
  config={dashboardConfig}
  data={analyticsData}
  components={components}
  surveyFilterValue={selectedSurveyId}
  onSurveyFilterChange={setSelectedSurveyId}
/>

Props:

Prop Type Required Description
config DashboardConfig Yes Dashboard layout configuration
data Record<string, any> Yes Analytics data to display
components object Yes Chart components from registry (include SimpleDropdown when using config.surveyFilter)
surveyFilterValue string No Current survey scope; matches surveyFilter.options[].value (often '' for all surveys)
onSurveyFilterChange (value: string) => void No Called when the scope changes; omit with surveyFilter if you do not want the control rendered

Types

SurveyConfig

Top-level survey configuration.

interface SurveyConfig {
  id: string
  title: string
  description?: string
  stages: SurveyStage[]
  navigation?: NavigationConfig
  progress?: ProgressConfig
}

SurveyStage

Top-level section of a survey.

interface SurveyStage {
  id: string
  title: string
  description?: string
  icon?: string
  groups: SurveyGroup[]
  conditional?: ConditionalLogic
}

SurveyGroup

Organises pages within a stage.

interface SurveyGroup {
  id: string
  title: string
  description?: string
  pages: SurveyPage[]
  conditional?: ConditionalLogic
}

SurveyPage

Container for questions (one page = one screen).

interface SurveyPage {
  id: string
  title?: string
  description?: string
  questions: SurveyQuestion[]
  conditional?: ConditionalLogic
  nextPageId?: string
}

SurveyQuestion

Individual form field.

interface SurveyQuestion {
  id: string
  type: QuestionType
  label: string
  description?: string
  placeholder?: string
  required?: boolean
  requiredToNavigate?: boolean
  options?: QuestionOption[]
  validation?: ValidationRule[]
  conditional?: ConditionalLogic
  emojiSlider?: EmojiSliderConfig
}

QuestionType

type QuestionType =
  | 'text'
  | 'textarea'
  | 'email'
  | 'number'
  | 'date'
  | 'select'
  | 'radio'
  | 'checkbox'
  | 'emoji-slider'

DashboardConfig

Configuration for the administrative dashboard.

interface DashboardConfig {
  id: string
  title: string
  allowedRoles: string[]
  groups: DashboardGroup[]
  filters?: DashboardFilterConfig[]
  surveyFilter?: DashboardSurveyFilterConfig
}

Use an option with value: '' when you want an “all surveys” scope (the template omits surveyId on the analytics request for that case).

DashboardSurveyFilterOption

interface DashboardSurveyFilterOption {
  value: string
  label: string
}

DashboardSurveyFilterConfig

interface DashboardSurveyFilterConfig {
  label: string
  options: DashboardSurveyFilterOption[]
}

DashboardFilter

Represents an active filter applied to the dashboard.

interface DashboardFilter {
  questionId: string
  value: string | string[]
}

DashboardFilterConfig

Configuration for a filterable dimension on the dashboard.

interface DashboardFilterConfig {
  id: string
  label: string
  type: 'select' | 'multiselect'
  options: { label: string; value: string }[]
}

Utilities

Conditional Logic

import {
  shouldShowQuestion,
  shouldShowPage,
  shouldShowGroup,
  shouldShowStage,
  evaluateConditions,
} from '@survey-kit/core'

// Check if a question should be visible
const visible = shouldShowQuestion(question, answers)

Configuration Helpers

import {
  normaliseSurveyConfig,
  getAllPages,
  findPageById,
  getPageLocation,
} from '@survey-kit/core'

// Get all pages from a config
const pages = getAllPages(config)

// Extract filterable questions from a survey config
const filters = extractFilterableQuestions(surveyConfig)