File tree Expand file tree Collapse file tree 3 files changed +54
-32
lines changed
cli/src/components/ask-user Expand file tree Collapse file tree 3 files changed +54
-32
lines changed Original file line number Diff line number Diff line change @@ -69,8 +69,28 @@ export interface AskUserParams {
6969 questions : {
7070 /** The question to ask the user */
7171 question : string
72- /** Array of answer options for the question (minimum 2) */
73- options : string [ ]
72+ /** Short label (max 12 chars) displayed as a chip/tag */
73+ header ?: string
74+ /** Array of answer options with label and optional description (minimum 2) */
75+ options : {
76+ /** The display text for this option */
77+ label : string
78+ /** Explanation shown when option is focused */
79+ description ?: string
80+ } [ ]
81+ /** If true, allows selecting multiple options (checkbox). If false, single selection only (radio). */
82+ multiSelect ?: boolean
83+ /** Validation rules for "Other" text input */
84+ validation ?: {
85+ /** Maximum length for "Other" text input */
86+ maxLength ?: number
87+ /** Minimum length for "Other" text input */
88+ minLength ?: number
89+ /** Regex pattern for "Other" text input */
90+ pattern ?: string
91+ /** Custom error message when pattern fails */
92+ patternError ?: string
93+ }
7494 } [ ]
7595}
7696
Original file line number Diff line number Diff line change 33 * Integrates with @opentui/react useKeyboard and focus manager
44 */
55
6- import { useCallback } from 'react'
6+ import { useCallback , useRef , useEffect } from 'react'
77import { useKeyboard } from '@opentui/react'
88import type { FocusTarget , AskUserQuestion } from '../types'
99import { isFocusOnOption , isFocusOnTextInput , isFocusOnConfirmSubmit } from '../types'
@@ -63,9 +63,36 @@ export function useKeyboardNavigation(params: KeyboardNavigationParams) {
6363 onGoBackFromConfirm,
6464 } = params
6565
66+ // Use refs for frequently changing values to avoid recreating the keyboard callback
67+ const paramsRef = useRef ( params )
68+ useEffect ( ( ) => {
69+ paramsRef . current = params
70+ } )
71+
6672 useKeyboard (
6773 useCallback (
6874 ( key ) => {
75+ // Get current values from ref to avoid stale closures
76+ const {
77+ focus,
78+ dispatchFocus,
79+ currentQuestionIndex,
80+ totalQuestions,
81+ isFirstQuestion,
82+ isLastQuestion,
83+ isOnConfirmScreen,
84+ otherTexts,
85+ onSelectAnswer,
86+ onOtherTextChange,
87+ onChangeQuestion,
88+ onSubmit,
89+ onAutoAdvance,
90+ onTextInputAdvance,
91+ onForceSubmit,
92+ onGoToConfirm,
93+ onGoBackFromConfirm,
94+ } = paramsRef . current
95+
6996 // Helper to prevent default behavior
7097 const preventDefault = ( ) => {
7198 if ( 'preventDefault' in key && typeof key . preventDefault === 'function' ) {
@@ -236,27 +263,7 @@ export function useKeyboardNavigation(params: KeyboardNavigationParams) {
236263 }
237264 }
238265 } ,
239- [
240- focus ,
241- dispatchFocus ,
242- currentQuestionIndex ,
243- totalQuestions ,
244- currentQuestion ,
245- isFirstQuestion ,
246- isLastQuestion ,
247- isOnConfirmScreen ,
248- allAnswered ,
249- otherTexts ,
250- onSelectAnswer ,
251- onOtherTextChange ,
252- onChangeQuestion ,
253- onSubmit ,
254- onAutoAdvance ,
255- onTextInputAdvance ,
256- onForceSubmit ,
257- onGoToConfirm ,
258- onGoBackFromConfirm ,
259- ]
266+ [ ] // Empty deps - callback is stable, values accessed via ref
260267 )
261268 )
262269}
Original file line number Diff line number Diff line change @@ -23,27 +23,22 @@ export interface QuestionValidation {
2323
2424/**
2525 * Validate "Other" text input against rules
26- * Phase 1: Basic length check only
27- * Phase 3: Full validation with regex, custom errors
26+ * Supports max/min length, regex patterns, and custom error messages
2827 */
2928export function validateOtherText (
3029 text : string ,
3130 validation ?: QuestionValidation ,
3231 maxLength : number = 500
3332) : ValidationResult {
34- // Phase 1: Simple max length check
33+ // Default max length check
3534 if ( text . length > maxLength ) {
3635 return {
3736 isValid : false ,
3837 error : `Max ${ maxLength } characters` ,
3938 }
4039 }
4140
42- // Phase 3 will add:
43- // - minLength check
44- // - pattern (regex) validation
45- // - custom error messages
46-
41+ // Validation rules (if provided)
4742 if ( validation ) {
4843 if ( validation . maxLength && text . length > validation . maxLength ) {
4944 return {
You can’t perform that action at this time.
0 commit comments