@dxos/react-ui-form 0.8.2-staging.7ac8446 → 0.8.3-main.672df60
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/dist/lib/browser/index.mjs +1817 -1309
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node/index.cjs +1773 -1273
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +1817 -1309
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/{ControlSection.d.ts → ControlSection/ControlSection.d.ts} +9 -6
- package/dist/types/src/components/ControlSection/ControlSection.d.ts.map +1 -0
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +8 -0
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts.map +1 -0
- package/dist/types/src/components/ControlSection/index.d.ts +2 -0
- package/dist/types/src/components/ControlSection/index.d.ts.map +1 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.d.ts.map +1 -1
- package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts +2 -0
- package/dist/types/src/components/FieldEditor/FieldEditor.test.d.ts.map +1 -0
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Defaults.d.ts +4 -4
- package/dist/types/src/components/Form/Defaults.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +6 -4
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +38 -36
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormActions.d.ts +1 -1
- package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts +16 -12
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +2 -2
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/RefField.d.ts +12 -0
- package/dist/types/src/components/Form/RefField.d.ts.map +1 -0
- package/dist/types/src/components/Form/custom/GeoPointInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/TupleInput.d.ts.map +1 -1
- package/dist/types/src/components/Form/factory.d.ts +1 -1
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/Form/index.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/Test.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +2 -2
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +5 -3
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.test.d.ts +2 -0
- package/dist/types/src/components/ViewEditor/ViewEditor.test.d.ts.map +1 -0
- package/dist/types/src/components/deprecated/Form.d.ts +2 -2
- package/dist/types/src/components/deprecated/Form.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/deprecated/FormInput.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +2 -2
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +23 -0
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -0
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts +8 -0
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +5 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/refs.d.ts +9 -0
- package/dist/types/src/util/refs.d.ts.map +1 -0
- package/dist/types/src/util/schema.d.ts +3 -0
- package/dist/types/src/util/schema.d.ts.map +1 -0
- package/dist/types/src/vitest-setup.d.ts +2 -0
- package/dist/types/src/vitest-setup.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +28 -25
- package/src/components/ControlSection/ControlSection.stories.tsx +29 -0
- package/src/components/{ControlSection.tsx → ControlSection/ControlSection.tsx} +40 -16
- package/src/components/ControlSection/index.ts +5 -0
- package/src/components/FieldEditor/FieldEditor.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.test.tsx +49 -0
- package/src/components/FieldEditor/FieldEditor.tsx +3 -2
- package/src/components/Form/ArrayField.tsx +63 -50
- package/src/components/Form/Defaults.tsx +77 -48
- package/src/components/Form/Form.stories.tsx +134 -109
- package/src/components/Form/Form.tsx +8 -5
- package/src/components/Form/FormActions.tsx +15 -18
- package/src/components/Form/FormContent.tsx +116 -46
- package/src/components/Form/FormContext.tsx +24 -10
- package/src/components/Form/Input.tsx +4 -10
- package/src/components/Form/RefField.tsx +217 -0
- package/src/components/Form/custom/GeoPointInput.tsx +2 -2
- package/src/components/Form/custom/SelectOptionsInput.stories.tsx +6 -5
- package/src/components/Form/custom/SelectOptionsInput.tsx +2 -2
- package/src/components/Form/factory.tsx +1 -1
- package/src/components/Form/index.ts +0 -1
- package/src/components/ViewEditor/ViewEditor.stories.tsx +19 -9
- package/src/components/ViewEditor/ViewEditor.test.tsx +166 -0
- package/src/components/ViewEditor/ViewEditor.tsx +63 -30
- package/src/components/deprecated/Form.stories.tsx +6 -6
- package/src/components/deprecated/Form.tsx +6 -6
- package/src/components/deprecated/FormInput.tsx +1 -1
- package/src/components/index.ts +1 -0
- package/src/components/testing.tsx +5 -9
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useForm.ts +4 -3
- package/src/hooks/useQueryRefOptions.ts +53 -0
- package/src/hooks/useRefQueryLookupHandler.ts +39 -0
- package/src/translations.ts +9 -2
- package/src/util/formatting.ts +15 -3
- package/src/util/index.ts +3 -1
- package/src/util/refs.ts +38 -0
- package/src/util/schema.ts +14 -0
- package/src/vitest-setup.ts +11 -0
- package/dist/types/src/components/ControlSection.d.ts.map +0 -1
|
@@ -79,6 +79,7 @@ export const FieldEditor = ({ view, projection, field, registry, onSave, onCance
|
|
|
79
79
|
}
|
|
80
80
|
return { fieldSchema };
|
|
81
81
|
});
|
|
82
|
+
|
|
82
83
|
setReferenceSchema((prev) => {
|
|
83
84
|
if (_props.referenceSchema !== prev?.typename) {
|
|
84
85
|
const newSchema = schemas.find((schema) => schema.typename === _props.referenceSchema);
|
|
@@ -129,7 +130,7 @@ export const FieldEditor = ({ view, projection, field, registry, onSave, onCance
|
|
|
129
130
|
onSave();
|
|
130
131
|
}, [onSave]);
|
|
131
132
|
|
|
132
|
-
const
|
|
133
|
+
const custom: Partial<Record<string, InputComponent>> = useMemo(
|
|
133
134
|
() => ({
|
|
134
135
|
['format' satisfies keyof PropertyType]: (props) => (
|
|
135
136
|
<SelectInput
|
|
@@ -187,7 +188,7 @@ export const FieldEditor = ({ view, projection, field, registry, onSave, onCance
|
|
|
187
188
|
onValidate={handleValidate}
|
|
188
189
|
onSave={handleSave}
|
|
189
190
|
onCancel={handleCancel}
|
|
190
|
-
Custom={
|
|
191
|
+
Custom={custom}
|
|
191
192
|
/>
|
|
192
193
|
);
|
|
193
194
|
};
|
|
@@ -2,15 +2,13 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { pipe } from 'effect';
|
|
5
|
+
import { SchemaAST, pipe } from 'effect';
|
|
6
6
|
import { capitalize } from 'effect/String';
|
|
7
|
-
import React, {
|
|
7
|
+
import React, { Fragment, useCallback } from 'react';
|
|
8
8
|
|
|
9
|
-
import { AST } from '@dxos/echo-schema';
|
|
10
9
|
import { findNode, getDiscriminatedType, isDiscriminatedUnion, SimpleType } from '@dxos/effect';
|
|
11
10
|
import { invariant } from '@dxos/invariant';
|
|
12
11
|
import { IconButton, useTranslation } from '@dxos/react-ui';
|
|
13
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
14
12
|
import { getSchemaProperties, type SchemaProperty } from '@dxos/schema';
|
|
15
13
|
|
|
16
14
|
import { type ComponentLookup } from './Form';
|
|
@@ -18,8 +16,7 @@ import { FormField } from './FormContent';
|
|
|
18
16
|
import { useFormValues, type FormInputStateProps } from './FormContext';
|
|
19
17
|
import { InputHeader, type InputComponent } from './Input';
|
|
20
18
|
import { translationKey } from '../../translations';
|
|
21
|
-
|
|
22
|
-
const padding = 'px-2';
|
|
19
|
+
import { findArrayElementType } from '../../util';
|
|
23
20
|
|
|
24
21
|
type ArrayFieldProps = {
|
|
25
22
|
property: SchemaProperty<any>;
|
|
@@ -33,16 +30,17 @@ type ArrayFieldProps = {
|
|
|
33
30
|
export const ArrayField = ({ property, readonly, path, inputProps, Custom, lookupComponent }: ArrayFieldProps) => {
|
|
34
31
|
const { t } = useTranslation(translationKey);
|
|
35
32
|
const { ast, name, type, title } = property;
|
|
36
|
-
|
|
33
|
+
// TODO(wittjosiah): The fallback to an empty array stops the form from crashing but isn't immediately live.
|
|
34
|
+
// It doesn't become live until another field is touched, but that's better than the whole form crashing.
|
|
35
|
+
const values = (useFormValues(path ?? []) ?? []) as any[];
|
|
37
36
|
invariant(Array.isArray(values), `Values at path ${path?.join('.')} must be an array.`);
|
|
38
37
|
const label = title ?? pipe(name, capitalize);
|
|
39
38
|
|
|
40
|
-
const
|
|
41
|
-
const elementType = (tupleType as AST.TupleType | undefined)?.rest[0]?.type;
|
|
39
|
+
const elementType = findArrayElementType(ast);
|
|
42
40
|
|
|
43
|
-
const getDefaultObjectValue = (typeNode:
|
|
41
|
+
const getDefaultObjectValue = (typeNode: SchemaAST.AST): any => {
|
|
44
42
|
const baseNode = findNode(typeNode, isDiscriminatedUnion);
|
|
45
|
-
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode,
|
|
43
|
+
const typeLiteral = baseNode ? getDiscriminatedType(baseNode, {}) : findNode(typeNode, SchemaAST.isTypeLiteral);
|
|
46
44
|
if (!typeLiteral) {
|
|
47
45
|
return {};
|
|
48
46
|
}
|
|
@@ -50,17 +48,12 @@ export const ArrayField = ({ property, readonly, path, inputProps, Custom, looku
|
|
|
50
48
|
return Object.fromEntries(getSchemaProperties(typeLiteral, {}).map((prop) => [prop.name, prop.defaultValue]));
|
|
51
49
|
};
|
|
52
50
|
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
return getDefaultObjectValue(elementType);
|
|
56
|
-
} else {
|
|
57
|
-
return SimpleType.getDefaultValue(type);
|
|
58
|
-
}
|
|
59
|
-
}, [type, elementType]);
|
|
51
|
+
const getDefaultValue = () =>
|
|
52
|
+
type === 'object' && elementType ? getDefaultObjectValue(elementType) : SimpleType.getDefaultValue(type);
|
|
60
53
|
|
|
61
54
|
const handleAdd = useCallback(() => {
|
|
62
|
-
inputProps.onValueChange(type, [...values,
|
|
63
|
-
}, [type, elementType, inputProps,
|
|
55
|
+
inputProps.onValueChange(type, [...values, getDefaultValue()]);
|
|
56
|
+
}, [type, elementType, inputProps, values]);
|
|
64
57
|
|
|
65
58
|
const handleRemove = useCallback(
|
|
66
59
|
(index: number) => {
|
|
@@ -74,38 +67,58 @@ export const ArrayField = ({ property, readonly, path, inputProps, Custom, looku
|
|
|
74
67
|
return null;
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
return (
|
|
78
|
-
|
|
70
|
+
return readonly && values.length < 1 ? null : (
|
|
71
|
+
<>
|
|
79
72
|
<InputHeader>{label}</InputHeader>
|
|
80
|
-
<div
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
<div
|
|
74
|
+
role='none'
|
|
75
|
+
className={
|
|
76
|
+
readonly
|
|
77
|
+
? 'flex flex-wrap gap-1 mlb-1'
|
|
78
|
+
: values.length > 0
|
|
79
|
+
? 'grid gap-1 grid-cols-[1fr_min-content] mlb-1'
|
|
80
|
+
: 'hidden'
|
|
81
|
+
}
|
|
82
|
+
>
|
|
83
|
+
{values.map((_value, index) => {
|
|
84
|
+
const field = (
|
|
85
|
+
<FormField
|
|
86
|
+
property={{
|
|
87
|
+
...property,
|
|
88
|
+
array: false, // NOTE(ZaymonFC): This breaks arrays of arrays but ¯\_(ツ)_/¯. Ping me if you need that.
|
|
89
|
+
ast: elementType,
|
|
90
|
+
}}
|
|
91
|
+
path={[...(path ?? []), index]}
|
|
92
|
+
readonly={readonly}
|
|
93
|
+
inline
|
|
94
|
+
Custom={Custom}
|
|
95
|
+
lookupComponent={lookupComponent}
|
|
102
96
|
/>
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
97
|
+
);
|
|
98
|
+
return readonly ? (
|
|
99
|
+
field
|
|
100
|
+
) : (
|
|
101
|
+
<Fragment key={index}>
|
|
102
|
+
<div role='none'>{field}</div>
|
|
103
|
+
<IconButton
|
|
104
|
+
icon='ph--trash--regular'
|
|
105
|
+
iconOnly
|
|
106
|
+
label={t('button remove')}
|
|
107
|
+
onClick={() => handleRemove(index)}
|
|
108
|
+
classNames='self-center'
|
|
109
|
+
/>
|
|
110
|
+
</Fragment>
|
|
111
|
+
);
|
|
112
|
+
})}
|
|
108
113
|
</div>
|
|
109
|
-
|
|
114
|
+
{!readonly && (
|
|
115
|
+
<IconButton
|
|
116
|
+
classNames='is-full mlb-1 flex'
|
|
117
|
+
icon='ph--plus--regular'
|
|
118
|
+
label={t('add field')}
|
|
119
|
+
onClick={handleAdd}
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
122
|
+
</>
|
|
110
123
|
);
|
|
111
124
|
};
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useEffect, useRef } from 'react';
|
|
6
6
|
|
|
7
|
-
import { Input, Select } from '@dxos/react-ui';
|
|
7
|
+
import { Input, Select, useTranslation } from '@dxos/react-ui';
|
|
8
8
|
|
|
9
9
|
import { type InputProps, InputHeader } from './Input';
|
|
10
|
+
import { translationKey } from '../../translations';
|
|
10
11
|
|
|
11
12
|
export const TextInput = ({
|
|
12
13
|
type,
|
|
@@ -21,20 +22,26 @@ export const TextInput = ({
|
|
|
21
22
|
}: InputProps) => {
|
|
22
23
|
const { status, error } = getStatus();
|
|
23
24
|
|
|
24
|
-
return (
|
|
25
|
+
return disabled && !getValue() ? null : disabled && inputOnly ? (
|
|
26
|
+
<p>{getValue() ?? ''}</p>
|
|
27
|
+
) : (
|
|
25
28
|
<Input.Root validationValence={status}>
|
|
26
29
|
{!inputOnly && (
|
|
27
30
|
<InputHeader error={error}>
|
|
28
31
|
<Input.Label>{label}</Input.Label>
|
|
29
32
|
</InputHeader>
|
|
30
33
|
)}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
{disabled ? (
|
|
35
|
+
<p>{getValue() ?? ''}</p>
|
|
36
|
+
) : (
|
|
37
|
+
<Input.TextInput
|
|
38
|
+
disabled={disabled}
|
|
39
|
+
placeholder={placeholder}
|
|
40
|
+
value={getValue() ?? ''}
|
|
41
|
+
onChange={(event) => onValueChange(type, event.target.value)}
|
|
42
|
+
onBlur={onBlur}
|
|
43
|
+
/>
|
|
44
|
+
)}
|
|
38
45
|
{inputOnly && <Input.Validation>{error}</Input.Validation>}
|
|
39
46
|
</Input.Root>
|
|
40
47
|
);
|
|
@@ -53,29 +60,36 @@ export const NumberInput = ({
|
|
|
53
60
|
}: InputProps) => {
|
|
54
61
|
const { status, error } = getStatus();
|
|
55
62
|
|
|
56
|
-
return (
|
|
63
|
+
return disabled && !getValue() ? null : disabled && inputOnly ? (
|
|
64
|
+
<p>{getValue() ?? ''}</p>
|
|
65
|
+
) : (
|
|
57
66
|
<Input.Root validationValence={status}>
|
|
58
67
|
{!inputOnly && (
|
|
59
68
|
<InputHeader error={error}>
|
|
60
69
|
<Input.Label>{label}</Input.Label>
|
|
61
70
|
</InputHeader>
|
|
62
71
|
)}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
{disabled ? (
|
|
73
|
+
<p>{getValue() ?? ''}</p>
|
|
74
|
+
) : (
|
|
75
|
+
<Input.TextInput
|
|
76
|
+
type='number'
|
|
77
|
+
disabled={disabled}
|
|
78
|
+
placeholder={placeholder}
|
|
79
|
+
value={getValue() ?? 0}
|
|
80
|
+
onChange={(event) => onValueChange(type, event.target.value)}
|
|
81
|
+
onBlur={onBlur}
|
|
82
|
+
/>
|
|
83
|
+
)}
|
|
71
84
|
{inputOnly && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
|
|
72
85
|
</Input.Root>
|
|
73
86
|
);
|
|
74
87
|
};
|
|
75
88
|
|
|
76
|
-
export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onValueChange }: InputProps) => {
|
|
89
|
+
export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onValueChange, disabled }: InputProps) => {
|
|
77
90
|
const { status, error } = getStatus();
|
|
78
91
|
const checked = Boolean(getValue());
|
|
92
|
+
const { t } = useTranslation(translationKey);
|
|
79
93
|
|
|
80
94
|
return (
|
|
81
95
|
<Input.Root validationValence={status}>
|
|
@@ -84,7 +98,11 @@ export const BooleanInput = ({ type, label, inputOnly, getStatus, getValue, onVa
|
|
|
84
98
|
<Input.Label>{label}</Input.Label>
|
|
85
99
|
</InputHeader>
|
|
86
100
|
)}
|
|
87
|
-
|
|
101
|
+
{disabled ? (
|
|
102
|
+
<p>{t(checked ? 'boolean input true value' : 'boolean input false value')}</p>
|
|
103
|
+
) : (
|
|
104
|
+
<Input.Switch checked={checked} onCheckedChange={(value) => onValueChange(type, value)} />
|
|
105
|
+
)}
|
|
88
106
|
{inputOnly && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
|
|
89
107
|
</Input.Root>
|
|
90
108
|
);
|
|
@@ -107,29 +125,36 @@ export const SelectInput = ({
|
|
|
107
125
|
}: SelectInputOptions) => {
|
|
108
126
|
const { status, error } = getStatus();
|
|
109
127
|
|
|
110
|
-
|
|
128
|
+
const value = getValue() as string | undefined;
|
|
129
|
+
const handleValueChange = useCallback((value: string | number) => onValueChange(type, value), [type, onValueChange]);
|
|
130
|
+
|
|
131
|
+
return disabled && !value ? null : (
|
|
111
132
|
<Input.Root validationValence={status}>
|
|
112
133
|
{!inputOnly && (
|
|
113
134
|
<InputHeader error={error}>
|
|
114
135
|
<Input.Label>{label}</Input.Label>
|
|
115
136
|
</InputHeader>
|
|
116
137
|
)}
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
<Select.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
138
|
+
{disabled ? (
|
|
139
|
+
<p>{options?.find(({ value: optionValue }) => optionValue === value)?.label ?? String(value)}</p>
|
|
140
|
+
) : (
|
|
141
|
+
<Select.Root value={value} onValueChange={handleValueChange}>
|
|
142
|
+
{/* TODO(burdon): Placeholder not working? */}
|
|
143
|
+
<Select.TriggerButton classNames='is-full' disabled={disabled} placeholder={placeholder} />
|
|
144
|
+
<Select.Portal>
|
|
145
|
+
<Select.Content>
|
|
146
|
+
<Select.Viewport>
|
|
147
|
+
{options?.map(({ value, label }) => (
|
|
148
|
+
// NOTE: Numeric values are converted to and from strings.
|
|
149
|
+
<Select.Option key={String(value)} value={String(value)}>
|
|
150
|
+
{label ?? String(value)}
|
|
151
|
+
</Select.Option>
|
|
152
|
+
))}
|
|
153
|
+
</Select.Viewport>
|
|
154
|
+
</Select.Content>
|
|
155
|
+
</Select.Portal>
|
|
156
|
+
</Select.Root>
|
|
157
|
+
)}
|
|
133
158
|
{inputOnly && <Input.DescriptionAndValidation>{error}</Input.DescriptionAndValidation>}
|
|
134
159
|
</Input.Root>
|
|
135
160
|
);
|
|
@@ -177,17 +202,21 @@ export const MarkdownInput = ({
|
|
|
177
202
|
<Input.Label>{label}</Input.Label>
|
|
178
203
|
</InputHeader>
|
|
179
204
|
)}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
205
|
+
{disabled ? (
|
|
206
|
+
<p>{getValue() ?? ''}</p>
|
|
207
|
+
) : (
|
|
208
|
+
<Input.TextArea
|
|
209
|
+
ref={textareaRef}
|
|
210
|
+
disabled={disabled}
|
|
211
|
+
placeholder={placeholder}
|
|
212
|
+
value={getValue() ?? ''}
|
|
213
|
+
classNames={'min-bs-auto max-h-40 overflow-auto'}
|
|
214
|
+
onChange={(event) => onValueChange(type, event.target.value)}
|
|
215
|
+
onBlur={onBlur}
|
|
216
|
+
style={{ resize: 'none' }}
|
|
217
|
+
spellCheck={false}
|
|
218
|
+
/>
|
|
219
|
+
)}
|
|
191
220
|
{inputOnly && <Input.Validation>{error}</Input.Validation>}
|
|
192
221
|
</Input.Root>
|
|
193
222
|
);
|