@evergis/react 4.0.148 → 4.0.149

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.
@@ -35,6 +35,8 @@ export interface StructuredDataAttribute {
35
35
  resizable?: boolean;
36
36
  /** Значение переносится по словам, а не режется многоточием. */
37
37
  multiline?: boolean;
38
+ /** Значение — цвет: колонка показывает плашку, а правится палитрой. */
39
+ colorPicker?: boolean;
38
40
  /** Стиль значений колонки из конфига. */
39
41
  style?: CSSProperties;
40
42
  }
@@ -0,0 +1,12 @@
1
+ import { FC } from 'react';
2
+ import { TableCellProps } from '../types';
3
+ /**
4
+ * Колонка цвета (`colorPicker` у атрибута).
5
+ *
6
+ * Значение хранится строкой в любом из привычных видов — `hex`, `rgb`, `rgba`, — поэтому рядом со
7
+ * значением показывается плашка этого цвета, а на правку встаёт палитра.
8
+ *
9
+ * Неразбираемая строка остаётся просто текстом, без плашки: так видно, что в данных мусор, а не
10
+ * пустое значение.
11
+ */
12
+ export declare const ColorCell: FC<TableCellProps>;
@@ -18,3 +18,8 @@ export declare const TIME_FORMAT: RegExp;
18
18
  export declare const PORTAL_ROOT_SELECTOR = "#portal-root";
19
19
  /** Ниже этой ширины колонку не ужать мышью: уже неё в ячейке не остаётся места под значение. */
20
20
  export declare const MIN_COLUMN_WIDTH = 48;
21
+ /**
22
+ * Цвет, с которого палитра открывается у пустой ячейки. Своего значения там ещё нет, а `Color`
23
+ * без валидной строки не собрать.
24
+ */
25
+ export declare const DEFAULT_CELL_COLOR = "#000000";
@@ -105,4 +105,18 @@ export declare const CellField: import('styled-components').StyledComponent<"div
105
105
  * обязаны стоять на одной линии.
106
106
  */
107
107
  export declare const AttachmentsCellBox: import('styled-components').StyledComponent<"div", any, {}, never>;
108
+ /**
109
+ * Ячейка цвета: плашка или палитра слева, значение справа.
110
+ *
111
+ * Отступы те же, что у текстовой ячейки: в одном ряду с обычными колонками значения обязаны
112
+ * стоять на одной линии.
113
+ */
114
+ export declare const ColorCellBox: import('styled-components').StyledComponent<"div", any, {}, never>;
115
+ /**
116
+ * Плашка цвета. Повторяет маркер легенды графика: цвет всюду обозначается одинаково, где бы он
117
+ * ни показывался.
118
+ */
119
+ export declare const ColorSwatch: import('styled-components').StyledComponent<"div", any, {
120
+ $color: string;
121
+ }, never>;
108
122
  export declare const TableEmpty: import('styled-components').StyledComponent<"div", any, {}, never>;
@@ -518,6 +518,11 @@ export interface ConfigAttributeDescription {
518
518
  resizable?: boolean;
519
519
  /** Значение переносится на следующую строку вместо обрезки многоточием, высота строки растёт. */
520
520
  multiline?: boolean;
521
+ /**
522
+ * Строковое значение атрибута — цвет (`hex`, `rgb` или `rgba`). Показывается плашкой этого
523
+ * цвета рядом со значением, а правится палитрой вместо текстового поля.
524
+ */
525
+ colorPicker?: boolean;
521
526
  /**
522
527
  * Стиль значений колонки: семейство, размер, цвет и начертание шрифта. Своего узла-элемента
523
528
  * у колонки нет, поэтому стиль живёт прямо у описания атрибута.
package/dist/index.js CHANGED
@@ -3849,7 +3849,7 @@ const hue2rgb = (p, q, t) => {
3849
3849
  */
3850
3850
  const toHex = (value) => {
3851
3851
  const hex = Math.round(value * 255).toString(16);
3852
- return hex.padStart(2, '0');
3852
+ return hex.padStart(2, "0");
3853
3853
  };
3854
3854
  /**
3855
3855
  * Adjusts color brightness
@@ -3859,7 +3859,7 @@ const toHex = (value) => {
3859
3859
  */
3860
3860
  const adjustColor = (color, lightnessAdjustment = 5) => {
3861
3861
  // Convert hex to RGB
3862
- const hex = color.replace('#', '');
3862
+ const hex = color.replace("#", "");
3863
3863
  const r = parseInt(hex.substring(0, 2), 16) / 255;
3864
3864
  const g = parseInt(hex.substring(2, 4), 16) / 255;
3865
3865
  const b = parseInt(hex.substring(4, 6), 16) / 255;
@@ -3901,6 +3901,17 @@ const adjustColor = (color, lightnessAdjustment = 5) => {
3901
3901
  }
3902
3902
  return `#${toHex(rNew)}${toHex(gNew)}${toHex(bNew)}`;
3903
3903
  };
3904
+ const OPAQUE_ALPHA = "ff";
3905
+ /**
3906
+ * Цвет в hex: `#rrggbb`, а при неполной непрозрачности — `#rrggbbaa`.
3907
+ *
3908
+ * Полностью непрозрачная альфа отбрасывается: в значении она ничего не уточняет, а строку
3909
+ * удлиняет — и в конфиге, и в данных удобнее короткая запись.
3910
+ */
3911
+ const colorToHex = (color) => {
3912
+ const hex = color.toString("hex");
3913
+ return hex.slice(HEX_RRGGBB_LENGTH).toLowerCase() === OPAQUE_ALPHA ? hex.slice(0, HEX_RRGGBB_LENGTH) : hex;
3914
+ };
3904
3915
 
3905
3916
  const NO_CONTENT_VALUE = "—";
3906
3917
  exports.DateFormat = void 0;
@@ -8751,22 +8762,31 @@ const LinkDialogContent = styled.div.withConfig({ displayName: "LinkDialogConten
8751
8762
  padding: 1rem 0;
8752
8763
  `;
8753
8764
 
8765
+ /**
8766
+ * Заглушка недоступного изображения.
8767
+ *
8768
+ * Масштаб значка считается от размера самого превью: `font-size` контейнера приравнен к нему, а
8769
+ * бокс значка и его глиф заданы одной долей от этого размера. Раньше бокс был долей превью, а
8770
+ * глиф — фиксированным: в списке, где превью всего `1.5rem`, глиф выходил втрое крупнее своего
8771
+ * бокса и съезжал относительно квадрата.
8772
+ */
8754
8773
  const ImagePreviewError = styled.div.withConfig({ displayName: "ImagePreviewError", componentId: "sc-7cwrhm" }) `
8755
8774
  display: flex;
8756
8775
  align-items: center;
8757
8776
  justify-content: center;
8758
8777
  width: 100%;
8759
8778
  height: 100%;
8779
+ font-size: ${({ $size = GRID_TILE_SIZE }) => $size};
8760
8780
  background-color: ${({ theme }) => theme.palette.elementDark};
8761
8781
  border-radius: ${({ theme: { borderRadius: themeBorder }, borderRadius }) => borderRadius || themeBorder.smallest};
8762
8782
 
8763
8783
  ${uilibGl.Icon} {
8764
- width: 37.5%;
8765
- height: 37.5%;
8784
+ width: 0.375em;
8785
+ height: 0.375em;
8766
8786
  }
8767
8787
 
8768
8788
  ${uilibGl.Icon}:after {
8769
- font-size: 1.5rem;
8789
+ font-size: 0.375em;
8770
8790
  color: ${({ theme }) => theme.palette.textSecondary};
8771
8791
  }
8772
8792
  `;
@@ -8804,7 +8824,7 @@ const FileImagePreview = ({ link, isExternal, size, borderRadius, }) => {
8804
8824
  URL.revokeObjectURL(objectUrl);
8805
8825
  };
8806
8826
  }, [api, link, isExternal]);
8807
- return (jsxRuntime.jsxs(ImagePreviewContainer, { size: size, children: [hasError && (jsxRuntime.jsx(ImagePreviewError, { borderRadius: borderRadius, children: jsxRuntime.jsx(uilibGl.Icon, { kind: "alert" }) })), !hasError && !imageSrc && (jsxRuntime.jsx(ImagePreviewLoaderContainer, { children: jsxRuntime.jsx(uilibGl.LinearProgress, {}) })), !hasError && imageSrc && (jsxRuntime.jsx(GridImagePreview, { borderRadius: borderRadius, size: size, src: imageSrc, alt: "", onError: () => setHasError(true) }))] }));
8827
+ return (jsxRuntime.jsxs(ImagePreviewContainer, { size: size, children: [hasError && (jsxRuntime.jsx(ImagePreviewError, { borderRadius: borderRadius, "$size": size, children: jsxRuntime.jsx(uilibGl.Icon, { kind: "alert" }) })), !hasError && !imageSrc && (jsxRuntime.jsx(ImagePreviewLoaderContainer, { children: jsxRuntime.jsx(uilibGl.LinearProgress, {}) })), !hasError && imageSrc && (jsxRuntime.jsx(GridImagePreview, { borderRadius: borderRadius, size: size, src: imageSrc, alt: "", onError: () => setHasError(true) }))] }));
8808
8828
  };
8809
8829
 
8810
8830
  const AttachmentItem = ({ item, viewMode, isEdit, onPreview, onDelete, }) => {
@@ -11466,6 +11486,7 @@ const toSchemaAttribute = (params) => {
11466
11486
  width: description?.width,
11467
11487
  resizable: description?.resizable,
11468
11488
  multiline: description?.multiline,
11489
+ colorPicker: description?.colorPicker,
11469
11490
  style: description?.style,
11470
11491
  };
11471
11492
  };
@@ -15499,6 +15520,11 @@ const TIME_FORMAT = /hh:mm/;
15499
15520
  const PORTAL_ROOT_SELECTOR = "#portal-root";
15500
15521
  /** Ниже этой ширины колонку не ужать мышью: уже неё в ячейке не остаётся места под значение. */
15501
15522
  const MIN_COLUMN_WIDTH = 48;
15523
+ /**
15524
+ * Цвет, с которого палитра открывается у пустой ячейки. Своего значения там ещё нет, а `Color`
15525
+ * без валидной строки не собрать.
15526
+ */
15527
+ const DEFAULT_CELL_COLOR = "#000000";
15502
15528
 
15503
15529
  /**
15504
15530
  * Собственный бокс таблицы. Без размеров в `options` представления узел ничего не меняет:
@@ -15730,7 +15756,35 @@ const AttachmentsCellBox = styled.div.withConfig({ displayName: "AttachmentsCell
15730
15756
  gap: 0.25rem;
15731
15757
  padding: 0.375rem 0.25rem;
15732
15758
  `;
15733
- const TableEmpty = styled.div.withConfig({ displayName: "TableEmpty", componentId: "sc-dmdhrv" }) `
15759
+ /**
15760
+ * Ячейка цвета: плашка или палитра слева, значение справа.
15761
+ *
15762
+ * Отступы те же, что у текстовой ячейки: в одном ряду с обычными колонками значения обязаны
15763
+ * стоять на одной линии.
15764
+ */
15765
+ const ColorCellBox = styled.div.withConfig({ displayName: "ColorCellBox", componentId: "sc-n2zhg2" }) `
15766
+ display: flex;
15767
+ align-items: center;
15768
+ gap: 0.375rem;
15769
+ padding: 0 0.25rem;
15770
+
15771
+ ${CellText} {
15772
+ padding-left: 0;
15773
+ padding-right: 0;
15774
+ }
15775
+ `;
15776
+ /**
15777
+ * Плашка цвета. Повторяет маркер легенды графика: цвет всюду обозначается одинаково, где бы он
15778
+ * ни показывался.
15779
+ */
15780
+ const ColorSwatch = styled.div.withConfig({ displayName: "ColorSwatch", componentId: "sc-103e3cx" }) `
15781
+ flex-shrink: 0;
15782
+ width: 0.75rem;
15783
+ height: 0.75rem;
15784
+ background-color: ${({ $color }) => $color};
15785
+ border-radius: ${({ theme: { borderRadius } }) => borderRadius.tiny};
15786
+ `;
15787
+ const TableEmpty = styled.div.withConfig({ displayName: "TableEmpty", componentId: "sc-zo5yrp" }) `
15734
15788
  padding: 0.75rem 0.25rem;
15735
15789
  color: ${({ theme }) => theme.palette.textSecondary};
15736
15790
  `;
@@ -15807,6 +15861,27 @@ const AttachmentsCell = React.memo(({ attribute, row, canEdit, onChange }) => {
15807
15861
  }) }, previewIndex))] }));
15808
15862
  });
15809
15863
 
15864
+ /**
15865
+ * Колонка цвета (`colorPicker` у атрибута).
15866
+ *
15867
+ * Значение хранится строкой в любом из привычных видов — `hex`, `rgb`, `rgba`, — поэтому рядом со
15868
+ * значением показывается плашка этого цвета, а на правку встаёт палитра.
15869
+ *
15870
+ * Неразбираемая строка остаётся просто текстом, без плашки: так видно, что в данных мусор, а не
15871
+ * пустое значение.
15872
+ */
15873
+ const ColorCell = React.memo(({ attribute, row, canEdit, onChange }) => {
15874
+ const { attributeName, isEditable } = attribute;
15875
+ const value = row.properties[attributeName];
15876
+ const text = React.useMemo(() => (lodash.isNil(value) ? "" : String(value)), [value]);
15877
+ const color = React.useMemo(() => (text ? new color$1.Color(text) : null), [text]);
15878
+ const isValidColor = !!color?.isValid;
15879
+ // Те же два условия, что и у обычной ячейки: режим таблицы и разрешение самого атрибута.
15880
+ const editable = canEdit && isEditable;
15881
+ const handleChange = React.useCallback((next) => onChange(row.key, attributeName, colorToHex(next)), [attributeName, onChange, row.key]);
15882
+ return (jsxRuntime.jsxs(ColorCellBox, { children: [editable ? (jsxRuntime.jsx(uilibGl.ColorPicker, { zIndex: DASHBOARD_OVERLAY_Z_INDEX, withOpacity: true, value: isValidColor ? color : new color$1.Color(DEFAULT_CELL_COLOR), onChange: handleChange })) : (isValidColor && jsxRuntime.jsx(ColorSwatch, { "$color": text })), jsxRuntime.jsx(CellText, { title: text, children: text || jsxRuntime.jsx(CellPlaceholder, { children: "\u2014" }) })] }));
15883
+ });
15884
+
15810
15885
  /**
15811
15886
  * Значение ячейки не изменилось.
15812
15887
  *
@@ -15905,7 +15980,7 @@ const useCellEditing = () => {
15905
15980
  const TableCell = React.memo(({ attribute, row, canEdit, onChange }) => {
15906
15981
  const { t, language } = useGlobalContext();
15907
15982
  const { editing, buttonProps, editorProps } = useCellEditing();
15908
- const { attributeName, type, subType, isEditable, stringFormat, multiline } = attribute;
15983
+ const { attributeName, type, subType, isEditable, stringFormat, multiline, colorPicker } = attribute;
15909
15984
  const value = row.properties[attributeName];
15910
15985
  const handleChange = React.useCallback((next) => {
15911
15986
  // Пустые правки отбрасываем: иначе строка становилась бы «изменённой» от простого
@@ -15929,6 +16004,11 @@ const TableCell = React.memo(({ attribute, row, canEdit, onChange }) => {
15929
16004
  if (subType === api.StringSubType.Attachments) {
15930
16005
  return jsxRuntime.jsx(AttachmentsCell, { attribute: attribute, row: row, canEdit: canEdit, onChange: onChange });
15931
16006
  }
16007
+ // Цвет — тоже строка, и по типу от обычной не отличается: что она значит, говорит только
16008
+ // `colorPicker` в схеме.
16009
+ if (colorPicker) {
16010
+ return jsxRuntime.jsx(ColorCell, { attribute: attribute, row: row, canEdit: canEdit, onChange: onChange });
16011
+ }
15932
16012
  // Логическое значение и на чтение показываем галкой, а не словами «true»/«false» —
15933
16013
  // так же, как остальной дашборд рисует булевы атрибуты.
15934
16014
  if (type === api.AttributeType.Boolean) {
@@ -19816,6 +19896,7 @@ exports.buildTrackTemplate = buildTrackTemplate;
19816
19896
  exports.checkEqualOrIncludes = checkEqualOrIncludes;
19817
19897
  exports.checkIsLoading = checkIsLoading;
19818
19898
  exports.collectConfigIds = collectConfigIds;
19899
+ exports.colorToHex = colorToHex;
19819
19900
  exports.containsNodeId = containsNodeId;
19820
19901
  exports.createConfigLayer = createConfigLayer;
19821
19902
  exports.createConfigPage = createConfigPage;