Skip to content

Commit 28054eb

Browse files
committed
fix: convert to Typescript
BREAKING CHANGE: remove render prop from Liform and LiformApi
1 parent 8f949f9 commit 28054eb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1699
-1267
lines changed
Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import React from 'react';
2-
import PropTypes from 'prop-types'
1+
import React, { ComponentProps } from 'react'
32
import { FieldArray as FinalFieldArray } from 'react-final-form-arrays'
43
import { Lifield, finalizeName, liformizeName } from '../..'
5-
import { Errors } from '../shared';
6-
import { SchemaProp } from '../../schema';
7-
import { LiformContextProp } from '../../form';
4+
import { Errors } from '../shared'
5+
import { LifieldWidgetProps } from '../../types'
86

9-
export const ArrayWidget = props => {
10-
const {
7+
export function ArrayWidget(
8+
{
119
liform,
1210
name,
13-
schema = true,
11+
schema: schemaProp = true,
1412
...others
15-
} = props
16-
13+
}: ComponentProps<typeof Lifield> & LifieldWidgetProps,
14+
): React.ReactElement {
1715
const finalName = finalizeName(name)
16+
const schema = typeof schemaProp === 'object' ? schemaProp : {}
1817

1918
return <FinalFieldArray name={finalName} render={({fields, meta}) => (
2019
<fieldset className="liform-field liform-array">
@@ -35,15 +34,9 @@ export const ArrayWidget = props => {
3534
}
3635
</div>
3736
)) }
38-
{ (schema.allowAdd || fields.length < (Array.isArray(meta.initial) ? meta.initial.length : 0))
39-
&& <button type="button" onClick={() => fields.push()}><span role="img" aria-label="add collection element"></span></button>
37+
{ (schema.allowAdd || (fields.length ?? 0) < (Array.isArray(meta.initial) ? meta.initial.length : 0))
38+
&& <button type="button" onClick={() => fields.push(undefined)}><span role="img" aria-label="add collection element"></span></button>
4039
}
4140
</fieldset>
4241
)}/>
4342
}
44-
45-
ArrayWidget.propTypes = {
46-
liform: LiformContextProp,
47-
schema: SchemaProp,
48-
name: PropTypes.string,
49-
}

src/DefaultTheme/Button/ButtonWidget.jsx

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react'
2+
import { LifieldWidgetProps } from '../../types'
3+
4+
export function ButtonWidget(
5+
{
6+
name,
7+
schema: schemaProp,
8+
}: LifieldWidgetProps,
9+
): React.ReactElement {
10+
11+
const types = ['submit', 'reset', 'button'] as const
12+
const schema = typeof schemaProp === 'object' ? schemaProp : {}
13+
const widget = typeof schema === 'object' ? schema.widget : undefined
14+
15+
let type
16+
if (typeof(widget) === 'string') {
17+
type = types.find(v => v === schema.widget)
18+
} else if (Array.isArray(schema.widget)) {
19+
type = types.filter(t => schema.widget?.includes(t))[0]
20+
}
21+
22+
return <button name={name} type={type || 'button'} className="liform-field liform-button">{schema.title}</button>
23+
}

src/DefaultTheme/Choice/Choice.jsx

Lines changed: 0 additions & 74 deletions
This file was deleted.

src/DefaultTheme/Choice/Choice.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React from 'react'
2+
import { Field } from '../Field/Field'
3+
import { PureOption } from './PureOption'
4+
import { LifieldRenderProps, LiformApi } from '../../types'
5+
import { arrayOrUndef, objOrUndef } from '../shared'
6+
7+
export function Choice(
8+
{
9+
schema: schemaProp = true,
10+
input: {
11+
name,
12+
onChange: onChangeProp,
13+
...input
14+
},
15+
placeholder,
16+
meta,
17+
}: LifieldRenderProps<
18+
string | string[],
19+
LiformApi,
20+
HTMLInputElement|HTMLSelectElement
21+
>,
22+
): React.ReactElement {
23+
const schema = typeof schemaProp === 'object' ? schemaProp : {}
24+
25+
const inputName = name + (schema.type === 'array' ? '[]' : '')
26+
27+
const options: {
28+
value: string
29+
title?: string
30+
}[] = (schema.enum || (objOrUndef(schema.items)?.enum ?? [])).map((v, i) => ({
31+
value: String(v),
32+
title: (schema.enumTitles || objOrUndef(schema.items)?.enumTitles || [])[i],
33+
}))
34+
35+
return schema.choiceExpanded
36+
? (
37+
<fieldset className="liform-field liform-choice">
38+
<legend>{ schema && schema.title }</legend>
39+
<div className="liform-options">
40+
{ options.map((o, i) =>
41+
<label key={i}>
42+
<input
43+
type={schema.type === 'array' ? 'checkbox' : 'radio'}
44+
name={inputName}
45+
value={o.value}
46+
checked={
47+
schema.type === 'array'
48+
? arrayOrUndef(input.value)?.includes(o.value)
49+
: input.value === o.value
50+
}
51+
onChange={e => onChangeProp(
52+
schema.type === 'array'
53+
? (e.target.checked
54+
? arrayOrUndef(input.value)?.concat([o.value])
55+
: arrayOrUndef(input.value)?.filter((v: string) => v !== o.value)
56+
)
57+
: (e.target.checked ? o.value : null),
58+
) }
59+
/>
60+
{ o.title || o.value }
61+
</label>,
62+
) }
63+
</div>
64+
{ meta.error?.map(e =>
65+
<div key={e} className="liform-error">{e}</div>,
66+
)}
67+
</fieldset>
68+
)
69+
: (
70+
<Field className="liform-choice" schema={schema} meta={meta}>
71+
<select {...input}
72+
multiple={schema.type === 'array'}
73+
name={inputName}
74+
onChange={e => onChangeProp(extractNativeSelectValue(e))}
75+
onBlur={e => onChangeProp(extractNativeSelectValue(e))}
76+
>
77+
{ schema.type !== 'array' && placeholder && <option value="">{placeholder}</option> }
78+
{ (schema.enum || objOrUndef(schema.items)?.enum) && (
79+
options.map(v => <PureOption key={v.value} value={v.value} title={v.title}/>)
80+
)}
81+
</select>
82+
</Field>
83+
)
84+
}
85+
86+
function extractNativeSelectValue(
87+
event: React.ChangeEvent<HTMLSelectElement> | React.FocusEvent<HTMLSelectElement>,
88+
) {
89+
if (event.target.hasAttribute('multiple')) {
90+
const v = []
91+
for (let i = 0; i < event.target.selectedOptions.length; i++) {
92+
const item = event.target.selectedOptions.item(i)
93+
v.push((item as NonNullable<typeof item>).value)
94+
}
95+
return v
96+
}
97+
98+
return event.target.value
99+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React from 'react'
2+
3+
export const PureOption = React.memo(
4+
function PureOption(
5+
{
6+
value,
7+
title,
8+
}: {
9+
value: string
10+
title?: string
11+
},
12+
): React.ReactElement {
13+
return <option value={value}>
14+
{title || value}
15+
</option>
16+
},
17+
)
18+

src/DefaultTheme/Choice/PureOptions.jsx

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/DefaultTheme/Field/Field.jsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/DefaultTheme/Field/Field.tsx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React, { PropsWithChildren } from 'react'
2+
import { LifieldRenderProps, LiformSchema } from '../../types'
3+
import { objOrUndef } from '../shared'
4+
5+
export function Field(
6+
{
7+
schema,
8+
meta: {error},
9+
className,
10+
children,
11+
}: PropsWithChildren<{
12+
schema: LiformSchema
13+
meta: LifieldRenderProps['meta']
14+
className: string
15+
}>,
16+
): React.ReactElement {
17+
return (
18+
<div
19+
className={'liform-field ' + className}
20+
>
21+
<label>
22+
{ objOrUndef(schema)?.title }
23+
{ children }
24+
</label>
25+
{ error?.map(e =>
26+
<div key={e} className="liform-error">{e}</div>,
27+
)}
28+
</div>
29+
)
30+
}
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import React from 'react';
2-
import { FieldRenderProps } from '../../field';
2+
import { LifieldRenderProps } from '../../types';
33
import { Input } from './Input'
44

5-
export const ColorInput = props => {
6-
const {
5+
export function ColorInput(
6+
{
77
input: {
88
value,
99
...input
1010
},
1111
...others
12-
} = props
13-
12+
}: LifieldRenderProps,
13+
): React.ReactElement {
1414
return <Input
1515
{...others}
1616
input={{
@@ -20,5 +20,3 @@ export const ColorInput = props => {
2020
}}
2121
/>
2222
}
23-
24-
ColorInput.propTypes = FieldRenderProps

0 commit comments

Comments
 (0)