Skip to content

Commit 31480c3

Browse files
authored
feat(ObjectBase): add inline variant (#104)
1 parent 65283d6 commit 31480c3

File tree

10 files changed

+214
-45
lines changed

10 files changed

+214
-45
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@import '../../../styles/variables.scss';
2+
3+
.#{$ns}object-base {
4+
&__content {
5+
&_inline {
6+
display: flex;
7+
8+
& > .#{$ns}use-search {
9+
width: 150px;
10+
margin-bottom: 0;
11+
margin-right: 8px;
12+
13+
&:last-child {
14+
margin-right: 0;
15+
}
16+
}
17+
}
18+
}
19+
}

src/lib/kit/components/Inputs/ObjectBase/ObjectBase.tsx

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,28 @@ import {
99
FieldObjectValue,
1010
FieldValue,
1111
ObjectIndependentInput,
12+
ObjectIndependentInputProps,
1213
ObjectValue,
13-
Spec,
1414
ValidateError,
1515
transformArrIn,
1616
} from '../../../../core';
17+
import {block, filterPropertiesForObjectInline} from '../../../utils';
1718

18-
export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restProps}) => {
19+
import './ObjectBase.scss';
20+
21+
const b = block('object-base');
22+
23+
export interface ObjectBaseProps extends ObjectIndependentInputProps {
24+
inline?: boolean;
25+
}
26+
27+
export const ObjectBase: React.FC<ObjectBaseProps> = ({
28+
inline,
29+
spec,
30+
name,
31+
Layout,
32+
...restProps
33+
}) => {
1934
const addBtn = React.useMemo(
2035
() => (
2136
<Button
@@ -49,18 +64,24 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
4964
);
5065

5166
const content = React.useMemo(() => {
52-
if (!_.isObjectLike(spec.properties) || !Object.keys(spec.properties || {}).length) {
67+
if (
68+
!spec.properties ||
69+
!_.isObjectLike(spec.properties) ||
70+
!Object.keys(spec.properties || {}).length
71+
) {
5372
return null;
5473
}
5574

56-
if (!restProps.input.value) {
75+
if (!inline && !restProps.input.value) {
5776
return addBtn;
5877
}
5978

60-
const specProperties = {...spec.properties} as Record<string, Spec>;
79+
const specProperties = inline
80+
? filterPropertiesForObjectInline(spec.properties)
81+
: spec.properties;
6182

6283
return (
63-
<React.Fragment>
84+
<div className={b('content', {inline})}>
6485
{(spec.viewSpec.order || Object.keys(specProperties)).map((property: string) =>
6586
specProperties[property] ? (
6687
<Controller
@@ -73,16 +94,17 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
7394
/>
7495
) : null,
7596
)}
76-
</React.Fragment>
97+
</div>
7798
);
7899
}, [
79100
spec.properties,
80101
spec.viewSpec.order,
81-
name,
82102
restProps.input.value,
103+
restProps.input.parentOnUnmount,
104+
inline,
83105
addBtn,
106+
name,
84107
parentOnChange,
85-
restProps.input.parentOnUnmount,
86108
]);
87109

88110
if (!Layout || !content) {
@@ -95,3 +117,7 @@ export const ObjectBase: ObjectIndependentInput = ({spec, name, Layout, ...restP
95117
</Layout>
96118
);
97119
};
120+
121+
export const ObjectInline: ObjectIndependentInput = (props) => {
122+
return <ObjectBase {...props} inline />;
123+
};

src/lib/kit/components/Views/ObjectBaseView.tsx

Lines changed: 0 additions & 36 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
@import '../../../styles/variables.scss';
2+
3+
.#{$ns}object-base-view {
4+
&__content {
5+
&_inline {
6+
display: flex;
7+
8+
& > div {
9+
flex: auto;
10+
margin-right: 8px;
11+
margin-bottom: 0;
12+
13+
&:last-child {
14+
margin-right: 0;
15+
}
16+
}
17+
}
18+
}
19+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
3+
import _ from 'lodash';
4+
5+
import {ObjectIndependentView, ObjectIndependentViewProps, ViewController} from '../../../../core';
6+
import {block, filterPropertiesForObjectInline} from '../../../utils';
7+
8+
import './ObjectBaseView.scss';
9+
10+
const b = block('object-base-view');
11+
12+
export interface ObjectBaseViewProps extends ObjectIndependentViewProps {
13+
inline?: boolean;
14+
}
15+
16+
export const ObjectBaseView: React.FC<ObjectBaseViewProps> = ({
17+
inline,
18+
spec,
19+
name,
20+
Layout,
21+
...restProps
22+
}) => {
23+
if (!spec.properties || !_.isObjectLike(spec.properties)) {
24+
return null;
25+
}
26+
27+
const specProperties = inline
28+
? filterPropertiesForObjectInline(spec.properties)
29+
: spec.properties;
30+
31+
const content = (
32+
<div className={b('content', {inline})}>
33+
{(spec.viewSpec.order || Object.keys(specProperties)).map((property: string) =>
34+
specProperties[property] ? (
35+
<ViewController
36+
spec={specProperties[property]}
37+
name={`${name ? name + '.' : ''}${property}`}
38+
key={`${name ? name + '.' : ''}${property}`}
39+
/>
40+
) : null,
41+
)}
42+
</div>
43+
);
44+
45+
if (!Layout) {
46+
return content;
47+
}
48+
49+
return (
50+
<Layout spec={spec} name={name} {...restProps}>
51+
{content}
52+
</Layout>
53+
);
54+
};
55+
56+
export const ObjectInlineView: ObjectIndependentView = (props) => {
57+
return <ObjectBaseView {...props} inline />;
58+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ObjectBaseView';

src/lib/kit/constants/config.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import {
2828
NumberWithScaleView,
2929
ObjectBase,
3030
ObjectBaseView,
31+
ObjectInline,
32+
ObjectInlineView,
3133
ObjectValueInput,
3234
ObjectValueInputView,
3335
OneOf,
@@ -144,6 +146,7 @@ export const dynamicConfig: DynamicFormConfig = {
144146
object_value: {Component: ObjectValueInput, independent: true},
145147
multi_oneof: {Component: MultiOneOf, independent: true},
146148
multi_oneof_flat: {Component: MultiOneOfFlat, independent: true},
149+
inline: {Component: ObjectInline, independent: true},
147150
},
148151
layouts: {
149152
row: Row,
@@ -246,6 +249,7 @@ export const dynamicCardConfig: DynamicFormConfig = {
246249
object_value: {Component: ObjectValueInput, independent: true},
247250
multi_oneof: {Component: MultiOneOf, independent: true},
248251
multi_oneof_flat: {Component: MultiOneOfFlat, independent: true},
252+
inline: {Component: ObjectInline, independent: true},
249253
},
250254
layouts: {
251255
row: Row2,
@@ -341,6 +345,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
341345
object_value: {Component: ObjectValueInputView, independent: true},
342346
multi_oneof: {Component: MultiOneOfView, independent: true},
343347
multi_oneof_flat: {Component: MultiOneOfFlatView, independent: true},
348+
inline: {Component: ObjectInlineView, independent: true},
344349
},
345350
layouts: {
346351
row: ViewRow,
@@ -427,6 +432,7 @@ export const dynamicViewCardConfig: DynamicViewConfig = {
427432
object_value: {Component: ObjectValueInputView, independent: true},
428433
multi_oneof: {Component: MultiOneOfView, independent: true},
429434
multi_oneof_flat: {Component: MultiOneOfFlatView, independent: true},
435+
inline: {Component: ObjectInlineView, independent: true},
430436
},
431437
layouts: {
432438
row: ViewRow2,

src/lib/kit/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './cn';
22
export * from './common';
33
export * from './bigIntMath';
4+
export * from './objectInline';

src/lib/kit/utils/objectInline.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import {Spec, isNumberSpec, isStringSpec} from '../../core';
2+
3+
export const filterPropertiesForObjectInline = (properties: Record<string, Spec>) => {
4+
return Object.fromEntries(
5+
Object.entries(properties).filter(
6+
([, propSpec]) => isStringSpec(propSpec) || isNumberSpec(propSpec),
7+
),
8+
);
9+
};
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React from 'react';
2+
3+
import {StoryFn} from '@storybook/react';
4+
5+
import {ObjectInline as ObjectInlineBase, ObjectSpec, SpecTypes} from '../lib';
6+
7+
import {InputPreview} from './components';
8+
9+
export default {
10+
title: 'Object/Inline',
11+
component: ObjectInlineBase,
12+
};
13+
14+
const baseSpec: ObjectSpec = {
15+
type: SpecTypes.Object,
16+
properties: {
17+
type: {
18+
type: SpecTypes.String,
19+
enum: ['first', 'second', 'third'],
20+
viewSpec: {
21+
type: 'select',
22+
placeholder: 'Choose type',
23+
layout: 'transparent',
24+
layoutTitle: 'Type',
25+
},
26+
},
27+
name: {
28+
type: SpecTypes.String,
29+
viewSpec: {
30+
type: 'base',
31+
placeholder: 'Type your name',
32+
layout: 'transparent',
33+
layoutTitle: 'Name',
34+
},
35+
},
36+
},
37+
viewSpec: {
38+
type: 'inline',
39+
layout: 'row',
40+
layoutTitle: 'Candidate',
41+
},
42+
};
43+
44+
const value = {type: 'first', name: 'Foo'};
45+
46+
const excludeOptions = [
47+
'description',
48+
'viewSpec.type',
49+
'viewSpec.oneOfParams',
50+
'viewSpec.placeholder',
51+
];
52+
53+
const template = (spec: ObjectSpec = baseSpec) => {
54+
const Template: StoryFn<typeof ObjectInlineBase> = (__, {viewMode}) => (
55+
<InputPreview
56+
spec={spec}
57+
value={value}
58+
excludeOptions={excludeOptions}
59+
viewMode={viewMode}
60+
/>
61+
);
62+
63+
return Template;
64+
};
65+
66+
export const Inline = template();

0 commit comments

Comments
 (0)