@evergis/react 3.1.42 → 3.1.46

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/dist/index.js CHANGED
@@ -22,6 +22,8 @@ var MapGL = require('react-map-gl/mapbox');
22
22
  require('@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css');
23
23
  require('mapbox-gl/dist/mapbox-gl.css');
24
24
  var react = require('swiper/react');
25
+ var ReactMarkdown = require('react-markdown');
26
+ var remarkGfm = require('remark-gfm');
25
27
 
26
28
  const AddFeatureButton = ({ title, icon = "feature_add" /* , layerName, geometryType*/ }) => {
27
29
  // const [, handleAddFeature] = useFeatureCreator(layerName, geometryType);
@@ -4448,24 +4450,48 @@ const formatDataSourceCondition = ({ condition, configFilters, filters, attribut
4448
4450
  const DashboardChipsContainer = styled(uilibGl.Flex) `
4449
4451
  flex-wrap: wrap;
4450
4452
  `;
4453
+ const DefaultChipColorMixin = styled.css `
4454
+ && {
4455
+ color: ${({ theme: { palette } }) => palette.textPrimary};
4456
+ }
4457
+
4458
+ && > * {
4459
+ color: ${({ theme: { palette } }) => palette.textPrimary};
4460
+ }
4461
+
4462
+ && span[kind]:after {
4463
+ color: ${({ theme: { palette } }) => palette.icon};
4464
+ }
4465
+ `;
4466
+ const CustomChipColorMixin = styled.css `
4467
+ && {
4468
+ color: ${({ $fontColor }) => $fontColor};
4469
+ }
4470
+
4471
+ && > * {
4472
+ color: ${({ $fontColor }) => $fontColor};
4473
+ }
4474
+
4475
+ && span[kind]:after {
4476
+ color: ${({ $fontColor }) => $fontColor};
4477
+ }
4478
+ `;
4451
4479
  const DashboardChip$1 = styled(uilibGl.Chip) `
4452
4480
  margin: 0 0.25rem 0.25rem 0;
4453
4481
  background: ${({ $isDefault, $bgColor, theme: { palette } }) => $isDefault ? palette.element : $bgColor || palette.primary};
4454
4482
  border-radius: ${({ $radius, theme: { borderRadius } }) => $radius || borderRadius.medium};
4455
4483
  white-space: nowrap;
4456
4484
  font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
4457
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => $isDefault ? palette.textPrimary : $fontColor || "#fff"};
4485
+ color: ${({ theme: { palette } }) => palette.iconContrast};
4458
4486
 
4459
4487
  > * {
4460
4488
  font-size: ${({ $fontSize }) => $fontSize || "0.875rem"};
4461
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => $isDefault ? palette.textPrimary : $fontColor || "#fff"};
4462
4489
  }
4463
4490
 
4464
4491
  span[kind] {
4465
4492
  height: 0.875rem;
4466
4493
 
4467
4494
  :after {
4468
- color: ${({ $isDefault, $fontColor, theme: { palette } }) => ($isDefault ? palette.icon : $fontColor || "#fff")};
4469
4495
  font-size: 0.875rem;
4470
4496
  }
4471
4497
  }
@@ -4474,6 +4500,9 @@ const DashboardChip$1 = styled(uilibGl.Chip) `
4474
4500
  width: auto;
4475
4501
  padding: 0 0.5rem;
4476
4502
  }
4503
+
4504
+ ${({ $isDefault }) => $isDefault && DefaultChipColorMixin}
4505
+ ${({ $fontColor, $isDefault }) => !!$fontColor && !$isDefault && CustomChipColorMixin}
4477
4506
  `;
4478
4507
 
4479
4508
  const ChartLegendContainer = styled(uilibGl.Flex) `
@@ -5040,7 +5069,7 @@ const LayerGroup = ({ group, onlyMainTools }) => {
5040
5069
  if (!group) {
5041
5070
  return null;
5042
5071
  }
5043
- return (jsxRuntime.jsx(LayerGroupContainer, { visible: group.isVisible, children: jsxRuntime.jsxs(LayerGroupMain, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: group.isExpanded ? "tree_folder_open" : "tree_folder_closed", style: { color: group.clientData.color } }), jsxRuntime.jsxs(uilibGl.Description, { children: [jsxRuntime.jsx("div", { style: { wordBreak: "break-word" }, children: group?.alias || group?.name }), jsxRuntime.jsx(uilibGl.IconButton, { kind: group.isExpanded ? "reduce" : "expand", onClick: () => onToggleExpand(group.name, !group.isExpanded) })] }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(uilibGl.Flex, { flexWrap: "nowrap", p: "0 0.5rem", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: group.isVisible ? "password_show" : "password_hide", className: "feature-visible", isSelected: group.isVisible, onClick: () => onToggleVisibility(group.name, !group.isVisible) }) }), !onlyMainTools && (jsxRuntime.jsx(uilibGl.Popup, { distance: -14, isVisible: isMenuOpen, onRequestClose: toggleMenu, anchor: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconButton, { innerRef: ref, kind: "menu_vertical", onClick: toggleMenu }) })), children: jsxRuntime.jsx(uilibGl.Menu, { options: options, selectOption: selectOption }) }))] }) })] }) }));
5072
+ return (jsxRuntime.jsx(LayerGroupContainer, { visible: group.isVisible, children: jsxRuntime.jsxs(LayerGroupMain, { children: [jsxRuntime.jsx(uilibGl.Icon, { kind: group.isExpanded ? "tree_folder_opened" : "tree_folder_closed", style: { color: group.clientData.color } }), jsxRuntime.jsxs(uilibGl.Description, { children: [jsxRuntime.jsx("div", { style: { wordBreak: "break-word" }, children: group?.alias || group?.name }), jsxRuntime.jsx(uilibGl.IconButton, { kind: group.isExpanded ? "reduce" : "expand", onClick: () => onToggleExpand(group.name, !group.isExpanded) })] }), jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsxs(uilibGl.Flex, { flexWrap: "nowrap", p: "0 0.5rem", children: [jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconToggle, { kind: group.isVisible ? "password_show" : "password_hide", className: "feature-visible", isSelected: group.isVisible, onClick: () => onToggleVisibility(group.name, !group.isVisible) }) }), !onlyMainTools && (jsxRuntime.jsx(uilibGl.Popup, { distance: -14, isVisible: isMenuOpen, onRequestClose: toggleMenu, anchor: ref => (jsxRuntime.jsx(uilibGl.FlexSpan, { children: jsxRuntime.jsx(uilibGl.IconButton, { innerRef: ref, kind: "menu_vertical", onClick: toggleMenu }) })), children: jsxRuntime.jsx(uilibGl.Menu, { options: options, selectOption: selectOption }) }))] }) })] }) }));
5044
5073
  };
5045
5074
 
5046
5075
  const createTreeNode = (layer, Component, onlyMainTools) => {
@@ -6174,12 +6203,29 @@ const SvgContainer = styled.div `
6174
6203
  const ContainerIconTitle = styled(uilibGl.Flex) `
6175
6204
  align-items: center;
6176
6205
  flex-wrap: nowrap;
6206
+ flex-shrink: 1;
6207
+ flex-grow: 0;
6177
6208
  color: ${({ fontColor, theme: { palette } }) => fontColor || palette.textSecondary};
6178
6209
 
6210
+ > div {
6211
+ flex-shrink: 1;
6212
+ flex-grow: 0;
6213
+ width: auto;
6214
+ }
6215
+
6216
+ ${SvgContainer} {
6217
+ flex-shrink: 0;
6218
+ flex-grow: 0;
6219
+ margin-right: 0.5rem;
6220
+ }
6221
+
6222
+ > * {
6223
+ width: auto;
6224
+ }
6225
+
6179
6226
  svg,
6180
6227
  img,
6181
- span[kind],
6182
- ${SvgContainer} {
6228
+ span[kind] {
6183
6229
  margin-right: 0.5rem;
6184
6230
  }
6185
6231
 
@@ -7550,6 +7596,169 @@ const ElementLink = React.memo(({ type, elementConfig }) => {
7550
7596
  return link.startsWith("http") ? jsxRuntime.jsx(ExternalLink, { onClick: () => window.open(link) }) : jsxRuntime.jsx(LocalLink, { link: link });
7551
7597
  });
7552
7598
 
7599
+ const MarkdownWrapper = styled.div `
7600
+ padding: 0;
7601
+ background: transparent;
7602
+ border-radius: 0.5rem;
7603
+ font-family: 'Nunito Sans', sans-serif;
7604
+ color: ${({ theme: { palette } }) => palette.textPrimary};
7605
+
7606
+ /* Paragraphs */
7607
+ p {
7608
+ font-size: 0.875rem;
7609
+ line-height: 1rem;
7610
+ letter-spacing: 0.0052rem;
7611
+ margin: 0 0 1rem 0;
7612
+ font-weight: 400;
7613
+
7614
+ &:last-child {
7615
+ margin-bottom: 0;
7616
+ }
7617
+ }
7618
+
7619
+ /* Headings */
7620
+ h1, h2, h3, h4, h5, h6 {
7621
+ margin: 0 0 0.75rem 0;
7622
+ font-weight: 300;
7623
+ }
7624
+
7625
+ h1 {
7626
+ font-size: 1.5rem;
7627
+ line-height: 1.75rem;
7628
+ }
7629
+
7630
+ h2 {
7631
+ font-size: 1.25rem;
7632
+ line-height: 1.5rem;
7633
+ }
7634
+
7635
+ h3 {
7636
+ font-size: 1rem;
7637
+ line-height: 1.25rem;
7638
+ }
7639
+
7640
+ /* Images */
7641
+ img {
7642
+ max-width: 100%;
7643
+ height: auto;
7644
+ border-radius: 0.5rem;
7645
+ object-fit: cover;
7646
+ margin: 0.75rem 0;
7647
+ }
7648
+
7649
+ /* Links */
7650
+ a {
7651
+ color: ${({ theme: { palette } }) => palette.primary};
7652
+ text-decoration: none;
7653
+
7654
+ &:hover {
7655
+ text-decoration: underline;
7656
+ }
7657
+ }
7658
+
7659
+ /* Lists */
7660
+ ul, ol {
7661
+ margin: 0 0 1rem 0;
7662
+ padding-left: 1.25rem;
7663
+
7664
+ li {
7665
+ font-size: 0.875rem;
7666
+ line-height: 1rem;
7667
+ margin-bottom: 0.5rem;
7668
+ }
7669
+ }
7670
+
7671
+ /* Code */
7672
+ code {
7673
+ background: ${({ theme: { palette } }) => palette.element};
7674
+ padding: 0.125rem 0.375rem;
7675
+ border-radius: 0.25rem;
7676
+ font-family: monospace;
7677
+ font-size: 0.8125rem;
7678
+ }
7679
+
7680
+ pre {
7681
+ background: ${({ theme: { palette } }) => palette.element};
7682
+ padding: 0.75rem;
7683
+ border-radius: 0.25rem;
7684
+ overflow-x: auto;
7685
+ margin: 0.75rem 0;
7686
+
7687
+ code {
7688
+ background: transparent;
7689
+ padding: 0;
7690
+ }
7691
+ }
7692
+
7693
+ /* Hide horizontal rules */
7694
+ hr {
7695
+ display: none;
7696
+ }
7697
+ `;
7698
+ styled(uilibGl.Flex) `
7699
+ align-items: center;
7700
+ gap: 1rem;
7701
+ margin-top: 1rem;
7702
+ `;
7703
+ styled.span `
7704
+ display: block;
7705
+ font-size: 0.75rem;
7706
+ line-height: 0.875rem;
7707
+ opacity: 0.36;
7708
+ margin: 0 0 0.5rem 0;
7709
+ `;
7710
+ styled.div `
7711
+ width: 1.25rem;
7712
+ height: 1.25rem;
7713
+ cursor: pointer;
7714
+ transition: opacity 0.2s;
7715
+
7716
+ &:hover {
7717
+ opacity: 0.7;
7718
+ }
7719
+
7720
+ img, svg {
7721
+ width: 100%;
7722
+ height: 100%;
7723
+ display: block;
7724
+ }
7725
+ `;
7726
+ const ExpandButton = styled(uilibGl.IconButton) `
7727
+ margin-bottom: 1rem;
7728
+ `;
7729
+
7730
+ const ElementMarkdown = React.memo(({ elementConfig, type }) => {
7731
+ const { attributes } = useWidgetContext(type);
7732
+ const { t } = useGlobalContext();
7733
+ const [expanded, setExpanded] = React.useState(false);
7734
+ const { attributeName, value, options } = elementConfig || {};
7735
+ const expandLength = options?.expandLength || 0;
7736
+ // Get markdown content from:
7737
+ // 1. value (static content)
7738
+ // 2. attribute by attributeName (dynamic content from data)
7739
+ let content = value;
7740
+ if (!content && attributeName && attributes) {
7741
+ const attribute = attributes.find(attr => attr.name === attributeName);
7742
+ content = attribute?.value;
7743
+ }
7744
+ if (!content)
7745
+ return null;
7746
+ const markdownString = String(content);
7747
+ const shouldShowExpand = expandLength > 0 && markdownString.length > expandLength;
7748
+ // If expand is not needed, show full content
7749
+ if (!shouldShowExpand) {
7750
+ return (jsxRuntime.jsx(MarkdownWrapper, { children: jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: markdownString }) }));
7751
+ }
7752
+ // Truncated content for collapsed state
7753
+ const truncatedContent = markdownString.substring(0, expandLength);
7754
+ // Collapsed state
7755
+ if (!expanded) {
7756
+ return (jsxRuntime.jsxs(MarkdownWrapper, { children: [jsxRuntime.jsx(ExpandButton, { primary: true, icon: jsxRuntime.jsx(uilibGl.Expander, { isSelected: false }), onClick: () => setExpanded(true), children: t("more", { ns: "dashboard", defaultValue: "Подробнее" }) }), jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: truncatedContent })] }));
7757
+ }
7758
+ // Expanded state
7759
+ return (jsxRuntime.jsxs(MarkdownWrapper, { children: [jsxRuntime.jsx(ExpandButton, { primary: true, icon: jsxRuntime.jsx(uilibGl.Expander, { isSelected: true }), onClick: () => setExpanded(false), children: t("hide", { ns: "dashboard", defaultValue: "Свернуть" }) }), jsxRuntime.jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: markdownString })] }));
7760
+ });
7761
+
7553
7762
  const SmallPreviewContainer = styled.div `
7554
7763
  width: 100%;
7555
7764
  height: 100%;
@@ -7829,6 +8038,7 @@ const elementComponents = {
7829
8038
  camera: ElementCamera,
7830
8039
  chart: ElementChart,
7831
8040
  legend: ElementLegend,
8041
+ markdown: ElementMarkdown,
7832
8042
  };
7833
8043
 
7834
8044
  const getElementValue = ({ getDefaultContainer, ...props }) => {
@@ -8420,6 +8630,268 @@ const RangeDateFilter = ({ type, filter }) => {
8420
8630
  return (jsxRuntime.jsx(uilibGl.RangeNumberInput, { label: label || t("interval", { ns: "dashboard", defaultValue: "Интервал" }), selectedOption: { range: true }, minDate: getDate(minDate), maxDate: getDate(maxDate), value: [getDate(value[0]), getDate(value[1])], zIndex: 100, prefix: jsxRuntime.jsx(uilibGl.Icon, { kind: "date", disabled: true }), suffix: !isEmpty && !isDefault && jsxRuntime.jsx(StyledIconButton, { kind: "error", onClick: reset }), withTime: withTime, isDate: true, onChange: onChange }));
8421
8631
  };
8422
8632
 
8633
+ const getJustifyContent = (align) => {
8634
+ switch (align) {
8635
+ case "center":
8636
+ return "center";
8637
+ case "right":
8638
+ return "flex-end";
8639
+ case "left":
8640
+ default:
8641
+ return "flex-start";
8642
+ }
8643
+ };
8644
+ const ChipsContainer = styled(uilibGl.Flex) `
8645
+ flex-wrap: wrap;
8646
+ gap: 0.25rem;
8647
+ background: transparent;
8648
+ justify-content: ${({ $align }) => getJustifyContent($align)};
8649
+ `;
8650
+
8651
+ const FilterChip = styled.div `
8652
+ display: inline-flex;
8653
+ align-items: center;
8654
+ gap: 0.25rem;
8655
+ padding: 0.3125rem 0.5rem;
8656
+ height: 1.5rem;
8657
+ border-radius: 0.25rem;
8658
+ background-color: ${({ $isActive, $bgColor, theme }) => $bgColor
8659
+ ? $bgColor
8660
+ : $isActive
8661
+ ? theme.palette?.primary
8662
+ : theme.palette?.elementLight};
8663
+ color: ${({ $isActive, $textColor, theme }) => $textColor
8664
+ ? $textColor
8665
+ : $isActive
8666
+ ? theme.palette?.textContrast
8667
+ : theme.palette?.textSecondary};
8668
+ cursor: pointer;
8669
+ font-size: 0.75rem;
8670
+ line-height: 0.875rem;
8671
+ white-space: nowrap;
8672
+ flex-shrink: 0;
8673
+ transition: all 0.2s ease-in-out;
8674
+ margin: 0 0.25rem 0 0;
8675
+ box-sizing: border-box;
8676
+
8677
+ &:hover {
8678
+ background-color: ${({ $isActive, $bgColor, theme }) => $isActive
8679
+ ? $bgColor || 'inherit'
8680
+ : $bgColor || theme.palette?.elementDark};
8681
+ }
8682
+ `;
8683
+ const ChipIconWrapper = styled.span `
8684
+ display: inline-flex;
8685
+ align-items: center;
8686
+ justify-content: center;
8687
+ width: 0.875rem;
8688
+ height: 0.875rem;
8689
+ flex-shrink: 0;
8690
+
8691
+ svg, img {
8692
+ width: 100%;
8693
+ height: 100%;
8694
+ display: block;
8695
+ }
8696
+ `;
8697
+ const ChipText = styled.span `
8698
+ overflow: hidden;
8699
+ text-overflow: ellipsis;
8700
+ white-space: nowrap;
8701
+ ${({ $maxTextWidth }) => $maxTextWidth && `max-width: ${$maxTextWidth / 16}rem;`}
8702
+ `;
8703
+
8704
+ const CustomChip = ({ text, icon, color, primary, secondary, error, disabled, isActive, maxTextWidth, fontColor: customFontColor, backgroundColor: customBackgroundColor, ...props }) => {
8705
+ const theme = styled.useTheme();
8706
+ const { palette } = theme;
8707
+ // Helper to add transparency to hex color
8708
+ const addTransparency = (hex, transparency = '1f') => {
8709
+ // Ensure hex starts with #
8710
+ const cleanHex = hex.startsWith('#') ? hex : `#${hex}`;
8711
+ return `${cleanHex}${transparency}`;
8712
+ };
8713
+ // Calculate colors based on priority:
8714
+ // 1. customFontColor / customBackgroundColor (highest, from options)
8715
+ // 2. color (from attribute)
8716
+ // 3. primary/secondary/error
8717
+ // 4. default theme colors
8718
+ let bgColor;
8719
+ let textColor;
8720
+ if (isActive) {
8721
+ // Priority 1: Custom colors from options
8722
+ if (customFontColor) {
8723
+ textColor = customFontColor;
8724
+ bgColor = customBackgroundColor || addTransparency(customFontColor); // 12% opacity
8725
+ }
8726
+ // Priority 2: Color from attribute
8727
+ else if (color) {
8728
+ textColor = palette.textPrimary; // White text for active chip
8729
+ bgColor = color; // Full color without transparency
8730
+ }
8731
+ // Priority 3: Variant colors
8732
+ else if (primary) {
8733
+ bgColor = theme.message.color.success; // Green
8734
+ textColor = palette.textContrast;
8735
+ }
8736
+ else if (secondary) {
8737
+ bgColor = palette.primary;
8738
+ textColor = palette.textContrast;
8739
+ }
8740
+ else if (error) {
8741
+ bgColor = theme.message.color.warning; // Yellow
8742
+ textColor = palette.textPrimary;
8743
+ }
8744
+ // Priority 4: Default - no colors specified
8745
+ else {
8746
+ textColor = palette.primary;
8747
+ bgColor = addTransparency(palette.primary); // palette.primary + 12%
8748
+ }
8749
+ }
8750
+ else {
8751
+ // Inactive state
8752
+ if (color) {
8753
+ textColor = color; // Use color for text
8754
+ bgColor = addTransparency(color); // Uses default 1f (12%) transparency
8755
+ }
8756
+ // else: No color attribute - leave bgColor and textColor undefined
8757
+ // Styled component will use fallback for inactive: bg = rgba(0,0,0,0.06), text = palette.textSecondary
8758
+ }
8759
+ const renderIcon = React.useCallback((iconValue) => {
8760
+ if (!iconValue) {
8761
+ return null;
8762
+ }
8763
+ // If icon doesn't contain a dot and doesn't start with /sp/, it's a built-in icon from uilib-gl
8764
+ if (!iconValue.includes(".") && !iconValue.startsWith("/sp/")) {
8765
+ return jsxRuntime.jsx(uilibGl.Icon, { kind: iconValue });
8766
+ }
8767
+ // If it's an SVG file or resourceId path, use SvgImage component
8768
+ const isSvg = iconValue.endsWith(".svg") || iconValue.startsWith("/sp/resources/file/");
8769
+ if (isSvg) {
8770
+ const iconColor = textColor
8771
+ ? textColor
8772
+ : isActive
8773
+ ? palette.textContrast
8774
+ : palette.textSecondary;
8775
+ return (jsxRuntime.jsx(SvgImage, { url: iconValue, width: 14, height: 14, fontColor: iconColor }));
8776
+ }
8777
+ // Otherwise, it's a regular image
8778
+ return jsxRuntime.jsx("img", { src: iconValue, alt: "" });
8779
+ }, [isActive, textColor, palette.textContrast, palette.textSecondary]);
8780
+ return (jsxRuntime.jsxs(FilterChip, { "$isActive": isActive, "$bgColor": bgColor, "$textColor": textColor, ...props, children: [icon && jsxRuntime.jsx(ChipIconWrapper, { children: renderIcon(icon) }), jsxRuntime.jsx(ChipText, { "$maxTextWidth": maxTextWidth, children: text })] }));
8781
+ };
8782
+
8783
+ const ChipsFilter = ({ type, filter, elementConfig, }) => {
8784
+ const { filters, dataSources, changeFilters } = useWidgetContext(type);
8785
+ const { currentPage } = useWidgetPage(type);
8786
+ const theme = styled.useTheme();
8787
+ const { filters: configFilters } = currentPage;
8788
+ const { options } = elementConfig || {};
8789
+ const { align } = options || {};
8790
+ const { filterName, colorAttribute, iconAttribute, maxTextWidth, icon, fontColor, backgroundColor, } = filter.options;
8791
+ const configFilter = getConfigFilter(filterName, configFilters);
8792
+ const multiSelect = configFilter?.valueType === "array";
8793
+ // Process icon URL (resourceId or direct URL)
8794
+ const processedIcon = icon ? getResourceUrl(icon) : undefined;
8795
+ const chipOptions = React.useMemo(() => {
8796
+ if (!configFilter)
8797
+ return [];
8798
+ const dataSource = getDataSource(configFilter.relatedDataSource, dataSources);
8799
+ if (!dataSource?.features)
8800
+ return [];
8801
+ const features = dataSource.features;
8802
+ return features.map(feature => {
8803
+ const attrs = feature.attributes;
8804
+ const text = attrs[configFilter.attributeAlias || DEFAULT_ATTRIBUTE_NAME];
8805
+ const value = attrs[configFilter.attributeValue || DEFAULT_ATTRIBUTE_NAME];
8806
+ const chipIcon = iconAttribute
8807
+ ? getIconFromAttribute(attrs, iconAttribute)
8808
+ : undefined;
8809
+ const chipColor = colorAttribute
8810
+ ? getColorFromAttribute(attrs, colorAttribute, theme)
8811
+ : undefined;
8812
+ return {
8813
+ text,
8814
+ value,
8815
+ color: chipColor,
8816
+ icon: chipIcon,
8817
+ };
8818
+ });
8819
+ }, [configFilter, dataSources, colorAttribute, iconAttribute, theme]);
8820
+ const isChipActive = React.useCallback((chipValue) => {
8821
+ const currentValue = filters?.[filterName]?.value;
8822
+ if (currentValue === undefined) {
8823
+ return checkEqualOrIncludes(configFilter?.defaultValue, chipValue);
8824
+ }
8825
+ return checkEqualOrIncludes(currentValue, chipValue);
8826
+ }, [filters, filterName, configFilter]);
8827
+ const handleChipClick = React.useCallback((chipValue) => {
8828
+ const currentValue = filters?.[filterName]?.value;
8829
+ let newValue;
8830
+ if (multiSelect) {
8831
+ const currentArray = Array.isArray(currentValue)
8832
+ ? currentValue
8833
+ : currentValue
8834
+ ? [currentValue]
8835
+ : [];
8836
+ const valueIndex = currentArray.indexOf(chipValue);
8837
+ if (valueIndex >= 0) {
8838
+ const filtered = currentArray.filter(v => v !== chipValue);
8839
+ if (filtered.length === 0) {
8840
+ newValue = configFilter?.defaultValue || null;
8841
+ }
8842
+ else {
8843
+ newValue = filtered;
8844
+ }
8845
+ }
8846
+ else {
8847
+ newValue = [...currentArray, chipValue];
8848
+ }
8849
+ }
8850
+ else {
8851
+ if (currentValue === chipValue) {
8852
+ newValue = configFilter?.defaultValue || null;
8853
+ }
8854
+ else {
8855
+ newValue = chipValue;
8856
+ }
8857
+ }
8858
+ changeFilters({
8859
+ [filterName]: { value: newValue },
8860
+ });
8861
+ }, [filters, filterName, multiSelect, changeFilters, configFilter]);
8862
+ if (!configFilter)
8863
+ return null;
8864
+ return (jsxRuntime.jsx(ChipsContainer, { "$align": align, children: chipOptions.map((chip, index) => {
8865
+ const isActive = isChipActive(chip.value);
8866
+ // Use chip.icon from attribute or fallback to static icon
8867
+ const chipIcon = chip.icon || processedIcon;
8868
+ return (jsxRuntime.jsx(CustomChip, { text: chip.text, icon: chipIcon, color: chip.color, isActive: isActive, maxTextWidth: maxTextWidth, fontColor: fontColor, backgroundColor: backgroundColor, onClick: () => handleChipClick(chip.value), title: chip.text }, index));
8869
+ }) }));
8870
+ };
8871
+ function getColorFromAttribute(option, colorAttribute, theme) {
8872
+ const value = option[colorAttribute];
8873
+ // If value is already a hex color (starts with #), return it directly
8874
+ if (value && typeof value === 'string' && value.startsWith('#')) {
8875
+ return value;
8876
+ }
8877
+ // Otherwise, map string values to theme colors
8878
+ const colorMap = {
8879
+ active: theme?.message?.color?.success,
8880
+ warning: theme?.message?.color?.warning,
8881
+ info: theme?.message?.color?.info,
8882
+ inactive: theme?.palette?.textDisabled,
8883
+ };
8884
+ return value && typeof value === 'string' ? colorMap[value.toLowerCase()] : undefined;
8885
+ }
8886
+ function getIconFromAttribute(option, iconAttribute) {
8887
+ const iconValue = option[iconAttribute];
8888
+ if (!iconValue || typeof iconValue !== 'string') {
8889
+ return undefined;
8890
+ }
8891
+ // Process through getResourceUrl to handle both URLs and resourceIds
8892
+ return getResourceUrl(iconValue);
8893
+ }
8894
+
8423
8895
  const getFilterComponent = (filterType) => {
8424
8896
  switch (filterType) {
8425
8897
  case "checkbox":
@@ -8432,6 +8904,8 @@ const getFilterComponent = (filterType) => {
8432
8904
  return RangeDateFilter;
8433
8905
  case "text":
8434
8906
  return TextFilter;
8907
+ case "chips":
8908
+ return ChipsFilter;
8435
8909
  case "dropdown":
8436
8910
  default:
8437
8911
  return DropdownFilter;
@@ -8617,7 +9091,9 @@ const getRenderElement = ({ t, config, elementConfig, attributes = [], layerInfo
8617
9091
  return formatElementValue({ t, value, elementConfig: element, attributes, wrap });
8618
9092
  };
8619
9093
 
8620
- const getResourceUrl = (url) => url ? (url.startsWith("http") ? url : `/sp/resources/file/${url}`) : "";
9094
+ const getResourceUrl = (url) => {
9095
+ return url ? (url.startsWith("http") ? url : `/sp/resources/file/${url}`) : "";
9096
+ };
8621
9097
 
8622
9098
  const getSlideshowImages = ({ element, attribute, }) => {
8623
9099
  const { defaultValue, options } = element;
@@ -10169,6 +10645,7 @@ exports.ElementIcon = ElementIcon;
10169
10645
  exports.ElementImage = ElementImage;
10170
10646
  exports.ElementLegend = ElementLegend;
10171
10647
  exports.ElementLink = ElementLink;
10648
+ exports.ElementMarkdown = ElementMarkdown;
10172
10649
  exports.ElementSlideshow = ElementSlideshow;
10173
10650
  exports.ElementSvg = ElementSvg;
10174
10651
  exports.ElementTooltip = ElementTooltip;