Skip to content

Commit e94e2e0

Browse files
committed
feat: add column view
1 parent e7a710c commit e94e2e0

File tree

9 files changed

+264
-0
lines changed

9 files changed

+264
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
@import '../../../styles/variables.scss';
2+
3+
.#{$ns}column {
4+
margin-bottom: 15px;
5+
6+
&:last-child {
7+
margin-bottom: 0;
8+
}
9+
10+
&__first-row {
11+
min-height: 28px;
12+
display: flex;
13+
margin-bottom: auto;
14+
flex-direction: column;
15+
flex-shrink: 0;
16+
17+
&-inner {
18+
display: inline;
19+
margin-top: auto;
20+
margin-bottom: auto;
21+
}
22+
23+
&::after {
24+
content: '';
25+
width: 100%;
26+
flex-shrink: 1;
27+
}
28+
}
29+
30+
&__title {
31+
word-break: break-word;
32+
margin-right: 3px;
33+
34+
&_required {
35+
&::after {
36+
content: '*';
37+
color: var(--g-color-text-danger);
38+
}
39+
}
40+
}
41+
42+
&__note {
43+
position: relative;
44+
45+
&-inner {
46+
position: absolute;
47+
margin-top: 1px;
48+
49+
.g-help-popover {
50+
display: flex;
51+
52+
& > span {
53+
display: flex;
54+
}
55+
}
56+
}
57+
}
58+
59+
&__second-row {
60+
display: flex;
61+
flex-direction: column;
62+
flex-grow: 1;
63+
64+
&-inner {
65+
display: flex;
66+
justify-content: space-around;
67+
}
68+
}
69+
70+
&__remove-button {
71+
margin-left: 5px;
72+
}
73+
74+
&__required-mark {
75+
color: var(--g-color-text-danger);
76+
}
77+
78+
&__error-wrapper {
79+
min-width: 100%;
80+
}
81+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import React from 'react';
2+
3+
import {HelpPopover} from '@gravity-ui/components';
4+
import {TrashBin} from '@gravity-ui/icons';
5+
import {Button, Icon, Text} from '@gravity-ui/uikit';
6+
7+
import {
8+
FieldValue,
9+
LayoutProps,
10+
Spec,
11+
StringSpec,
12+
isArrayItem,
13+
isArraySpec,
14+
isObjectSpec,
15+
withGenerateButton,
16+
} from '../../../../core';
17+
import {ErrorWrapper, GenerateRandomValueButton} from '../../../components';
18+
import {block} from '../../../utils';
19+
20+
import './Column.scss';
21+
22+
const b = block('column');
23+
24+
interface ColumnProps {}
25+
26+
const ColumnBase = <T extends FieldValue, S extends Spec>({
27+
name,
28+
spec,
29+
input,
30+
meta,
31+
children,
32+
}: LayoutProps<T, undefined, undefined, S> & ColumnProps) => {
33+
const arrayItem = React.useMemo(() => isArrayItem(name), [name]);
34+
const generateButton = React.useMemo(() => withGenerateButton(spec), [spec]);
35+
36+
return (
37+
<div className={b()}>
38+
<div className={b('first-row')}>
39+
<div className={b('first-row-inner')}>
40+
<Text className={b('title', {required: spec.required})}>
41+
{spec.viewSpec.layoutTitle}
42+
</Text>
43+
{spec.viewSpec.layoutDescription ? (
44+
<span className={b('note')}>
45+
<Text className={b('note-inner')}>
46+
<HelpPopover
47+
htmlContent={spec.viewSpec.layoutDescription}
48+
placement={['bottom', 'top']}
49+
/>
50+
</Text>
51+
</span>
52+
) : null}
53+
</div>
54+
</div>
55+
<div className={b('second-row')}>
56+
<div className={b('second-row-inner')}>
57+
<ErrorWrapper
58+
name={name}
59+
meta={meta}
60+
withoutChildErrorStyles={
61+
// TODO: remove condition spec.viewSpec.type !== 'select'
62+
(isArraySpec(spec) && spec.viewSpec.type !== 'select') ||
63+
isObjectSpec(spec)
64+
}
65+
className={b('error-wrapper')}
66+
>
67+
{children}
68+
</ErrorWrapper>
69+
{generateButton ? (
70+
<GenerateRandomValueButton
71+
spec={spec as StringSpec}
72+
onChange={input.onChange as (value: string) => void}
73+
/>
74+
) : null}
75+
{arrayItem ? (
76+
<Button
77+
view="flat-secondary"
78+
className={b('remove-button')}
79+
onClick={input.onDrop}
80+
qa={`${name}-remove-item`}
81+
>
82+
<Icon data={TrashBin} size={16} />
83+
</Button>
84+
) : null}
85+
</div>
86+
</div>
87+
</div>
88+
);
89+
};
90+
91+
export const Column = <T extends FieldValue, S extends Spec>(
92+
props: LayoutProps<T, undefined, undefined, S>,
93+
) => <ColumnBase {...props} />;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Column';

src/lib/kit/components/Layouts/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export * from './AccordeonCard';
33
export * from './CardAccordeon';
44
export * from './CardSection';
55
export * from './Row';
6+
export * from './Column';
67
export * from './Section';
78
export * from './TableCell';
89
export * from './Transparent';
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
@import '../../../styles/variables.scss';
2+
@import '../../../styles/mixins.scss';
3+
4+
.#{$ns}view-column {
5+
margin-bottom: 20px;
6+
7+
&:last-child {
8+
margin-bottom: 0;
9+
}
10+
11+
&__first-row {
12+
display: flex;
13+
align-items: baseline;
14+
}
15+
16+
&__note {
17+
margin-inline-start: var(--g-spacing-half);
18+
}
19+
20+
&__second-row {
21+
& > .#{$ns}view-transparent {
22+
margin-bottom: 6px;
23+
24+
&:last-child {
25+
margin-bottom: 0;
26+
}
27+
}
28+
}
29+
30+
@include with-copy-button();
31+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
3+
import {Text} from '@gravity-ui/uikit';
4+
import {HelpPopover} from '@gravity-ui/components';
5+
6+
import {FormValue, Spec, ViewLayoutProps, useDynamicFormsCtx} from '../../../../core';
7+
import {CopyButton} from '../../../../kit';
8+
import {block, isNotEmptyValue} from '../../../utils';
9+
10+
import './ViewColumn.scss';
11+
12+
const b = block('view-column');
13+
14+
export const ViewColumn = <T extends FormValue, S extends Spec>({
15+
value,
16+
spec,
17+
children,
18+
}: ViewLayoutProps<T, S>) => {
19+
const {showLayoutDescription} = useDynamicFormsCtx();
20+
21+
if (!isNotEmptyValue(value, spec)) {
22+
return null;
23+
}
24+
25+
return (
26+
<div className={b()}>
27+
<div className={b('first-row')}>
28+
<Text color="secondary" ellipsis={true}>
29+
{spec.viewSpec.layoutTitle}
30+
</Text>
31+
{showLayoutDescription && spec.viewSpec.layoutDescription ? (
32+
<HelpPopover
33+
className={b('note')}
34+
htmlContent={spec.viewSpec.layoutDescription}
35+
placement={['bottom', 'top']}
36+
/>
37+
) : null}
38+
</div>
39+
<div className={b('second-row')}>{children}</div>
40+
<CopyButton spec={spec} value={value} />
41+
</div>
42+
);
43+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ViewColumn';

src/lib/kit/components/ViewLayouts/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export * from './ViewCardAccordeon';
33
export * from './ViewAccordeonCard';
44
export * from './ViewCardSection';
55
export * from './ViewRow';
6+
export * from './ViewColumn';
67
export * from './ViewSection';
78
export * from './ViewTableCell';
89
export * from './ViewTransparent';

src/lib/kit/constants/config.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
Checkbox,
1313
CheckboxGroup,
1414
CheckboxGroupView,
15+
Column,
1516
DateInput,
1617
DateView,
1718
FileInput,
@@ -62,6 +63,7 @@ import {
6263
ViewAccordeonCard,
6364
ViewCardAccordeon,
6465
ViewCardSection,
66+
ViewColumn,
6567
ViewGroup,
6668
ViewGroup2,
6769
ViewRow,
@@ -89,6 +91,7 @@ export const dynamicConfig: DynamicFormConfig = {
8991
layouts: {
9092
row: Row,
9193
row_verbose: RowVerbose,
94+
column: Column,
9295
accordeon: Accordeon,
9396
section: Section,
9497
section2: Section2,
@@ -112,6 +115,7 @@ export const dynamicConfig: DynamicFormConfig = {
112115
layouts: {
113116
row: Row,
114117
row_verbose: RowVerbose,
118+
column: Column,
115119
table_item: TableCell,
116120
transparent: Transparent,
117121
},
@@ -126,6 +130,7 @@ export const dynamicConfig: DynamicFormConfig = {
126130
layouts: {
127131
row: Row,
128132
row_verbose: RowVerbose,
133+
column: Column,
129134
table_item: TableCell,
130135
transparent: Transparent,
131136
},
@@ -150,6 +155,7 @@ export const dynamicConfig: DynamicFormConfig = {
150155
layouts: {
151156
row: Row,
152157
row_verbose: RowVerbose,
158+
column: Column,
153159
accordeon: Accordeon,
154160
section: Section,
155161
section2: Section2,
@@ -179,6 +185,7 @@ export const dynamicConfig: DynamicFormConfig = {
179185
layouts: {
180186
row: Row,
181187
row_verbose: RowVerbose,
188+
column: Column,
182189
table_item: TableCell,
183190
transparent: Transparent,
184191
section: Section,
@@ -205,6 +212,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
205212
layouts: {
206213
row: ViewRow,
207214
row_verbose: ViewRow,
215+
column: ViewColumn,
208216
accordeon: ViewAccordeon,
209217
section: ViewSection,
210218
section2: ViewSection2,
@@ -225,6 +233,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
225233
layouts: {
226234
row: ViewRow,
227235
row_verbose: ViewRow,
236+
column: ViewColumn,
228237
table_item: ViewTableCell,
229238
transparent: ViewTransparent,
230239
},
@@ -236,6 +245,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
236245
layouts: {
237246
row: ViewRow,
238247
row_verbose: ViewRow,
248+
column: ViewColumn,
239249
table_item: ViewTableCell,
240250
transparent: ViewTransparent,
241251
},
@@ -257,6 +267,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
257267
layouts: {
258268
row: ViewRow,
259269
row_verbose: ViewRow,
270+
column: ViewColumn,
260271
accordeon: ViewAccordeon,
261272
section: ViewSection,
262273
section2: ViewSection2,
@@ -283,6 +294,7 @@ export const dynamicViewConfig: DynamicViewConfig = {
283294
layouts: {
284295
row: ViewRow,
285296
row_verbose: ViewRow,
297+
column: ViewColumn,
286298
table_item: ViewTableCell,
287299
transparent: ViewTransparent,
288300
section: ViewSection,

0 commit comments

Comments
 (0)