@@ -11,6 +11,47 @@ import { useSDK } from "@/context/sdk"
1111
1212const cache = new Map < string , { tab : number ; answers : QuestionAnswer [ ] ; custom : string [ ] ; customOn : boolean [ ] } > ( )
1313
14+ function Mark ( props : { multi : boolean ; picked : boolean ; onClick ?: ( event : MouseEvent ) => void } ) {
15+ return (
16+ < span data-slot = "question-option-check" aria-hidden = "true" onClick = { props . onClick } >
17+ < span data-slot = "question-option-box" data-type = { props . multi ? "checkbox" : "radio" } data-picked = { props . picked } >
18+ < Show when = { props . multi } fallback = { < span data-slot = "question-option-radio-dot" /> } >
19+ < Icon name = "check-small" size = "small" />
20+ </ Show >
21+ </ span >
22+ </ span >
23+ )
24+ }
25+
26+ function Option ( props : {
27+ multi : boolean
28+ picked : boolean
29+ label : string
30+ description ?: string
31+ disabled : boolean
32+ onClick : VoidFunction
33+ } ) {
34+ return (
35+ < button
36+ type = "button"
37+ data-slot = "question-option"
38+ data-picked = { props . picked }
39+ role = { props . multi ? "checkbox" : "radio" }
40+ aria-checked = { props . picked }
41+ disabled = { props . disabled }
42+ onClick = { props . onClick }
43+ >
44+ < Mark multi = { props . multi } picked = { props . picked } />
45+ < span data-slot = "question-option-main" >
46+ < span data-slot = "option-label" > { props . label } </ span >
47+ < Show when = { props . description } >
48+ < span data-slot = "option-description" > { props . description } </ span >
49+ </ Show >
50+ </ span >
51+ </ button >
52+ )
53+ }
54+
1455export const SessionQuestionDock : Component < { request : QuestionRequest ; onSubmit : ( ) => void } > = ( props ) => {
1556 const sdk = useSDK ( )
1657 const language = useLanguage ( )
@@ -41,6 +82,9 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
4182 return language . t ( "session.question.progress" , { current : n , total : total ( ) } )
4283 } )
4384
85+ const customLabel = ( ) => language . t ( "ui.messagePart.option.typeOwnAnswer" )
86+ const customPlaceholder = ( ) => language . t ( "ui.question.custom.placeholder" )
87+
4488 const last = createMemo ( ( ) => store . tab >= total ( ) - 1 )
4589
4690 const customUpdate = ( value : string , selected : boolean = on ( ) ) => {
@@ -164,6 +208,13 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
164208
165209 const submit = ( ) => void reply ( questions ( ) . map ( ( _ , i ) => store . answers [ i ] ?? [ ] ) )
166210
211+ const answered = ( i : number ) => {
212+ if ( ( store . answers [ i ] ?. length ?? 0 ) > 0 ) return true
213+ return store . customOn [ i ] === true && ( store . custom [ i ] ?? "" ) . trim ( ) . length > 0
214+ }
215+
216+ const picked = ( answer : string ) => store . answers [ store . tab ] ?. includes ( answer ) ?? false
217+
167218 const pick = ( answer : string , custom : boolean = false ) => {
168219 setStore ( "answers" , store . tab , [ answer ] )
169220 if ( custom ) setStore ( "custom" , store . tab , answer )
@@ -230,6 +281,24 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
230281 customUpdate ( input ( ) )
231282 }
232283
284+ const resizeInput = ( el : HTMLTextAreaElement ) => {
285+ el . style . height = "0px"
286+ el . style . height = `${ el . scrollHeight } px`
287+ }
288+
289+ const focusCustom = ( el : HTMLTextAreaElement ) => {
290+ setTimeout ( ( ) => {
291+ el . focus ( )
292+ resizeInput ( el )
293+ } , 0 )
294+ }
295+
296+ const toggleCustomMark = ( event : MouseEvent ) => {
297+ event . preventDefault ( )
298+ event . stopPropagation ( )
299+ customToggle ( )
300+ }
301+
233302 const next = ( ) => {
234303 if ( sending ( ) ) return
235304 if ( store . editing ) commitCustom ( )
@@ -270,10 +339,7 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
270339 type = "button"
271340 data-slot = "question-progress-segment"
272341 data-active = { i ( ) === store . tab }
273- data-answered = {
274- ( store . answers [ i ( ) ] ?. length ?? 0 ) > 0 ||
275- ( store . customOn [ i ( ) ] === true && ( store . custom [ i ( ) ] ?? "" ) . trim ( ) . length > 0 )
276- }
342+ data-answered = { answered ( i ( ) ) }
277343 disabled = { sending ( ) }
278344 onClick = { ( ) => jump ( i ( ) ) }
279345 aria-label = { `${ language . t ( "ui.tool.questions" ) } ${ i ( ) + 1 } ` }
@@ -307,43 +373,23 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
307373 </ Show >
308374 < div data-slot = "question-options" >
309375 < For each = { options ( ) } >
310- { ( opt , i ) => {
311- const picked = ( ) => store . answers [ store . tab ] ?. includes ( opt . label ) ?? false
312- return (
313- < button
314- data-slot = "question-option"
315- data-picked = { picked ( ) }
316- role = { multi ( ) ? "checkbox" : "radio" }
317- aria-checked = { picked ( ) }
318- disabled = { sending ( ) }
319- onClick = { ( ) => selectOption ( i ( ) ) }
320- >
321- < span data-slot = "question-option-check" aria-hidden = "true" >
322- < span
323- data-slot = "question-option-box"
324- data-type = { multi ( ) ? "checkbox" : "radio" }
325- data-picked = { picked ( ) }
326- >
327- < Show when = { multi ( ) } fallback = { < span data-slot = "question-option-radio-dot" /> } >
328- < Icon name = "check-small" size = "small" />
329- </ Show >
330- </ span >
331- </ span >
332- < span data-slot = "question-option-main" >
333- < span data-slot = "option-label" > { opt . label } </ span >
334- < Show when = { opt . description } >
335- < span data-slot = "option-description" > { opt . description } </ span >
336- </ Show >
337- </ span >
338- </ button >
339- )
340- } }
376+ { ( opt , i ) => (
377+ < Option
378+ multi = { multi ( ) }
379+ picked = { picked ( opt . label ) }
380+ label = { opt . label }
381+ description = { opt . description }
382+ disabled = { sending ( ) }
383+ onClick = { ( ) => selectOption ( i ( ) ) }
384+ />
385+ ) }
341386 </ For >
342387
343388 < Show
344389 when = { store . editing }
345390 fallback = {
346391 < button
392+ type = "button"
347393 data-slot = "question-option"
348394 data-custom = "true"
349395 data-picked = { on ( ) }
@@ -352,24 +398,10 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
352398 disabled = { sending ( ) }
353399 onClick = { customOpen }
354400 >
355- < span
356- data-slot = "question-option-check"
357- aria-hidden = "true"
358- onClick = { ( e ) => {
359- e . preventDefault ( )
360- e . stopPropagation ( )
361- customToggle ( )
362- } }
363- >
364- < span data-slot = "question-option-box" data-type = { multi ( ) ? "checkbox" : "radio" } data-picked = { on ( ) } >
365- < Show when = { multi ( ) } fallback = { < span data-slot = "question-option-radio-dot" /> } >
366- < Icon name = "check-small" size = "small" />
367- </ Show >
368- </ span >
369- </ span >
401+ < Mark multi = { multi ( ) } picked = { on ( ) } onClick = { toggleCustomMark } />
370402 < span data-slot = "question-option-main" >
371- < span data-slot = "option-label" > { language . t ( "ui.messagePart.option.typeOwnAnswer" ) } </ span >
372- < span data-slot = "option-description" > { input ( ) || language . t ( "ui.question.custom.placeholder" ) } </ span >
403+ < span data-slot = "option-label" > { customLabel ( ) } </ span >
404+ < span data-slot = "option-description" > { input ( ) || customPlaceholder ( ) } </ span >
373405 </ span >
374406 </ button >
375407 }
@@ -394,33 +426,13 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
394426 commitCustom ( )
395427 } }
396428 >
397- < span
398- data-slot = "question-option-check"
399- aria-hidden = "true"
400- onClick = { ( e ) => {
401- e . preventDefault ( )
402- e . stopPropagation ( )
403- customToggle ( )
404- } }
405- >
406- < span data-slot = "question-option-box" data-type = { multi ( ) ? "checkbox" : "radio" } data-picked = { on ( ) } >
407- < Show when = { multi ( ) } fallback = { < span data-slot = "question-option-radio-dot" /> } >
408- < Icon name = "check-small" size = "small" />
409- </ Show >
410- </ span >
411- </ span >
429+ < Mark multi = { multi ( ) } picked = { on ( ) } onClick = { toggleCustomMark } />
412430 < span data-slot = "question-option-main" >
413- < span data-slot = "option-label" > { language . t ( "ui.messagePart.option.typeOwnAnswer" ) } </ span >
431+ < span data-slot = "option-label" > { customLabel ( ) } </ span >
414432 < textarea
415- ref = { ( el ) =>
416- setTimeout ( ( ) => {
417- el . focus ( )
418- el . style . height = "0px"
419- el . style . height = `${ el . scrollHeight } px`
420- } , 0 )
421- }
433+ ref = { focusCustom }
422434 data-slot = "question-custom-input"
423- placeholder = { language . t ( "ui.question.custom.placeholder" ) }
435+ placeholder = { customPlaceholder ( ) }
424436 value = { input ( ) }
425437 rows = { 1 }
426438 disabled = { sending ( ) }
@@ -436,8 +448,7 @@ export const SessionQuestionDock: Component<{ request: QuestionRequest; onSubmit
436448 } }
437449 onInput = { ( e ) => {
438450 customUpdate ( e . currentTarget . value )
439- e . currentTarget . style . height = "0px"
440- e . currentTarget . style . height = `${ e . currentTarget . scrollHeight } px`
451+ resizeInput ( e . currentTarget )
441452 } }
442453 />
443454 </ span >
0 commit comments