@cloud-ru/uikit-product-info-row 0.8.30 → 0.9.0

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/CHANGELOG.md CHANGED
@@ -3,6 +3,17 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 0.9.0 (2025-12-12)
7
+
8
+
9
+ ### Features
10
+
11
+ * **PDS-2967:** add two columns view for InfoGroup ([ca818a4](https://gitverse.ru/cloud-ru-tech/uikit-product/commits/ca818a48ad21a28bb204342407fbcc498f505cb8))
12
+
13
+
14
+
15
+
16
+
6
17
  ## 0.8.30 (2025-12-08)
7
18
 
8
19
  ### Only dependencies have been changed
@@ -1,2 +1,2 @@
1
1
  import { DataType, InfoGroupProps } from './types';
2
- export declare function InfoGroup<T extends DataType>({ data, items, className, loading }: InfoGroupProps<T>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function InfoGroup<T extends DataType>({ data, items, className, loading, columns, width, }: InfoGroupProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -10,17 +10,30 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  }
11
11
  return t;
12
12
  };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
13
16
  Object.defineProperty(exports, "__esModule", { value: true });
14
17
  exports.InfoGroup = InfoGroup;
15
18
  const jsx_runtime_1 = require("react/jsx-runtime");
19
+ const classnames_1 = __importDefault(require("classnames"));
16
20
  const InfoRow_1 = require("../InfoRow");
21
+ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
17
22
  const utils_1 = require("./utils");
18
- function InfoGroup({ data, items, className, loading }) {
23
+ function InfoGroup({ data, items, className, loading, columns = 'single', width = 'fixed', }) {
19
24
  const getContent = (0, utils_1.useGetContent)();
20
- return ((0, jsx_runtime_1.jsx)("div", { className: className, children: items.map((_a, index) => {
21
- var _b;
22
- var { label, accessorKey, render } = _a, rest = __rest(_a, ["label", "accessorKey", "render"]);
25
+ return ((0, jsx_runtime_1.jsx)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.wrapper, className), "data-columns": columns, "data-width": width, children: items.map((_a, index) => {
26
+ var { label, accessorKey, render, labelClassName, className, rowClassName } = _a, rest = __rest(_a, ["label", "accessorKey", "render", "labelClassName", "className", "rowClassName"]);
23
27
  const content = getContent({ data, render, accessorKey });
24
- return ((0, jsx_runtime_1.jsx)(InfoRow_1.InfoRow, Object.assign({ label: label, content: content, topDivider: index === 0, bottomDivider: true, loading: loading }, rest), (_b = accessorKey) !== null && _b !== void 0 ? _b : label));
28
+ const rowWidth = columns === 'double' || width === 'full' ? 'full' : 'fixed';
29
+ const showTopDivider = columns === 'double' ? index < 2 : index === 0;
30
+ return ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.infoRowWrapper, "data-width": width, children: (0, jsx_runtime_1.jsx)(InfoRow_1.InfoRow, Object.assign({ label: label, content: content, topDivider: showTopDivider, bottomDivider: true, loading: loading, width: rowWidth, labelClassName: (0, classnames_1.default)({
31
+ [styles_module_scss_1.default.infoRowLabelDoubleFixed]: width === 'fixed' && columns === 'double',
32
+ [styles_module_scss_1.default.infoRowLabelDoubleFull]: width === 'full' && columns === 'double',
33
+ }, labelClassName), className: (0, classnames_1.default)({
34
+ [styles_module_scss_1.default.contentDouble]: columns === 'double',
35
+ }, className), rowClassName: (0, classnames_1.default)({
36
+ [styles_module_scss_1.default.contentDouble]: columns === 'double',
37
+ }, rowClassName) }, rest)) }, accessorKey || label));
25
38
  }) }));
26
39
  }
@@ -0,0 +1,38 @@
1
+ .wrapper{
2
+ display:flex;
3
+ flex-direction:column;
4
+ width:100%;
5
+ }
6
+ .wrapper[data-columns=double]{
7
+ display:grid;
8
+ grid-template-columns:repeat(2, 1fr);
9
+ -moz-column-gap:48px;
10
+ column-gap:48px;
11
+ max-width:900px;
12
+ }
13
+ .wrapper[data-width=full]{
14
+ max-width:100%;
15
+ }
16
+
17
+ .infoRowWrapper[data-width=fixed]{
18
+ width:426px;
19
+ }
20
+ .infoRowWrapper[data-width=full]{
21
+ max-width:100%;
22
+ }
23
+
24
+ .infoRowLabelDoubleFixed.infoRowLabelDoubleFixed{
25
+ width:100px;
26
+ flex-shrink:0;
27
+ }
28
+
29
+ .infoRowLabelDoubleFull.infoRowLabelDoubleFull{
30
+ width:100px;
31
+ flex-grow:0.3;
32
+ flex-shrink:0;
33
+ }
34
+
35
+ .contentDouble{
36
+ height:100%;
37
+ box-sizing:border-box;
38
+ }
@@ -15,5 +15,7 @@ export type InfoGroupProps<T extends DataType> = {
15
15
  items: InfoGroupItem<T>[];
16
16
  className?: string;
17
17
  loading?: boolean;
18
+ columns?: 'single' | 'double';
19
+ width?: 'fixed' | 'full';
18
20
  };
19
21
  export {};
@@ -12,6 +12,8 @@ export type InfoRowPropsBase = {
12
12
  topDivider?: boolean;
13
13
  bottomDivider?: boolean;
14
14
  className?: string;
15
+ labelClassName?: string;
16
+ rowClassName?: string;
15
17
  content?: ReactNode;
16
18
  rowActions?: {
17
19
  first: RowActionButton;
@@ -19,8 +21,9 @@ export type InfoRowPropsBase = {
19
21
  };
20
22
  loading?: boolean;
21
23
  width?: 'fixed' | 'full';
24
+ labelWidth?: 'fixed' | 'auto';
22
25
  };
23
26
  export type InfoRowProps = WithSupportProps<InfoRowPropsBase>;
24
27
  export declare function withTip(children: ReactNode, tip?: TooltipProps | string): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
25
- export declare function InfoRow({ label, topDivider, bottomDivider, className, labelTooltip, content, rowActions, labelTruncate, loading, width, ...rest }: InfoRowProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function InfoRow({ label, topDivider, bottomDivider, className, labelTooltip, content, rowActions, labelTruncate, loading, width, labelClassName, rowClassName, labelWidth, ...rest }: InfoRowProps): import("react/jsx-runtime").JSX.Element;
26
29
  export {};
@@ -32,8 +32,8 @@ function withTip(children, tip) {
32
32
  return typeof tip === 'string' ? (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { tip: tip, children: children }) : (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, Object.assign({}, tip, { children: children }));
33
33
  }
34
34
  function InfoRow(_a) {
35
- var { label, topDivider = true, bottomDivider = true, className, labelTooltip, content, rowActions, labelTruncate = 1, loading = false, width = 'fixed' } = _a, rest = __rest(_a, ["label", "topDivider", "bottomDivider", "className", "labelTooltip", "content", "rowActions", "labelTruncate", "loading", "width"]);
36
- return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, (0, uikit_product_utils_1.extractSupportProps)(rest), { className: (0, classnames_1.default)(styles_module_scss_1.default.wrapper, className), "data-width": width, children: [topDivider && (0, jsx_runtime_1.jsx)(divider_1.Divider, { weight: 'regular' }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.infoRow, children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.labelLayout, children: [(0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, { text: label, maxLines: labelTruncate }), labelTooltip &&
35
+ var { label, topDivider = true, bottomDivider = true, className, labelTooltip, content, rowActions, labelTruncate = 1, loading = false, width = 'fixed', labelClassName, rowClassName, labelWidth } = _a, rest = __rest(_a, ["label", "topDivider", "bottomDivider", "className", "labelTooltip", "content", "rowActions", "labelTruncate", "loading", "width", "labelClassName", "rowClassName", "labelWidth"]);
36
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, (0, uikit_product_utils_1.extractSupportProps)(rest), { className: (0, classnames_1.default)(styles_module_scss_1.default.wrapper, className), "data-width": width, children: [topDivider && (0, jsx_runtime_1.jsx)(divider_1.Divider, { weight: 'light' }), (0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.infoRow, rowClassName), children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.labelLayout, labelClassName), "data-label-width": labelWidth, children: [(0, jsx_runtime_1.jsx)(truncate_string_1.TruncateString, { className: styles_module_scss_1.default.label, text: label, maxLines: labelTruncate }), labelTooltip &&
37
37
  (typeof labelTooltip === 'string' ? ((0, jsx_runtime_1.jsx)(tooltip_1.QuestionTooltip, { tip: labelTooltip, size: 'xs', placement: 'top', trigger: 'hover', tabIndex: -1 })) : ((0, jsx_runtime_1.jsx)(tooltip_1.QuestionTooltip, Object.assign({}, labelTooltip, { size: 'xs' }))))] }), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.contentLayout, children: [(0, jsx_runtime_1.jsx)(skeleton_1.SkeletonContextProvider, { loading: loading, children: (0, jsx_runtime_1.jsx)(skeleton_1.WithSkeleton, { skeleton: (0, jsx_runtime_1.jsx)(skeleton_1.SkeletonText, { width: '100%', lines: 1 }), children: (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.content, children: content }) }) }), rowActions && ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.rowActions, children: [withTip((0, jsx_runtime_1.jsx)(button_1.ButtonTonal, Object.assign({}, rowActions.first, { disabled: loading || rowActions.first.disabled, appearance: 'neutral', size: 's' })), rowActions.first.tip), rowActions.second &&
38
- withTip((0, jsx_runtime_1.jsx)(button_1.ButtonTonal, Object.assign({}, rowActions.second, { disabled: loading || rowActions.second.disabled, appearance: 'neutral', size: 's' })), rowActions.second.tip)] }))] })] }), bottomDivider && (0, jsx_runtime_1.jsx)(divider_1.Divider, { weight: 'regular' })] })));
38
+ withTip((0, jsx_runtime_1.jsx)(button_1.ButtonTonal, Object.assign({}, rowActions.second, { disabled: loading || rowActions.second.disabled, appearance: 'neutral', size: 's' })), rowActions.second.tip)] }))] })] }), bottomDivider && (0, jsx_runtime_1.jsx)(divider_1.Divider, { weight: 'light' })] })));
39
39
  }
@@ -1,5 +1,6 @@
1
1
  .wrapper{
2
2
  width:calc(200px + var(--dimension-3m, 24px) + 496px);
3
+ min-height:40px;
3
4
  }
4
5
  .wrapper[data-width=full]{
5
6
  width:100%;
@@ -11,6 +12,7 @@
11
12
  -moz-column-gap:var(--dimension-3m, 24px);
12
13
  column-gap:var(--dimension-3m, 24px);
13
14
  width:100%;
15
+ min-height:32px;
14
16
  align-items:center;
15
17
  }
16
18
 
@@ -31,6 +33,13 @@
31
33
  justify-content:flex-start;
32
34
  height:100%;
33
35
  }
36
+ .labelLayout[data-label-width=auto]{
37
+ width:auto;
38
+ }
39
+
40
+ .label{
41
+ color:var(--sys-neutral-text-support, #6d707f);
42
+ }
34
43
 
35
44
  .contentLayout{
36
45
  position:relative;
@@ -1,2 +1,2 @@
1
1
  import { DataType, InfoGroupProps } from './types';
2
- export declare function InfoGroup<T extends DataType>({ data, items, className, loading }: InfoGroupProps<T>): import("react/jsx-runtime").JSX.Element;
2
+ export declare function InfoGroup<T extends DataType>({ data, items, className, loading, columns, width, }: InfoGroupProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -10,14 +10,24 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
+ import cn from 'classnames';
13
14
  import { InfoRow } from '../InfoRow';
15
+ import styles from './styles.module.css';
14
16
  import { useGetContent } from './utils';
15
- export function InfoGroup({ data, items, className, loading }) {
17
+ export function InfoGroup({ data, items, className, loading, columns = 'single', width = 'fixed', }) {
16
18
  const getContent = useGetContent();
17
- return (_jsx("div", { className: className, children: items.map((_a, index) => {
18
- var _b;
19
- var { label, accessorKey, render } = _a, rest = __rest(_a, ["label", "accessorKey", "render"]);
19
+ return (_jsx("div", { className: cn(styles.wrapper, className), "data-columns": columns, "data-width": width, children: items.map((_a, index) => {
20
+ var { label, accessorKey, render, labelClassName, className, rowClassName } = _a, rest = __rest(_a, ["label", "accessorKey", "render", "labelClassName", "className", "rowClassName"]);
20
21
  const content = getContent({ data, render, accessorKey });
21
- return (_jsx(InfoRow, Object.assign({ label: label, content: content, topDivider: index === 0, bottomDivider: true, loading: loading }, rest), (_b = accessorKey) !== null && _b !== void 0 ? _b : label));
22
+ const rowWidth = columns === 'double' || width === 'full' ? 'full' : 'fixed';
23
+ const showTopDivider = columns === 'double' ? index < 2 : index === 0;
24
+ return (_jsx("div", { className: styles.infoRowWrapper, "data-width": width, children: _jsx(InfoRow, Object.assign({ label: label, content: content, topDivider: showTopDivider, bottomDivider: true, loading: loading, width: rowWidth, labelClassName: cn({
25
+ [styles.infoRowLabelDoubleFixed]: width === 'fixed' && columns === 'double',
26
+ [styles.infoRowLabelDoubleFull]: width === 'full' && columns === 'double',
27
+ }, labelClassName), className: cn({
28
+ [styles.contentDouble]: columns === 'double',
29
+ }, className), rowClassName: cn({
30
+ [styles.contentDouble]: columns === 'double',
31
+ }, rowClassName) }, rest)) }, accessorKey || label));
22
32
  }) }));
23
33
  }
@@ -0,0 +1,38 @@
1
+ .wrapper{
2
+ display:flex;
3
+ flex-direction:column;
4
+ width:100%;
5
+ }
6
+ .wrapper[data-columns=double]{
7
+ display:grid;
8
+ grid-template-columns:repeat(2, 1fr);
9
+ -moz-column-gap:48px;
10
+ column-gap:48px;
11
+ max-width:900px;
12
+ }
13
+ .wrapper[data-width=full]{
14
+ max-width:100%;
15
+ }
16
+
17
+ .infoRowWrapper[data-width=fixed]{
18
+ width:426px;
19
+ }
20
+ .infoRowWrapper[data-width=full]{
21
+ max-width:100%;
22
+ }
23
+
24
+ .infoRowLabelDoubleFixed.infoRowLabelDoubleFixed{
25
+ width:100px;
26
+ flex-shrink:0;
27
+ }
28
+
29
+ .infoRowLabelDoubleFull.infoRowLabelDoubleFull{
30
+ width:100px;
31
+ flex-grow:0.3;
32
+ flex-shrink:0;
33
+ }
34
+
35
+ .contentDouble{
36
+ height:100%;
37
+ box-sizing:border-box;
38
+ }
@@ -15,5 +15,7 @@ export type InfoGroupProps<T extends DataType> = {
15
15
  items: InfoGroupItem<T>[];
16
16
  className?: string;
17
17
  loading?: boolean;
18
+ columns?: 'single' | 'double';
19
+ width?: 'fixed' | 'full';
18
20
  };
19
21
  export {};
@@ -12,6 +12,8 @@ export type InfoRowPropsBase = {
12
12
  topDivider?: boolean;
13
13
  bottomDivider?: boolean;
14
14
  className?: string;
15
+ labelClassName?: string;
16
+ rowClassName?: string;
15
17
  content?: ReactNode;
16
18
  rowActions?: {
17
19
  first: RowActionButton;
@@ -19,8 +21,9 @@ export type InfoRowPropsBase = {
19
21
  };
20
22
  loading?: boolean;
21
23
  width?: 'fixed' | 'full';
24
+ labelWidth?: 'fixed' | 'auto';
22
25
  };
23
26
  export type InfoRowProps = WithSupportProps<InfoRowPropsBase>;
24
27
  export declare function withTip(children: ReactNode, tip?: TooltipProps | string): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
25
- export declare function InfoRow({ label, topDivider, bottomDivider, className, labelTooltip, content, rowActions, labelTruncate, loading, width, ...rest }: InfoRowProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function InfoRow({ label, topDivider, bottomDivider, className, labelTooltip, content, rowActions, labelTruncate, loading, width, labelClassName, rowClassName, labelWidth, ...rest }: InfoRowProps): import("react/jsx-runtime").JSX.Element;
26
29
  export {};
@@ -25,8 +25,8 @@ export function withTip(children, tip) {
25
25
  return typeof tip === 'string' ? _jsx(Tooltip, { tip: tip, children: children }) : _jsx(Tooltip, Object.assign({}, tip, { children: children }));
26
26
  }
27
27
  export function InfoRow(_a) {
28
- var { label, topDivider = true, bottomDivider = true, className, labelTooltip, content, rowActions, labelTruncate = 1, loading = false, width = 'fixed' } = _a, rest = __rest(_a, ["label", "topDivider", "bottomDivider", "className", "labelTooltip", "content", "rowActions", "labelTruncate", "loading", "width"]);
29
- return (_jsxs("div", Object.assign({}, extractSupportProps(rest), { className: cn(styles.wrapper, className), "data-width": width, children: [topDivider && _jsx(Divider, { weight: 'regular' }), _jsxs("div", { className: styles.infoRow, children: [_jsxs("div", { className: styles.labelLayout, children: [_jsx(TruncateString, { text: label, maxLines: labelTruncate }), labelTooltip &&
28
+ var { label, topDivider = true, bottomDivider = true, className, labelTooltip, content, rowActions, labelTruncate = 1, loading = false, width = 'fixed', labelClassName, rowClassName, labelWidth } = _a, rest = __rest(_a, ["label", "topDivider", "bottomDivider", "className", "labelTooltip", "content", "rowActions", "labelTruncate", "loading", "width", "labelClassName", "rowClassName", "labelWidth"]);
29
+ return (_jsxs("div", Object.assign({}, extractSupportProps(rest), { className: cn(styles.wrapper, className), "data-width": width, children: [topDivider && _jsx(Divider, { weight: 'light' }), _jsxs("div", { className: cn(styles.infoRow, rowClassName), children: [_jsxs("div", { className: cn(styles.labelLayout, labelClassName), "data-label-width": labelWidth, children: [_jsx(TruncateString, { className: styles.label, text: label, maxLines: labelTruncate }), labelTooltip &&
30
30
  (typeof labelTooltip === 'string' ? (_jsx(QuestionTooltip, { tip: labelTooltip, size: 'xs', placement: 'top', trigger: 'hover', tabIndex: -1 })) : (_jsx(QuestionTooltip, Object.assign({}, labelTooltip, { size: 'xs' }))))] }), _jsxs("div", { className: styles.contentLayout, children: [_jsx(SkeletonContextProvider, { loading: loading, children: _jsx(WithSkeleton, { skeleton: _jsx(SkeletonText, { width: '100%', lines: 1 }), children: _jsx("div", { className: styles.content, children: content }) }) }), rowActions && (_jsxs("div", { className: styles.rowActions, children: [withTip(_jsx(ButtonTonal, Object.assign({}, rowActions.first, { disabled: loading || rowActions.first.disabled, appearance: 'neutral', size: 's' })), rowActions.first.tip), rowActions.second &&
31
- withTip(_jsx(ButtonTonal, Object.assign({}, rowActions.second, { disabled: loading || rowActions.second.disabled, appearance: 'neutral', size: 's' })), rowActions.second.tip)] }))] })] }), bottomDivider && _jsx(Divider, { weight: 'regular' })] })));
31
+ withTip(_jsx(ButtonTonal, Object.assign({}, rowActions.second, { disabled: loading || rowActions.second.disabled, appearance: 'neutral', size: 's' })), rowActions.second.tip)] }))] })] }), bottomDivider && _jsx(Divider, { weight: 'light' })] })));
32
32
  }
@@ -1,5 +1,6 @@
1
1
  .wrapper{
2
2
  width:calc(200px + var(--dimension-3m, 24px) + 496px);
3
+ min-height:40px;
3
4
  }
4
5
  .wrapper[data-width=full]{
5
6
  width:100%;
@@ -11,6 +12,7 @@
11
12
  -moz-column-gap:var(--dimension-3m, 24px);
12
13
  column-gap:var(--dimension-3m, 24px);
13
14
  width:100%;
15
+ min-height:32px;
14
16
  align-items:center;
15
17
  }
16
18
 
@@ -31,6 +33,13 @@
31
33
  justify-content:flex-start;
32
34
  height:100%;
33
35
  }
36
+ .labelLayout[data-label-width=auto]{
37
+ width:auto;
38
+ }
39
+
40
+ .label{
41
+ color:var(--sys-neutral-text-support, #6d707f);
42
+ }
34
43
 
35
44
  .contentLayout{
36
45
  position:relative;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloud-ru/uikit-product-info-row",
3
3
  "title": "Info Row",
4
- "version": "0.8.30",
4
+ "version": "0.9.0",
5
5
  "sideEffects": [
6
6
  "*.css",
7
7
  "*.woff",
@@ -47,5 +47,5 @@
47
47
  "peerDependencies": {
48
48
  "@cloud-ru/uikit-product-locale": "*"
49
49
  },
50
- "gitHead": "ab61e93fe6f723c522e95a7c5540b3080de6b2de"
50
+ "gitHead": "5972121394b5b8516ee73aafb1a594100ac7c7c9"
51
51
  }
@@ -1,25 +1,58 @@
1
+ import cn from 'classnames';
2
+
1
3
  import { InfoRow } from '../InfoRow';
4
+ import styles from './styles.module.scss';
2
5
  import { DataType, InfoGroupProps } from './types';
3
6
  import { useGetContent } from './utils';
4
7
 
5
- export function InfoGroup<T extends DataType>({ data, items, className, loading }: InfoGroupProps<T>) {
8
+ export function InfoGroup<T extends DataType>({
9
+ data,
10
+ items,
11
+ className,
12
+ loading,
13
+ columns = 'single',
14
+ width = 'fixed',
15
+ }: InfoGroupProps<T>) {
6
16
  const getContent = useGetContent();
7
17
 
8
18
  return (
9
- <div className={className}>
10
- {items.map(({ label, accessorKey, render, ...rest }, index) => {
19
+ <div className={cn(styles.wrapper, className)} data-columns={columns} data-width={width}>
20
+ {items.map(({ label, accessorKey, render, labelClassName, className, rowClassName, ...rest }, index) => {
11
21
  const content = getContent<T>({ data, render, accessorKey });
22
+ const rowWidth = columns === 'double' || width === 'full' ? 'full' : 'fixed';
23
+ const showTopDivider = columns === 'double' ? index < 2 : index === 0;
12
24
 
13
25
  return (
14
- <InfoRow
15
- key={(accessorKey as string | undefined) ?? label}
16
- label={label}
17
- content={content}
18
- topDivider={index === 0}
19
- bottomDivider
20
- loading={loading}
21
- {...rest}
22
- />
26
+ <div className={styles.infoRowWrapper} data-width={width} key={(accessorKey as string) || label}>
27
+ <InfoRow
28
+ label={label}
29
+ content={content}
30
+ topDivider={showTopDivider}
31
+ bottomDivider
32
+ loading={loading}
33
+ width={rowWidth}
34
+ labelClassName={cn(
35
+ {
36
+ [styles.infoRowLabelDoubleFixed]: width === 'fixed' && columns === 'double',
37
+ [styles.infoRowLabelDoubleFull]: width === 'full' && columns === 'double',
38
+ },
39
+ labelClassName,
40
+ )}
41
+ className={cn(
42
+ {
43
+ [styles.contentDouble]: columns === 'double',
44
+ },
45
+ className,
46
+ )}
47
+ rowClassName={cn(
48
+ {
49
+ [styles.contentDouble]: columns === 'double',
50
+ },
51
+ rowClassName,
52
+ )}
53
+ {...rest}
54
+ />
55
+ </div>
23
56
  );
24
57
  })}
25
58
  </div>
@@ -0,0 +1,49 @@
1
+ @use '@sbercloud/figma-tokens-cloud-platform/build/scss/styles-theme-variables.scss';
2
+
3
+ $width: 900px;
4
+ $gap: 48px;
5
+ $info-row-width: 426px;
6
+ $label-double-min-width: 100px;
7
+
8
+ .wrapper {
9
+ display: flex;
10
+ flex-direction: column;
11
+ width: 100%;
12
+
13
+ &[data-columns='double'] {
14
+ display: grid;
15
+ grid-template-columns: repeat(2, 1fr);
16
+ column-gap: $gap;
17
+ max-width: $width;
18
+ }
19
+
20
+ &[data-width='full'] {
21
+ max-width: 100%;
22
+ }
23
+ }
24
+
25
+ .infoRowWrapper {
26
+ &[data-width='fixed'] {
27
+ width: $info-row-width;
28
+ }
29
+
30
+ &[data-width='full'] {
31
+ max-width: 100%;
32
+ }
33
+ }
34
+
35
+ .infoRowLabelDoubleFixed.infoRowLabelDoubleFixed {
36
+ width: $label-double-min-width;
37
+ flex-shrink: 0;
38
+ }
39
+
40
+ .infoRowLabelDoubleFull.infoRowLabelDoubleFull {
41
+ width: $label-double-min-width;
42
+ flex-grow: 0.3;
43
+ flex-shrink: 0;
44
+ }
45
+
46
+ .contentDouble {
47
+ height: 100%;
48
+ box-sizing: border-box;
49
+ }
@@ -21,4 +21,6 @@ export type InfoGroupProps<T extends DataType> = {
21
21
  items: InfoGroupItem<T>[];
22
22
  className?: string;
23
23
  loading?: boolean;
24
+ columns?: 'single' | 'double';
25
+ width?: 'fixed' | 'full';
24
26
  };
@@ -23,6 +23,8 @@ export type InfoRowPropsBase = {
23
23
  topDivider?: boolean;
24
24
  bottomDivider?: boolean;
25
25
  className?: string;
26
+ labelClassName?: string;
27
+ rowClassName?: string;
26
28
  content?: ReactNode;
27
29
  rowActions?: {
28
30
  first: RowActionButton;
@@ -30,6 +32,7 @@ export type InfoRowPropsBase = {
30
32
  };
31
33
  loading?: boolean;
32
34
  width?: 'fixed' | 'full';
35
+ labelWidth?: 'fixed' | 'auto';
33
36
  };
34
37
 
35
38
  export type InfoRowProps = WithSupportProps<InfoRowPropsBase>;
@@ -53,15 +56,18 @@ export function InfoRow({
53
56
  labelTruncate = 1,
54
57
  loading = false,
55
58
  width = 'fixed',
59
+ labelClassName,
60
+ rowClassName,
61
+ labelWidth,
56
62
  ...rest
57
63
  }: InfoRowProps) {
58
64
  return (
59
65
  <div {...extractSupportProps(rest)} className={cn(styles.wrapper, className)} data-width={width}>
60
- {topDivider && <Divider weight='regular' />}
66
+ {topDivider && <Divider weight='light' />}
61
67
 
62
- <div className={styles.infoRow}>
63
- <div className={styles.labelLayout}>
64
- <TruncateString text={label} maxLines={labelTruncate} />
68
+ <div className={cn(styles.infoRow, rowClassName)}>
69
+ <div className={cn(styles.labelLayout, labelClassName)} data-label-width={labelWidth}>
70
+ <TruncateString className={styles.label} text={label} maxLines={labelTruncate} />
65
71
 
66
72
  {labelTooltip &&
67
73
  (typeof labelTooltip === 'string' ? (
@@ -103,7 +109,7 @@ export function InfoRow({
103
109
  </div>
104
110
  </div>
105
111
 
106
- {bottomDivider && <Divider weight='regular' />}
112
+ {bottomDivider && <Divider weight='light' />}
107
113
  </div>
108
114
  );
109
115
  }
@@ -3,9 +3,12 @@
3
3
  $labelWidth: 200px;
4
4
  $contentWidth: 496px;
5
5
  $gap: styles-theme-variables.$dimension-3m;
6
+ $minHeight: 40px;
7
+ $minRowHeight: 32px;
6
8
 
7
9
  .wrapper {
8
10
  width: calc($labelWidth + $gap + $contentWidth);
11
+ min-height: $minHeight;
9
12
 
10
13
  &[data-width=full] {
11
14
  width: 100%;
@@ -17,6 +20,7 @@ $gap: styles-theme-variables.$dimension-3m;
17
20
  display: flex;
18
21
  column-gap: $gap;
19
22
  width: 100%;
23
+ min-height: $minRowHeight;
20
24
  align-items: center;
21
25
  }
22
26
 
@@ -30,6 +34,14 @@ $gap: styles-theme-variables.$dimension-3m;
30
34
  align-items: center;
31
35
  justify-content: flex-start;
32
36
  height: 100%;
37
+
38
+ &[data-label-width='auto'] {
39
+ width: auto;
40
+ }
41
+ }
42
+
43
+ .label {
44
+ color: styles-theme-variables.$sys-neutral-text-support;
33
45
  }
34
46
 
35
47
  .contentLayout {