1- import { WebCellProps , VNodeChildElement , VNode , createCell } from 'web-cell' ;
2- import type { HTMLContainerProps } from 'web-utility' ;
3- import { uniqueID } from 'web-utility/source/data' ;
1+ import { VNode , VNodeChildElement , WebCellProps , createCell } from 'web-cell' ;
2+ import { HTMLContainerProps , uniqueID } from 'web-utility' ;
43import classNames from 'classnames' ;
54
65import { isButton } from './Button' ;
76import { DropMenu } from '../Navigator/DropMenu' ;
8- import { isField } from './Field ' ;
7+ import { isToggleField } from './ToggleField ' ;
98import { ValidMessage , ValidableFieldProps } from './Form' ;
109
11- export interface GroupLabelProps extends WebCellProps {
12- htmlFor ?: string ;
13- type : 'prepend' | 'append' ;
14- list : VNodeChildElement [ ] ;
15- }
16-
17- export function GroupLabel ( {
18- className,
19- type,
20- list,
21- id = uniqueID ( ) ,
22- htmlFor
23- } : GroupLabelProps ) {
24- return (
25- < div className = { classNames ( `input-group-${ type } ` , className ) } >
26- { list . map ( ( item , index ) => {
27- const ID = `${ id } -${ type } -${ index } ` ;
28-
29- if ( isButton ( item as VNode ) || DropMenu . is ( item as VNode ) ) {
30- ( item as VNode ) . data . props . id = ID ;
31-
32- return item ;
33- }
34-
35- return typeof item !== 'object' ? (
36- < label
37- className = "input-group-text"
38- id = { ID }
39- htmlFor = { htmlFor }
40- >
41- { item }
42- </ label >
43- ) : (
44- < div className = "input-group-text" id = { ID } >
45- { item }
46- </ div >
47- ) ;
48- } ) }
49- </ div >
50- ) ;
51- }
52-
5310export interface InputGroupProps
5411 extends WebCellProps ,
5512 HTMLContainerProps ,
5613 ValidableFieldProps {
5714 size ?: 'sm' | 'lg' ;
5815}
5916
17+ function toLabelNode ( node : VNodeChildElement ) {
18+ if ( isToggleField ( node ) )
19+ node . data . class = {
20+ ...node . data . class ,
21+ 'input-group-text' : true
22+ } ;
23+ else if (
24+ typeof node === 'string' ||
25+ typeof node === 'number' ||
26+ ! (
27+ / ^ ( i n p u t | t e x t a r e a | s e l e c t | l a b e l ) / . test ( ( node as VNode ) . sel ) ||
28+ isButton ( node ) ||
29+ DropMenu . is ( node )
30+ )
31+ )
32+ node = < label className = "input-group-text" > { node } </ label > ;
33+
34+ return node as VNode ;
35+ }
36+
6037export function InputGroup ( {
6138 className,
6239 id = uniqueID ( ) ,
@@ -67,37 +44,31 @@ export function InputGroup({
6744 invalidMessage,
6845 ...rest
6946} : InputGroupProps ) {
70- var field_id = `${ id } -field-0` ;
71-
72- const [ fields , prepends , appends ] = (
73- defaultSlot as VNodeChildElement [ ]
74- ) . reduce (
75- ( [ fields , prepends , appends ] , node ) => {
76- if ( isField ( node ) ) {
77- fields . push ( node ) ;
47+ var lastID = '' ,
48+ count = 0 ;
7849
79- if ( fields . length === 1 ) {
80- if ( node . data . props ?. id ) field_id = node . data . props . id ;
81- else
82- ( node . data . props = node . data . props || { } ) . id = field_id ;
83- }
84- ( node . data . attrs = node . data . attrs || { } ) [
85- 'aria-describedby'
86- ] = `${ id } -label-${ prepends [ 0 ] ? 'prepend' : 'append' } -0` ;
87- } else if ( fields [ 0 ] ) appends . push ( node ) ;
88- else prepends . push ( node ) ;
50+ const nodes = ( defaultSlot as VNodeChildElement [ ] )
51+ . flat ( Infinity )
52+ . reverse ( )
53+ . map ( node => {
54+ node = toLabelNode ( node ) ;
8955
90- return [ fields , prepends , appends ] ;
91- } ,
92- [ [ ] , [ ] , [ ] ] as [ VNode [ ] , VNodeChildElement [ ] , VNodeChildElement [ ] ]
93- ) ;
94-
95- if ( ! appends [ 0 ] ) {
96- const [ last_field ] = fields . slice ( - 1 ) ;
56+ const [ tag ] = node . sel . split ( / [ ^ \w - ] / ) ;
9757
98- ( last_field . data . class = last_field . data . class || { } ) [ 'rounded-end' ] =
99- true ;
100- }
58+ switch ( tag ) {
59+ case 'input' :
60+ case 'textarea' :
61+ case 'select' :
62+ lastID = ( node . data . props ||= { } ) . id =
63+ node . data . props ?. id || `${ id } -${ count ++ } ` ;
64+ break ;
65+ case 'label' :
66+ if ( node . data . class ?. [ 'input-group-text' ] )
67+ ( node . data . props ||= { } ) . htmlFor = lastID ;
68+ }
69+ return node ;
70+ } )
71+ . reverse ( ) ;
10172
10273 return (
10374 < div
@@ -108,25 +79,7 @@ export function InputGroup({
10879 ) }
10980 { ...{ id, ...rest } }
11081 >
111- { prepends [ 0 ] && (
112- < GroupLabel
113- type = "prepend"
114- id = { `${ id } -label` }
115- htmlFor = { field_id }
116- list = { prepends }
117- />
118- ) }
119- { fields }
120-
121- { appends [ 0 ] && (
122- < GroupLabel
123- className = "rounded-end"
124- type = "append"
125- id = { `${ id } -label` }
126- htmlFor = { field_id }
127- list = { appends }
128- />
129- ) }
82+ { nodes }
13083 < ValidMessage { ...{ validMode, validMessage, invalidMessage } } />
13184 </ div >
13285 ) ;
0 commit comments