From 67214a13f5ed67dd46071caf0d0ad0bee1a4d071 Mon Sep 17 00:00:00 2001 From: Egor Date: Tue, 18 Apr 2023 13:05:30 +0300 Subject: [PATCH] feat(ObjectValue): added new input object value (#28) --- .../ObjectValueInput/ObjectValueInput.tsx | 45 +++++++++++++++++++ .../Inputs/ObjectValueInput/index.ts | 1 + src/lib/kit/components/Inputs/index.ts | 1 + .../ObjectValueInputView.tsx | 20 +++++++++ .../Views/ObjectValueInputView/index.ts | 1 + src/lib/kit/components/Views/index.ts | 1 + src/lib/kit/constants/config.tsx | 6 +++ src/stories/ObjectTextLink.stories.tsx | 2 +- src/stories/ObjectValue.stories.tsx | 41 +++++++++++++++++ 9 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.tsx create mode 100644 src/lib/kit/components/Inputs/ObjectValueInput/index.ts create mode 100644 src/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.tsx create mode 100644 src/lib/kit/components/Views/ObjectValueInputView/index.ts create mode 100644 src/stories/ObjectValue.stories.tsx diff --git a/src/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.tsx b/src/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.tsx new file mode 100644 index 00000000..2e87b53a --- /dev/null +++ b/src/lib/kit/components/Inputs/ObjectValueInput/ObjectValueInput.tsx @@ -0,0 +1,45 @@ +import React from 'react'; + +import _ from 'lodash'; + +import {Controller, FieldValue, ObjectIndependentInput, ValidateError} from '../../../../core'; + +const OBJECT_VALUE_PROPERTY_NAME = 'value'; + +export const ObjectValueInput: ObjectIndependentInput = ({spec, input, name}) => { + const parentOnChange = React.useCallback( + (childName: string, childValue: FieldValue, childErrors?: Record) => + input.onChange( + (currentValue) => + _.set( + {...(currentValue || {})}, + childName.split(`${name}.`).join(''), + childValue, + ), + childErrors, + ), + [input.onChange, input.name], + ); + + const parentOnUnmount = React.useCallback( + (childName: string) => input.onChange((currentValue) => currentValue, {[childName]: false}), + [input.onChange], + ); + + const specProperties = {...spec.properties}; + + if (!specProperties[OBJECT_VALUE_PROPERTY_NAME]) { + return null; + } + + return ( + + ); +}; diff --git a/src/lib/kit/components/Inputs/ObjectValueInput/index.ts b/src/lib/kit/components/Inputs/ObjectValueInput/index.ts new file mode 100644 index 00000000..cddfd501 --- /dev/null +++ b/src/lib/kit/components/Inputs/ObjectValueInput/index.ts @@ -0,0 +1 @@ +export * from './ObjectValueInput'; diff --git a/src/lib/kit/components/Inputs/index.ts b/src/lib/kit/components/Inputs/index.ts index ed07bed4..df5c775e 100644 --- a/src/lib/kit/components/Inputs/index.ts +++ b/src/lib/kit/components/Inputs/index.ts @@ -4,6 +4,7 @@ export * from './Checkbox'; export * from './FileInput'; export * from './MultiSelect'; export * from './ObjectBase'; +export * from './ObjectValueInput'; export * from './OneOf'; export * from './OneOfCard'; export * from './Secret'; diff --git a/src/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.tsx b/src/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.tsx new file mode 100644 index 00000000..570f0de9 --- /dev/null +++ b/src/lib/kit/components/Views/ObjectValueInputView/ObjectValueInputView.tsx @@ -0,0 +1,20 @@ +import React from 'react'; + +import {ObjectIndependentView, ViewController} from '../../../../core'; + +const OBJECT_VALUE_PROPERTY_NAME = 'value'; + +export const ObjectValueInputView: ObjectIndependentView = ({spec, name}) => { + const specProperties = {...spec.properties}; + + if (!specProperties[OBJECT_VALUE_PROPERTY_NAME]) { + return null; + } + + return ( + + ); +}; diff --git a/src/lib/kit/components/Views/ObjectValueInputView/index.ts b/src/lib/kit/components/Views/ObjectValueInputView/index.ts new file mode 100644 index 00000000..7dcfa9cc --- /dev/null +++ b/src/lib/kit/components/Views/ObjectValueInputView/index.ts @@ -0,0 +1 @@ +export * from './ObjectValueInputView'; diff --git a/src/lib/kit/components/Views/index.ts b/src/lib/kit/components/Views/index.ts index 999d4edd..b27c196b 100644 --- a/src/lib/kit/components/Views/index.ts +++ b/src/lib/kit/components/Views/index.ts @@ -6,6 +6,7 @@ export * from './MonacoInputView'; export * from './MultiSelectView'; export * from './NumberWithScaleView'; export * from './ObjectBaseView'; +export * from './ObjectValueInputView'; export * from './OneOfCardView'; export * from './OneOfView'; export * from './TableArrayView'; diff --git a/src/lib/kit/constants/config.tsx b/src/lib/kit/constants/config.tsx index 6da420c9..fa615880 100644 --- a/src/lib/kit/constants/config.tsx +++ b/src/lib/kit/constants/config.tsx @@ -24,6 +24,8 @@ import { NumberWithScaleView, ObjectBase, ObjectBaseView, + ObjectValueInput, + ObjectValueInputView, OneOf, OneOfCard, OneOfCardView, @@ -130,6 +132,7 @@ export const dynamicConfig: DynamicFormConfig = { secret: {Component: Secret, independent: true}, base: {Component: ObjectBase, independent: true}, text_link: {Component: TextLink, independent: true}, + object_value: {Component: ObjectValueInput, independent: true}, }, layouts: { row: Row, @@ -228,6 +231,7 @@ export const dynamicCardConfig: DynamicFormConfig = { secret: {Component: Secret, independent: true}, base: {Component: ObjectBase, independent: true}, text_link: {Component: TextLink, independent: true}, + object_value: {Component: ObjectValueInput, independent: true}, }, layouts: { row: Row2, @@ -315,6 +319,7 @@ export const dynamicViewConfig: DynamicViewConfig = { secret: undefined, base: {Component: ObjectBaseView, independent: true}, text_link: {Component: TextLinkView, independent: true}, + object_value: {Component: ObjectValueInputView, independent: true}, }, layouts: { row: ViewRow, @@ -395,6 +400,7 @@ export const dynamicViewCardConfig: DynamicViewConfig = { secret: undefined, base: {Component: ObjectBaseView, independent: true}, text_link: {Component: TextLinkView, independent: true}, + object_value: {Component: ObjectValueInputView, independent: true}, }, layouts: { row: ViewRow2, diff --git a/src/stories/ObjectTextLink.stories.tsx b/src/stories/ObjectTextLink.stories.tsx index 7a073bf7..1881964f 100644 --- a/src/stories/ObjectTextLink.stories.tsx +++ b/src/stories/ObjectTextLink.stories.tsx @@ -31,7 +31,7 @@ const baseSpec: ObjectSpec = { const value = {link: 'https://gravity-ui.com'}; -const excludeOptions = ['description', 'validator', 'viewSpec']; +const excludeOptions = ['description', 'validator', 'viewSpec', 'required']; const template = (spec: ObjectSpec = baseSpec) => { const Template: ComponentStory = (__, {viewMode}) => ( diff --git a/src/stories/ObjectValue.stories.tsx b/src/stories/ObjectValue.stories.tsx new file mode 100644 index 00000000..ec95e28b --- /dev/null +++ b/src/stories/ObjectValue.stories.tsx @@ -0,0 +1,41 @@ +import React from 'react'; + +import {ComponentStory} from '@storybook/react'; + +import {ObjectSpec, ObjectValueInput as ObjectValueInputBase, SpecTypes} from '../lib'; + +import {InputPreview} from './components'; + +export default { + title: 'Object/ObjectValue', + component: ObjectValueInputBase, +}; + +const baseSpec: ObjectSpec = { + type: SpecTypes.Object, + properties: { + value: { + type: SpecTypes.String, + viewSpec: { + type: 'base', + layout: 'row', + layoutTitle: 'Value', + }, + }, + }, + viewSpec: { + type: 'object_value', + }, +}; + +const excludeOptions = ['description', 'validator', 'viewSpec', 'required']; + +const template = (spec: ObjectSpec = baseSpec) => { + const Template: ComponentStory = (__, {viewMode}) => ( + + ); + + return Template; +}; + +export const ObjectValue = template();