@tachui/forms 0.7.1-alpha → 0.8.1-alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -272
- package/dist/DatePicker-D5nRFTUm.js +475 -0
- package/dist/DatePicker-D5nRFTUm.js.map +1 -0
- package/dist/Select-yZyKooXk.js +945 -0
- package/dist/Select-yZyKooXk.js.map +1 -0
- package/dist/Slider-0-oal5YR.js +644 -0
- package/dist/Slider-0-oal5YR.js.map +1 -0
- package/dist/TextField-hX15dY3U.js +509 -0
- package/dist/TextField-hX15dY3U.js.map +1 -0
- package/dist/components/advanced/Slider.d.ts +190 -0
- package/dist/components/advanced/Slider.d.ts.map +1 -0
- package/dist/components/advanced/Stepper.d.ts +161 -0
- package/dist/components/advanced/Stepper.d.ts.map +1 -0
- package/dist/components/advanced/index.d.ts +15 -0
- package/dist/components/advanced/index.d.ts.map +1 -0
- package/dist/components/advanced/index.js +6 -0
- package/dist/components/advanced/index.js.map +1 -0
- package/dist/components/date-picker/DatePicker.d.ts +126 -0
- package/dist/components/date-picker/DatePicker.d.ts.map +1 -0
- package/dist/components/date-picker/index.d.ts +14 -0
- package/dist/components/date-picker/index.d.ts.map +1 -0
- package/dist/components/date-picker/index.js +5 -0
- package/dist/components/date-picker/index.js.map +1 -0
- package/dist/components/form-container/index.d.ts +58 -0
- package/dist/components/form-container/index.d.ts.map +1 -0
- package/dist/components/selection/Checkbox.d.ts.map +1 -0
- package/dist/components/selection/Radio.d.ts.map +1 -0
- package/dist/components/selection/Select.d.ts.map +1 -0
- package/dist/components/selection/index.d.ts +68 -0
- package/dist/components/selection/index.d.ts.map +1 -0
- package/dist/components/selection/index.js +12 -0
- package/dist/components/selection/index.js.map +1 -0
- package/dist/components/text-input/TextField.d.ts.map +1 -0
- package/dist/components/text-input/index.d.ts +8 -0
- package/dist/components/text-input/index.d.ts.map +1 -0
- package/dist/components/text-input/index.js +18 -0
- package/dist/components/text-input/index.js.map +1 -0
- package/dist/{state/index.js → index-D3WfkqVv.js} +15 -8
- package/dist/index-D3WfkqVv.js.map +1 -0
- package/dist/index.d.ts +10 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +198 -376
- package/dist/index.js.map +1 -0
- package/dist/state/index.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/validation/component-validation.d.ts +11 -2
- package/dist/validation/component-validation.d.ts.map +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +282 -191
- package/dist/validation/index.js.map +1 -0
- package/package.json +53 -39
- package/src/components/advanced/Slider.ts +722 -0
- package/src/components/advanced/Stepper.ts +715 -0
- package/src/components/advanced/index.ts +20 -0
- package/src/components/date-picker/DatePicker.ts +925 -0
- package/src/components/date-picker/index.ts +20 -0
- package/src/components/form-container/index.ts +266 -0
- package/src/components/selection/Checkbox.ts +478 -0
- package/src/components/selection/Radio.ts +470 -0
- package/src/components/selection/Select.ts +620 -0
- package/src/components/selection/index.ts +81 -0
- package/src/components/text-input/TextField.ts +728 -0
- package/src/components/text-input/index.ts +35 -0
- package/src/index.ts +48 -0
- package/src/state/index.ts +544 -0
- package/src/types/index.ts +579 -0
- package/src/utils/formatters.ts +184 -0
- package/src/utils/index.ts +57 -0
- package/src/validation/component-validation.ts +429 -0
- package/src/validation/index.ts +641 -0
- package/dist/TextField-CGBM3x7K.js +0 -1799
- package/dist/components/Form.d.ts +0 -76
- package/dist/components/Form.d.ts.map +0 -1
- package/dist/components/index.d.ts +0 -9
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/index.js +0 -28
- package/dist/components/input/Checkbox.d.ts.map +0 -1
- package/dist/components/input/Radio.d.ts.map +0 -1
- package/dist/components/input/Select.d.ts.map +0 -1
- package/dist/components/input/TextField.d.ts.map +0 -1
- package/dist/components/input/index.d.ts +0 -11
- package/dist/components/input/index.d.ts.map +0 -1
- package/dist/utils/validators.d.ts +0 -101
- package/dist/utils/validators.d.ts.map +0 -1
- /package/dist/components/{input → selection}/Checkbox.d.ts +0 -0
- /package/dist/components/{input → selection}/Radio.d.ts +0 -0
- /package/dist/components/{input → selection}/Select.d.ts +0 -0
- /package/dist/components/{input → text-input}/TextField.d.ts +0 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Radio Button Component
|
|
3
|
+
*
|
|
4
|
+
* SwiftUI-inspired radio button with group management,
|
|
5
|
+
* validation, and comprehensive accessibility support.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Component, ComponentInstance } from '@tachui/core'
|
|
9
|
+
import { createEffect, createSignal, h, text } from '@tachui/core'
|
|
10
|
+
import { createField } from '../../state'
|
|
11
|
+
import type { RadioProps } from '../../types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Individual Radio component
|
|
15
|
+
*/
|
|
16
|
+
export const Radio: Component<RadioProps> = props => {
|
|
17
|
+
const {
|
|
18
|
+
name,
|
|
19
|
+
value,
|
|
20
|
+
label,
|
|
21
|
+
checked: controlledChecked,
|
|
22
|
+
groupName,
|
|
23
|
+
disabled = false,
|
|
24
|
+
required = false,
|
|
25
|
+
validation,
|
|
26
|
+
onChange,
|
|
27
|
+
onBlur,
|
|
28
|
+
onFocus,
|
|
29
|
+
error: externalError,
|
|
30
|
+
helperText,
|
|
31
|
+
...restProps
|
|
32
|
+
} = props
|
|
33
|
+
|
|
34
|
+
// Get form context if available
|
|
35
|
+
const formContext = (props as any)._formContext
|
|
36
|
+
|
|
37
|
+
// For radio buttons, we use the group name or the name
|
|
38
|
+
const fieldName = groupName || name
|
|
39
|
+
|
|
40
|
+
// Create field state (shared across radio group)
|
|
41
|
+
const field = createField(
|
|
42
|
+
fieldName,
|
|
43
|
+
controlledChecked ? value : undefined,
|
|
44
|
+
validation
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
// Register field with form if form context exists
|
|
48
|
+
if (formContext) {
|
|
49
|
+
formContext.register(fieldName, validation)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const [focused, setFocused] = createSignal(false)
|
|
53
|
+
|
|
54
|
+
// Determine if this radio is checked
|
|
55
|
+
const isChecked = () => field.value() === value
|
|
56
|
+
|
|
57
|
+
// Handle radio change
|
|
58
|
+
const handleChange = (event: Event) => {
|
|
59
|
+
const target = event.target as HTMLInputElement
|
|
60
|
+
|
|
61
|
+
if (target.checked) {
|
|
62
|
+
field.setValue(value)
|
|
63
|
+
|
|
64
|
+
if (formContext) {
|
|
65
|
+
formContext.setValue(fieldName, value)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (onChange) {
|
|
69
|
+
onChange(fieldName, value, field as any)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Handle focus
|
|
75
|
+
const handleFocus = (_event: Event) => {
|
|
76
|
+
setFocused(true)
|
|
77
|
+
field.onFocus()
|
|
78
|
+
|
|
79
|
+
if (onFocus) {
|
|
80
|
+
onFocus(fieldName, field.value())
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Handle blur
|
|
85
|
+
const handleBlur = (_event: Event) => {
|
|
86
|
+
setFocused(false)
|
|
87
|
+
field.onBlur()
|
|
88
|
+
|
|
89
|
+
if (onBlur) {
|
|
90
|
+
onBlur(fieldName, field.value())
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Determine error message
|
|
95
|
+
const errorMessage =
|
|
96
|
+
externalError || field.error() || formContext?.getError(fieldName)
|
|
97
|
+
|
|
98
|
+
// Handle keyboard interaction
|
|
99
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
100
|
+
// Arrow keys for radio group navigation would be handled at the group level
|
|
101
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
102
|
+
event.preventDefault()
|
|
103
|
+
handleChange(event)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const componentInstance: ComponentInstance = {
|
|
108
|
+
type: 'component',
|
|
109
|
+
id: restProps.id || `radio-${fieldName}-${value}`,
|
|
110
|
+
render: () =>
|
|
111
|
+
h(
|
|
112
|
+
'div',
|
|
113
|
+
{
|
|
114
|
+
...restProps,
|
|
115
|
+
class: `tachui-radio ${restProps.class || ''}`.trim(),
|
|
116
|
+
'data-tachui-radio-container': true,
|
|
117
|
+
'data-field-state': errorMessage
|
|
118
|
+
? 'error'
|
|
119
|
+
: field.validating()
|
|
120
|
+
? 'validating'
|
|
121
|
+
: 'valid',
|
|
122
|
+
'data-checked': isChecked(),
|
|
123
|
+
'data-disabled': disabled,
|
|
124
|
+
},
|
|
125
|
+
// Radio input and label wrapper
|
|
126
|
+
h(
|
|
127
|
+
'label',
|
|
128
|
+
{
|
|
129
|
+
'data-tachui-radio-label': true,
|
|
130
|
+
'data-focused': focused(),
|
|
131
|
+
'data-disabled': disabled,
|
|
132
|
+
},
|
|
133
|
+
// Hidden native radio for accessibility
|
|
134
|
+
h('input', {
|
|
135
|
+
type: 'radio',
|
|
136
|
+
id: restProps.id || `${fieldName}-${value}`,
|
|
137
|
+
name: fieldName,
|
|
138
|
+
value: value,
|
|
139
|
+
checked: isChecked(),
|
|
140
|
+
disabled,
|
|
141
|
+
required,
|
|
142
|
+
onchange: handleChange,
|
|
143
|
+
onfocus: handleFocus,
|
|
144
|
+
onblur: handleBlur,
|
|
145
|
+
onkeydown: handleKeyDown,
|
|
146
|
+
'aria-invalid': !!errorMessage,
|
|
147
|
+
'aria-describedby':
|
|
148
|
+
[
|
|
149
|
+
errorMessage ? `${fieldName}-error` : null,
|
|
150
|
+
helperText ? `${fieldName}-helper` : null,
|
|
151
|
+
]
|
|
152
|
+
.filter(Boolean)
|
|
153
|
+
.join(' ') || undefined,
|
|
154
|
+
'data-tachui-radio-input': true,
|
|
155
|
+
style: {
|
|
156
|
+
position: 'absolute',
|
|
157
|
+
opacity: '0',
|
|
158
|
+
width: '1px',
|
|
159
|
+
height: '1px',
|
|
160
|
+
margin: '-1px',
|
|
161
|
+
padding: '0',
|
|
162
|
+
border: '0',
|
|
163
|
+
clip: 'rect(0,0,0,0)',
|
|
164
|
+
},
|
|
165
|
+
}),
|
|
166
|
+
|
|
167
|
+
// Custom radio visual
|
|
168
|
+
h(
|
|
169
|
+
'div',
|
|
170
|
+
{
|
|
171
|
+
'data-tachui-radio-visual': true,
|
|
172
|
+
'data-checked': isChecked(),
|
|
173
|
+
'data-focused': focused(),
|
|
174
|
+
'data-disabled': disabled,
|
|
175
|
+
'data-error': !!errorMessage,
|
|
176
|
+
'aria-hidden': 'true',
|
|
177
|
+
role: 'presentation',
|
|
178
|
+
},
|
|
179
|
+
// Radio dot indicator
|
|
180
|
+
...(isChecked()
|
|
181
|
+
? [
|
|
182
|
+
h('div', {
|
|
183
|
+
'data-tachui-radio-dot': true,
|
|
184
|
+
}),
|
|
185
|
+
]
|
|
186
|
+
: [])
|
|
187
|
+
),
|
|
188
|
+
|
|
189
|
+
// Label text
|
|
190
|
+
...(label
|
|
191
|
+
? [
|
|
192
|
+
h(
|
|
193
|
+
'span',
|
|
194
|
+
{
|
|
195
|
+
'data-tachui-radio-text': true,
|
|
196
|
+
'data-disabled': disabled,
|
|
197
|
+
},
|
|
198
|
+
text(label),
|
|
199
|
+
...(required
|
|
200
|
+
? [
|
|
201
|
+
h(
|
|
202
|
+
'span',
|
|
203
|
+
{
|
|
204
|
+
'aria-label': 'required',
|
|
205
|
+
'data-required-indicator': true,
|
|
206
|
+
},
|
|
207
|
+
text(' *')
|
|
208
|
+
),
|
|
209
|
+
]
|
|
210
|
+
: [])
|
|
211
|
+
),
|
|
212
|
+
]
|
|
213
|
+
: [])
|
|
214
|
+
)
|
|
215
|
+
),
|
|
216
|
+
props: props,
|
|
217
|
+
cleanup: [
|
|
218
|
+
() => {
|
|
219
|
+
// Only unregister if this is the last radio in the group
|
|
220
|
+
// This would need more sophisticated group management
|
|
221
|
+
// For now, we let the form handle cleanup
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return componentInstance
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* RadioGroup component for managing multiple radio buttons
|
|
231
|
+
*/
|
|
232
|
+
export const RadioGroup: Component<{
|
|
233
|
+
name: string
|
|
234
|
+
label?: string
|
|
235
|
+
options: Array<{
|
|
236
|
+
value: any
|
|
237
|
+
label: string
|
|
238
|
+
disabled?: boolean
|
|
239
|
+
}>
|
|
240
|
+
value?: any
|
|
241
|
+
defaultValue?: any
|
|
242
|
+
onChange?: (name: string, value: any) => void
|
|
243
|
+
validation?: any
|
|
244
|
+
error?: string
|
|
245
|
+
helperText?: string
|
|
246
|
+
disabled?: boolean
|
|
247
|
+
required?: boolean
|
|
248
|
+
direction?: 'horizontal' | 'vertical'
|
|
249
|
+
id?: string
|
|
250
|
+
[key: string]: any
|
|
251
|
+
}> = props => {
|
|
252
|
+
const {
|
|
253
|
+
name,
|
|
254
|
+
label,
|
|
255
|
+
options,
|
|
256
|
+
value: controlledValue,
|
|
257
|
+
defaultValue,
|
|
258
|
+
onChange,
|
|
259
|
+
validation,
|
|
260
|
+
error,
|
|
261
|
+
helperText,
|
|
262
|
+
disabled = false,
|
|
263
|
+
required = false,
|
|
264
|
+
direction = 'vertical',
|
|
265
|
+
...restProps
|
|
266
|
+
} = props
|
|
267
|
+
|
|
268
|
+
// Get form context if available
|
|
269
|
+
const formContext = (props as any)._formContext
|
|
270
|
+
|
|
271
|
+
// Create field state for the group
|
|
272
|
+
const field = createField(name, controlledValue ?? defaultValue, validation)
|
|
273
|
+
|
|
274
|
+
// Register field with form if form context exists
|
|
275
|
+
if (formContext) {
|
|
276
|
+
formContext.register(name, validation)
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Sync with controlled value
|
|
280
|
+
if (controlledValue !== undefined) {
|
|
281
|
+
createEffect(() => {
|
|
282
|
+
if (field.value() !== controlledValue) {
|
|
283
|
+
field.setValue(controlledValue)
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Handle radio selection change
|
|
289
|
+
const handleRadioChange = (optionValue: any) => {
|
|
290
|
+
field.setValue(optionValue)
|
|
291
|
+
|
|
292
|
+
if (formContext) {
|
|
293
|
+
formContext.setValue(name, optionValue)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (onChange) {
|
|
297
|
+
onChange(name, optionValue)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Keyboard navigation for radio group
|
|
302
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
303
|
+
const currentIndex = options.findIndex(opt => opt.value === field.value())
|
|
304
|
+
let nextIndex = currentIndex
|
|
305
|
+
|
|
306
|
+
switch (event.key) {
|
|
307
|
+
case 'ArrowDown':
|
|
308
|
+
case 'ArrowRight':
|
|
309
|
+
event.preventDefault()
|
|
310
|
+
nextIndex = (currentIndex + 1) % options.length
|
|
311
|
+
break
|
|
312
|
+
case 'ArrowUp':
|
|
313
|
+
case 'ArrowLeft':
|
|
314
|
+
event.preventDefault()
|
|
315
|
+
nextIndex = currentIndex === 0 ? options.length - 1 : currentIndex - 1
|
|
316
|
+
break
|
|
317
|
+
case 'Home':
|
|
318
|
+
event.preventDefault()
|
|
319
|
+
nextIndex = 0
|
|
320
|
+
break
|
|
321
|
+
case 'End':
|
|
322
|
+
event.preventDefault()
|
|
323
|
+
nextIndex = options.length - 1
|
|
324
|
+
break
|
|
325
|
+
default:
|
|
326
|
+
return
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Skip disabled options
|
|
330
|
+
while (options[nextIndex]?.disabled) {
|
|
331
|
+
if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
|
|
332
|
+
nextIndex = (nextIndex + 1) % options.length
|
|
333
|
+
} else {
|
|
334
|
+
nextIndex = nextIndex === 0 ? options.length - 1 : nextIndex - 1
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Prevent infinite loop
|
|
338
|
+
if (nextIndex === currentIndex) break
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (!options[nextIndex]?.disabled) {
|
|
342
|
+
handleRadioChange(options[nextIndex].value)
|
|
343
|
+
|
|
344
|
+
// Focus the newly selected radio
|
|
345
|
+
setTimeout(() => {
|
|
346
|
+
const radioInput = document.querySelector(
|
|
347
|
+
`input[name="${name}"][value="${options[nextIndex].value}"]`
|
|
348
|
+
) as HTMLInputElement
|
|
349
|
+
if (radioInput) {
|
|
350
|
+
radioInput.focus()
|
|
351
|
+
}
|
|
352
|
+
}, 0)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const errorMessage = error || field.error()
|
|
357
|
+
|
|
358
|
+
const componentInstance: ComponentInstance = {
|
|
359
|
+
type: 'component',
|
|
360
|
+
id: restProps.id || `radio-group-${name}`,
|
|
361
|
+
render: () =>
|
|
362
|
+
h(
|
|
363
|
+
'fieldset',
|
|
364
|
+
{
|
|
365
|
+
...restProps,
|
|
366
|
+
'data-tachui-radio-group': true,
|
|
367
|
+
'data-direction': direction,
|
|
368
|
+
'data-disabled': disabled,
|
|
369
|
+
role: 'radiogroup',
|
|
370
|
+
'aria-invalid': !!errorMessage,
|
|
371
|
+
'aria-describedby':
|
|
372
|
+
[
|
|
373
|
+
errorMessage ? `${name}-error` : null,
|
|
374
|
+
helperText ? `${name}-helper` : null,
|
|
375
|
+
]
|
|
376
|
+
.filter(Boolean)
|
|
377
|
+
.join(' ') || undefined,
|
|
378
|
+
onkeydown: handleKeyDown,
|
|
379
|
+
},
|
|
380
|
+
// Group label
|
|
381
|
+
...(label
|
|
382
|
+
? [
|
|
383
|
+
h(
|
|
384
|
+
'legend',
|
|
385
|
+
{
|
|
386
|
+
'data-tachui-group-label': true,
|
|
387
|
+
},
|
|
388
|
+
text(label),
|
|
389
|
+
...(required
|
|
390
|
+
? [
|
|
391
|
+
h(
|
|
392
|
+
'span',
|
|
393
|
+
{
|
|
394
|
+
'aria-label': 'required',
|
|
395
|
+
'data-required-indicator': true,
|
|
396
|
+
},
|
|
397
|
+
text(' *')
|
|
398
|
+
),
|
|
399
|
+
]
|
|
400
|
+
: [])
|
|
401
|
+
),
|
|
402
|
+
]
|
|
403
|
+
: []),
|
|
404
|
+
|
|
405
|
+
// Radio options
|
|
406
|
+
h(
|
|
407
|
+
'div',
|
|
408
|
+
{
|
|
409
|
+
'data-tachui-radio-options': true,
|
|
410
|
+
'data-direction': direction,
|
|
411
|
+
},
|
|
412
|
+
...options.flatMap((option, index) => {
|
|
413
|
+
const radio = Radio({
|
|
414
|
+
name: `${name}-${index}`,
|
|
415
|
+
groupName: name,
|
|
416
|
+
value: option.value,
|
|
417
|
+
label: option.label,
|
|
418
|
+
checked: field.value() === option.value,
|
|
419
|
+
disabled: disabled || option.disabled,
|
|
420
|
+
required,
|
|
421
|
+
onChange: () => handleRadioChange(option.value),
|
|
422
|
+
_formContext: formContext,
|
|
423
|
+
})
|
|
424
|
+
const result = radio.render()
|
|
425
|
+
return Array.isArray(result) ? result : [result]
|
|
426
|
+
})
|
|
427
|
+
),
|
|
428
|
+
|
|
429
|
+
// Error message
|
|
430
|
+
...(errorMessage
|
|
431
|
+
? [
|
|
432
|
+
h(
|
|
433
|
+
'div',
|
|
434
|
+
{
|
|
435
|
+
id: `${name}-error`,
|
|
436
|
+
role: 'alert',
|
|
437
|
+
'aria-live': 'polite',
|
|
438
|
+
'data-tachui-error': true,
|
|
439
|
+
},
|
|
440
|
+
text(errorMessage)
|
|
441
|
+
),
|
|
442
|
+
]
|
|
443
|
+
: []),
|
|
444
|
+
|
|
445
|
+
// Helper text
|
|
446
|
+
...(helperText && !errorMessage
|
|
447
|
+
? [
|
|
448
|
+
h(
|
|
449
|
+
'div',
|
|
450
|
+
{
|
|
451
|
+
id: `${name}-helper`,
|
|
452
|
+
'data-tachui-helper': true,
|
|
453
|
+
},
|
|
454
|
+
text(helperText)
|
|
455
|
+
),
|
|
456
|
+
]
|
|
457
|
+
: [])
|
|
458
|
+
),
|
|
459
|
+
props: props,
|
|
460
|
+
cleanup: [
|
|
461
|
+
() => {
|
|
462
|
+
if (formContext) {
|
|
463
|
+
formContext.unregister(name)
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
],
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
return componentInstance
|
|
470
|
+
}
|