@odigos/ui-kit 0.0.26 → 0.0.28

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
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.28](https://github.com/odigos-io/ui-kit/compare/ui-kit-v0.0.27...ui-kit-v0.0.28) (2025-05-19)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * state of source selection ([#118](https://github.com/odigos-io/ui-kit/issues/118)) ([7b73ae3](https://github.com/odigos-io/ui-kit/commit/7b73ae34778d6576a9a3c6645a434ae2ec4a2674))
9
+ * stream name input to include initial value, and validated as required ([#119](https://github.com/odigos-io/ui-kit/issues/119)) ([31a7f97](https://github.com/odigos-io/ui-kit/commit/31a7f9791def013cf1b99dcb36e043d6fa77021a))
10
+
11
+ ## [0.0.27](https://github.com/odigos-io/ui-kit/compare/ui-kit-v0.0.26...ui-kit-v0.0.27) (2025-05-19)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * checkbox for already configured destinations ([#117](https://github.com/odigos-io/ui-kit/issues/117)) ([1ec9ee7](https://github.com/odigos-io/ui-kit/commit/1ec9ee7b10c3fcc5ab258b5e6fdf5c0ff7b53af8))
17
+ * remove dest in setup ([#116](https://github.com/odigos-io/ui-kit/issues/116)) ([2c346c0](https://github.com/odigos-io/ui-kit/commit/2c346c02984a90bbf974cc8adb95b124e66861e8))
18
+
3
19
  ## [0.0.26](https://github.com/odigos-io/ui-kit/compare/ui-kit-v0.0.25...ui-kit-v0.0.26) (2025-05-15)
4
20
 
5
21
 
@@ -16,6 +16,7 @@ interface AutocompleteInputProps extends InputHTMLAttributes<HTMLInputElement> {
16
16
  onTextChange?: (text: string) => void;
17
17
  style?: CSSProperties;
18
18
  disabled?: boolean;
19
+ errorMessage?: string;
19
20
  }
20
21
  declare const AutocompleteInput: FC<AutocompleteInputProps>;
21
22
  export { AutocompleteInput, type AutocompleteInputProps };
package/lib/components.js CHANGED
@@ -1,19 +1,19 @@
1
- import { B as Button } from './index-C_LWKMnO.js';
2
- export { a as AutocompleteInput, b as Badge, a1 as CenterThis, C as Checkbox, c as Code, d as ConditionDetails, D as DataCard, f as DataCardFieldTypes, e as DataCardFields, g as DataTab, h as Divider, i as DocsButton, j as Drawer, l as DrawerFooter, k as DrawerHeader, m as Dropdown, E as ExtendArrow, F as FadeLoader, n as FieldError, o as FieldLabel, a0 as FlexColumn, $ as FlexRow, H as Header, I as IconButton, p as IconGroup, q as IconTitleBadge, r as IconWrapped, s as IconsNav, t as ImageControlled, u as Input, v as InputList, w as InputTable, x as InteractiveTable, K as KeyValueInputsList, M as Modal, a4 as ModalBody, y as MonitorsCheckboxes, z as MonitorsIcons, N as NavigationButtons, G as NoDataFound, J as NotificationNote, a3 as Overlay, S as ScrollX, L as SectionTitle, O as Segment, P as SelectionButton, Q as SkeletonLoader, R as Status, U as Stepper, a5 as TableContainer, a6 as TableTitleWrap, a7 as TableWrap, V as Text, W as TextArea, X as Toggle, T as ToggleCodeComponent, Y as Tooltip, Z as TraceLoader, a2 as VerticalScroll, _ as WarningModal } from './index-C_LWKMnO.js';
3
- export { C as CancelWarning, D as DeleteWarning } from './index-ByO2rgKy.js';
1
+ import { B as Button } from './index-CX75oR-h.js';
2
+ export { a as AutocompleteInput, b as Badge, a1 as CenterThis, C as Checkbox, c as Code, d as ConditionDetails, D as DataCard, f as DataCardFieldTypes, e as DataCardFields, g as DataTab, h as Divider, i as DocsButton, j as Drawer, l as DrawerFooter, k as DrawerHeader, m as Dropdown, E as ExtendArrow, F as FadeLoader, n as FieldError, o as FieldLabel, a0 as FlexColumn, $ as FlexRow, H as Header, I as IconButton, p as IconGroup, q as IconTitleBadge, r as IconWrapped, s as IconsNav, t as ImageControlled, u as Input, v as InputList, w as InputTable, x as InteractiveTable, K as KeyValueInputsList, M as Modal, a4 as ModalBody, y as MonitorsCheckboxes, z as MonitorsIcons, N as NavigationButtons, G as NoDataFound, J as NotificationNote, a3 as Overlay, S as ScrollX, L as SectionTitle, O as Segment, P as SelectionButton, Q as SkeletonLoader, R as Status, U as Stepper, a5 as TableContainer, a6 as TableTitleWrap, a7 as TableWrap, V as Text, W as TextArea, X as Toggle, T as ToggleCodeComponent, Y as Tooltip, Z as TraceLoader, a2 as VerticalScroll, _ as WarningModal } from './index-CX75oR-h.js';
3
+ export { C as CancelWarning, D as DeleteWarning } from './index-8BSRffGz.js';
4
4
  import React, { Component, createElement, createContext } from 'react';
5
5
  import Theme from './theme.js';
6
6
  import 'styled-components';
7
7
  import './index-BJxaoI0G.js';
8
8
  import './types.js';
9
9
  import './index-BZS1ijMm.js';
10
- import './index-B6FywnIf.js';
10
+ import './index-CTgLYGo-.js';
11
11
  import './index-CFnxjzaW.js';
12
12
  import './index-DGel4E-Z.js';
13
13
  import './index-DMXaEyAB.js';
14
14
  import './index-CJs4RDHU.js';
15
15
  import './index-IKusBlIE.js';
16
- import './useTransition-BPxqZqXu.js';
16
+ import './useTransition-BSKilkmZ.js';
17
17
  import 'react-dom';
18
18
 
19
19
  const ErrorBoundaryContext = createContext(null);
@@ -79,6 +79,7 @@ export declare const BUTTON_TEXTS: {
79
79
  ADD: string;
80
80
  ADD_NEW: string;
81
81
  NEW: string;
82
+ SELECT: string;
82
83
  CREATE: string;
83
84
  UPDATE: string;
84
85
  EDIT: string;
package/lib/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ACTION_OPTIONS, B as BUTTON_TEXTS, D as DISPLAY_TITLES, F as FORM_ALERTS, I as INSTRUMENTATION_RULE_OPTIONS, M as MONITORS_OPTIONS } from './index-B6FywnIf.js';
1
+ export { A as ACTION_OPTIONS, B as BUTTON_TEXTS, D as DISPLAY_TITLES, F as FORM_ALERTS, I as INSTRUMENTATION_RULE_OPTIONS, M as MONITORS_OPTIONS } from './index-CTgLYGo-.js';
2
2
  export { D as DESTINATION_CATEGORIES } from './index-Dqief9td.js';
3
3
  import './types.js';
4
4
  import './index-CFnxjzaW.js';
@@ -4,6 +4,7 @@ interface DataStreamSelectionFormProps {
4
4
  onClickSummary?: () => void;
5
5
  }
6
6
  interface DataStreamSelectionFormRef {
7
+ validateForm: () => boolean;
7
8
  getFormValues: () => {
8
9
  name: string;
9
10
  };
package/lib/containers.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle, useMemo, memo, useContext, createContext, useCallback, useLayoutEffect, Fragment } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
- import { D as DISPLAY_TITLES, A as ACTION_OPTIONS, M as MONITORS_OPTIONS, B as BUTTON_TEXTS, I as INSTRUMENTATION_RULE_OPTIONS, F as FORM_ALERTS } from './index-B6FywnIf.js';
3
+ import { D as DISPLAY_TITLES, A as ACTION_OPTIONS, M as MONITORS_OPTIONS, B as BUTTON_TEXTS, F as FORM_ALERTS, I as INSTRUMENTATION_RULE_OPTIONS } from './index-CTgLYGo-.js';
4
4
  import { ActionType, EntityTypes, StatusType, Crud, OtherStatus, NodeTypes, AddNodeTypes, EdgeTypes, FieldTypes, SignalType, CodeAttributesKeyTypes, PayloadCollectionKeyTypes, InstrumentationRuleType } from './types.js';
5
- import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, M as Modal, N as NavigationButtons, a4 as ModalBody, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, a0 as FlexColumn, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, J as NotificationNote, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-C_LWKMnO.js';
5
+ import { f as DataCardFieldTypes, o as FieldLabel, C as Checkbox, n as FieldError, u as Input, w as InputTable, K as KeyValueInputsList, v as InputList, V as Text, O as Segment, L as SectionTitle, i as DocsButton, y as MonitorsCheckboxes, W as TextArea, j as Drawer, d as ConditionDetails, D as DataCard, M as Modal, N as NavigationButtons, a4 as ModalBody, a as AutocompleteInput, h as Divider, R as Status, $ as FlexRow, Y as Tooltip, r as IconWrapped, z as MonitorsIcons, a5 as TableContainer, a6 as TableTitleWrap, q as IconTitleBadge, a7 as TableWrap, x as InteractiveTable, a1 as CenterThis, G as NoDataFound, a0 as FlexColumn, Z as TraceLoader, b as Badge, E as ExtendArrow, a2 as VerticalScroll, P as SelectionButton, B as Button, m as Dropdown, a8 as getDefaultExportFromCjs, F as FadeLoader, g as DataTab, Q as SkeletonLoader, X as Toggle, A as AddButton$1, J as NotificationNote, U as Stepper, I as IconButton, e as DataCardFields, s as IconsNav, p as IconGroup } from './index-CX75oR-h.js';
6
6
  import { h as usePendingStore, g as useNotificationStore, b as useDrawerStore, c as useEntityStore, f as useModalStore, d as useFilterStore, s as styleInject, i as useSelectedStore, e as useInstrumentStore, a as useDataStreamStore, k as getEntityId, j as useSetupStore, u as useDarkMode } from './index-DMXaEyAB.js';
7
7
  import Theme from './theme.js';
8
8
  import { i as isEmpty, s as safeJsonParse } from './index-BZS1ijMm.js';
9
9
  import { i as CheckCircledIcon, O as OdigosLogo } from './index-IKusBlIE.js';
10
10
  import { C as CrossCircledIcon, O as OdigosLogoText, a as OverviewIcon, F as FilterIcon, D as DataStreamsIcon, N as NotificationIcon, S as SlackLogo, K as KeyIcon, T as TerminalIcon } from './index-CamnKrev.js';
11
11
  import { g as getActionIcon, a as getInstrumentationRuleIcon } from './index-CFnxjzaW.js';
12
- import { u as useActionFormData, a as useClickNode, c as useDestinationFormData, b as useClickNotification, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-plxXIM0Q.js';
13
- import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-BPxqZqXu.js';
12
+ import { u as useActionFormData, a as useClickNode, c as useDestinationFormData, b as useClickNotification, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-CoaXePS_.js';
13
+ import { d as useKeyDown, e as useOnClickOutside, u as useContainerSize, b as useGenericForm, c as useInstrumentationRuleFormData, g as useTransition, f as useTimeAgo, a as useCopy } from './useTransition-BSKilkmZ.js';
14
14
  import { E as EditIcon } from './index-CWbxXTof.js';
15
15
  import { T as TrashIcon, S as SearchIcon, P as PlusIcon$1, f as CheckIcon, A as ArrowIcon, a as CopyIcon, g as CrossIcon } from './index-BJxaoI0G.js';
16
- import { D as DeleteWarning, C as CancelWarning } from './index-ByO2rgKy.js';
16
+ import { D as DeleteWarning, C as CancelWarning } from './index-8BSRffGz.js';
17
17
  import { m as mapConditions, b as getStatusIcon, c as capitalizeFirstLetter } from './index-CJs4RDHU.js';
18
18
  import { f as filterActions, i as getConditionsBooleans, n as getEntityLabel, m as getEntityIcon, v as sleep$1, p as getPlatformIcon, q as getPlatformLabel, h as formatBytes, k as getContainersIcons, r as getValueForRange, l as getDestinationIcon, u as mapExportedSignals, g as filterSourcesByStream, e as filterSources, b as filterDestinationsByStream, a as filterDestinations, c as compareCondition, d as deepClone, o as getMetricForEntity, s as getWorkloadId, j as getContainersInstrumentedCount, t as isOverTime } from './index-BfatCMWq.js';
19
19
  import { createPortal } from 'react-dom';
20
- import { N as NoteBackToSummary, E as EditButton } from './index-CWufhl9G.js';
20
+ import { N as NoteBackToSummary, E as EditButton } from './index-R9xRto5r.js';
21
21
  import { D as DESTINATION_CATEGORIES } from './index-Dqief9td.js';
22
22
  import { a6 as RulesIcon, a7 as SourcesIcon, a3 as ActionsIcon, a4 as DestinationsIcon } from './index-BRW_Nl-n.js';
23
23
  import './index-DGel4E-Z.js';
@@ -13999,19 +13999,30 @@ const DataFlowActionsMenu = ({ addEntity, onClickNewDataStream }) => {
13999
13999
  };
14000
14000
 
14001
14001
  const DataStreamSelectionForm = forwardRef(({ isModal, onClickSummary }, ref) => {
14002
- const { dataStreams } = useDataStreamStore();
14003
- const [nameInput, setNameInput] = useState('');
14002
+ const { selectedStreamName, dataStreams } = useDataStreamStore();
14003
+ const { formData, handleFormChange, formErrors, handleErrorChange } = useGenericForm({
14004
+ name: selectedStreamName,
14005
+ });
14004
14006
  useImperativeHandle(ref, () => ({
14005
- getFormValues: () => ({
14006
- name: nameInput,
14007
- }),
14007
+ validateForm: () => {
14008
+ let isValid = true;
14009
+ if (!formData['name']) {
14010
+ isValid = false;
14011
+ handleErrorChange('name', FORM_ALERTS.FIELD_IS_REQUIRED);
14012
+ }
14013
+ else {
14014
+ handleErrorChange('name', undefined);
14015
+ }
14016
+ return isValid;
14017
+ },
14018
+ getFormValues: () => formData,
14008
14019
  }));
14009
14020
  const dataStreamOptions = useMemo(() => dataStreams.map(({ name }) => ({ label: name })), [dataStreams]);
14010
14021
  return (React.createElement(ModalBody, { "$isNotModal": !isModal, "$minHeight": '70vh' },
14011
14022
  React.createElement(FlexColumn, { "$gap": 24 },
14012
14023
  onClickSummary && React.createElement(NoteBackToSummary, { onClick: onClickSummary }),
14013
14024
  React.createElement(SectionTitle, { title: DISPLAY_TITLES.NAME_YOUR_STREAM, description: DISPLAY_TITLES.STREAM_DESCRIPTION }),
14014
- React.createElement(AutocompleteInput, { placeholder: DISPLAY_TITLES.NAME_YOUR_STREAM_PLACEHOLDER, autoFocus: true, options: dataStreamOptions, defaultText: nameInput, onTextChange: setNameInput }))));
14025
+ React.createElement(AutocompleteInput, { placeholder: DISPLAY_TITLES.NAME_YOUR_STREAM_PLACEHOLDER, required: true, autoFocus: true, options: dataStreamOptions, defaultText: formData['name'], onTextChange: (v) => handleFormChange('name', v), errorMessage: formErrors['name'] }))));
14015
14026
  });
14016
14027
 
14017
14028
  const buildMonitorsList = (exportedSignals) => Object.keys(exportedSignals)
@@ -14325,19 +14336,22 @@ const ListsWrapper = styled.div `
14325
14336
  gap: 12px;
14326
14337
  `;
14327
14338
  const DestinationsList = ({ items, onSelectOption, onSelectConfigured }) => {
14339
+ const { configuredDestinationsUpdateOnly } = useSetupStore();
14328
14340
  return items.map((category) => {
14329
14341
  const isAlreadyExisting = category.name === DESTINATION_CATEGORIES['EXISTS']['TITLE'];
14330
14342
  return (React.createElement(ListsWrapper, { key: `category-${category.name}` },
14331
14343
  React.createElement(SectionTitle, { size: 'small', icon: category.icon, title: capitalizeFirstLetter(category.name), description: category.description }),
14332
14344
  category.items.map((item) => {
14345
+ // Following replaceAll() is to create a "legal" data-id (no spaces) for Cypress testing
14346
+ const key = `select-${category.name.replaceAll(' ', '')}-destination-${item.type}`;
14347
+ const isChecked = item.selected || configuredDestinationsUpdateOnly.some((dest) => dest.id === item.id);
14348
+ const monitors = Object.keys(item.supportedSignals).filter((signal) => item.supportedSignals[signal].supported);
14349
+ const onClick = isAlreadyExisting ? () => onSelectConfigured(item.id) : () => onSelectOption(item);
14333
14350
  const { icon, iconSrc } = getDestinationIcon(item.type);
14334
- return (React.createElement(DataTab, { key: `select-${category.name}-destination-${item.type}`, "data-id": `select-${category.name}-destination-${item.type}`, title: item.displayName, hoverText: 'SELECT', onClick: () => (isAlreadyExisting ? onSelectConfigured(item.id) : onSelectOption(item)), iconProps: { icon, iconSrc }, checkboxProps: {
14351
+ return (React.createElement(DataTab, { key: key, "data-id": key, title: item.displayName, hoverText: BUTTON_TEXTS.SELECT, onClick: onClick, iconProps: { icon, iconSrc }, visualProps: { monitors, monitorsWithLabels: true }, checkboxProps: {
14335
14352
  withCheckbox: isAlreadyExisting,
14336
- isChecked: item.selected,
14353
+ isChecked,
14337
14354
  onCheckboxChange: () => onSelectConfigured(item.id),
14338
- }, visualProps: {
14339
- monitors: Object.keys(item.supportedSignals).filter((signal) => item.supportedSignals[signal].supported),
14340
- monitorsWithLabels: true,
14341
14355
  } }));
14342
14356
  })));
14343
14357
  });
@@ -14480,7 +14494,7 @@ const DestinationModal = ({ isOnboarding, categories, potentialDestinations, cre
14480
14494
  });
14481
14495
  }
14482
14496
  return {
14483
- id: alreadyConfigDest?.id || formData.type,
14497
+ id: alreadyConfigDest?.id || '',
14484
14498
  name: alreadyConfigDest?.name || formData.name,
14485
14499
  dataStreamNames: alreadyConfigDest?.dataStreamNames || [],
14486
14500
  conditions: alreadyConfigDest?.conditions || [],
@@ -14589,9 +14603,9 @@ const DestinationList = ({ withDelete }) => {
14589
14603
  return (React.createElement(Container$7, null, configuredDestinations.concat(configuredDestinationsUpdateOnly).map((dest, idx) => (React.createElement(ListItem, { key: `configured-destination-${dest.destinationType.type}-${idx}`, "data-id": `configured-destination-${dest.destinationType.type}`, item: dest, isLastItem: configuredDestinations.length + configuredDestinationsUpdateOnly.length === 1, withDelete: withDelete })))));
14590
14604
  };
14591
14605
  const ListItem = ({ item, isLastItem, withDelete }) => {
14592
- const { removeConfiguredDestination } = useSetupStore();
14593
14606
  const [deleteWarning, setDeleteWarning] = useState(false);
14594
14607
  const { icon, iconSrc } = getDestinationIcon(item.destinationType.type);
14608
+ const { removeConfiguredDestination, removeConfiguredDestinationUpdateOnly } = useSetupStore();
14595
14609
  const mappedFields = useMemo(() => Object.entries(safeJsonParse(item.fields, {})).map(([k, v]) => ({ title: k, value: v })) || [], [item.fields]);
14596
14610
  return (React.createElement(React.Fragment, null,
14597
14611
  React.createElement(DataTab, { title: item.destinationType.displayName || item.name, subTitle: item.destinationType.type, iconProps: { icon, iconSrc }, visualProps: {
@@ -14604,7 +14618,14 @@ const ListItem = ({ item, isLastItem, withDelete }) => {
14604
14618
  ? () => (React.createElement(IconButton, { onClick: () => setDeleteWarning(true) },
14605
14619
  React.createElement(TrashIcon, null)))
14606
14620
  : undefined }),
14607
- withDelete && (React.createElement(DeleteWarning, { isOpen: deleteWarning, name: item.destinationType.displayName || item.name, type: EntityTypes.Destination, isLastItem: isLastItem, onApprove: () => removeConfiguredDestination(item), onDeny: () => setDeleteWarning(false) }))));
14621
+ withDelete && (React.createElement(DeleteWarning, { isOpen: deleteWarning, name: item.destinationType.displayName || item.name, type: EntityTypes.Destination, isLastItem: isLastItem, onApprove: () => {
14622
+ if (item.id) {
14623
+ removeConfiguredDestinationUpdateOnly(item);
14624
+ }
14625
+ else {
14626
+ removeConfiguredDestination(item);
14627
+ }
14628
+ }, onDeny: () => setDeleteWarning(false) }))));
14608
14629
  };
14609
14630
 
14610
14631
  const LargeAndWideAddButton = styled(Button) `
@@ -15753,10 +15774,10 @@ const SearchWrapper = styled.div `
15753
15774
  `;
15754
15775
  const SourceSelectionForm = forwardRef(({ isModal, fetchSingleNamespace, onClickSummary }, ref) => {
15755
15776
  const formState = useSourceSelectionFormData({ fetchSingleNamespace });
15756
- const { recordedInitialSources, selectedSources, getApiSourcesPayload, getApiFutureAppsPayload, searchText, setSearchText, showSelectedOnly, setShowSelectedOnly } = formState;
15777
+ const { availableSources, selectedSources, getApiSourcesPayload, getApiFutureAppsPayload, searchText, setSearchText, showSelectedOnly, setShowSelectedOnly } = formState;
15757
15778
  useImperativeHandle(ref, () => ({
15758
15779
  getFormValues: () => ({
15759
- initial: recordedInitialSources,
15780
+ initial: availableSources,
15760
15781
  apps: getApiSourcesPayload(),
15761
15782
  futureApps: getApiFutureAppsPayload(),
15762
15783
  }),
@@ -6,7 +6,7 @@ interface UseSourceFormDataParams {
6
6
  fetchSingleNamespace: FetchSingleNamespace;
7
7
  }
8
8
  export interface UseSourceSelectionFormData {
9
- recordedInitialSources: AvailableSourcesByNamespace;
9
+ availableSources: AvailableSourcesByNamespace;
10
10
  filteredNamespacesAndSources: AvailableSourcesByNamespace;
11
11
  getApiSourcesPayload: () => SourceSelectionFormData;
12
12
  getApiFutureAppsPayload: () => NamespaceSelectionFormData;
package/lib/hooks.js CHANGED
@@ -1,11 +1,11 @@
1
- export { u as useActionFormData, a as useClickNode, b as useClickNotification, c as useDestinationFormData, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-plxXIM0Q.js';
2
- export { u as useContainerSize, a as useCopy, b as useGenericForm, c as useInstrumentationRuleFormData, d as useKeyDown, e as useOnClickOutside, f as useTimeAgo, g as useTransition } from './useTransition-BPxqZqXu.js';
1
+ export { u as useActionFormData, a as useClickNode, b as useClickNotification, c as useDestinationFormData, d as useSourceFormData, e as useSourceSelectionFormData } from './useSourceSelectionFormData-CoaXePS_.js';
2
+ export { u as useContainerSize, a as useCopy, b as useGenericForm, c as useInstrumentationRuleFormData, d as useKeyDown, e as useOnClickOutside, f as useTimeAgo, g as useTransition } from './useTransition-BSKilkmZ.js';
3
3
  import './types.js';
4
4
  import 'react';
5
5
  import './index-DMXaEyAB.js';
6
6
  import 'styled-components';
7
7
  import './index-BZS1ijMm.js';
8
- import './index-B6FywnIf.js';
8
+ import './index-CTgLYGo-.js';
9
9
  import './index-CFnxjzaW.js';
10
10
  import './index-DGel4E-Z.js';
11
11
  import './theme.js';
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { _ as WarningModal } from './index-C_LWKMnO.js';
2
+ import { _ as WarningModal } from './index-CX75oR-h.js';
3
3
  import { StatusType, EntityTypes } from './types.js';
4
4
  import './index-DMXaEyAB.js';
5
5
  import 'styled-components';
@@ -206,6 +206,7 @@ const BUTTON_TEXTS = {
206
206
  ADD: 'Add',
207
207
  ADD_NEW: 'Add New',
208
208
  NEW: 'New',
209
+ SELECT: 'Select',
209
210
  CREATE: 'Create',
210
211
  UPDATE: 'Update',
211
212
  EDIT: 'Edit',
@@ -4,10 +4,10 @@ import styled, { css } from 'styled-components';
4
4
  import { M as MinusIcon, f as CheckIcon, L as ListIcon, C as CodeIcon, E as ExtendArrowIcon, c as SortArrowsIcon, a as CopyIcon, b as NotebookIcon, X as XIcon, d as EyeClosedIcon, e as EyeOpenIcon, N as NoDataIcon, g as CrossIcon, S as SearchIcon, P as PlusIcon, T as TrashIcon, A as ArrowIcon } from './index-BJxaoI0G.js';
5
5
  import { StatusType, OtherStatus, SortDirection, ProgrammingLanguages } from './types.js';
6
6
  import { s as safeJsonParse, i as isEmpty } from './index-BZS1ijMm.js';
7
- import { M as MONITORS_OPTIONS, B as BUTTON_TEXTS } from './index-B6FywnIf.js';
7
+ import { M as MONITORS_OPTIONS, B as BUTTON_TEXTS } from './index-CTgLYGo-.js';
8
8
  import { b as getStatusIcon, r as removeEmptyValuesFromObject, s as safeJsonStringify, f as flattenObjectKeys, m as mapConditions, c as capitalizeFirstLetter, g as getMonitorIcon, p as parseJsonStringToPrettyString, a as getProgrammingLanguageIcon, d as splitCamelString } from './index-CJs4RDHU.js';
9
9
  import './index-DMXaEyAB.js';
10
- import { u as useContainerSize, a as useCopy, g as useTransition, d as useKeyDown, e as useOnClickOutside } from './useTransition-BPxqZqXu.js';
10
+ import { u as useContainerSize, a as useCopy, g as useTransition, d as useKeyDown, e as useOnClickOutside } from './useTransition-BSKilkmZ.js';
11
11
  import { I as ImageErrorIcon } from './index-DGel4E-Z.js';
12
12
  import ReactDOM from 'react-dom';
13
13
  import { I as InfoIcon } from './index-IKusBlIE.js';
@@ -26,6 +26,18 @@ const Text = ({ children, color, size, weight, align, family, opacity, decoratio
26
26
  return (React.createElement(TextWrapper$2, { "$color": color, "$size": size, "$weight": weight, "$align": align, "$family": family, "$opacity": opacity, "$decoration": decoration, ...props }, children));
27
27
  };
28
28
 
29
+ const ErrorWrapper = styled.div `
30
+ padding: 4px 0 0 0;
31
+ `;
32
+ const ErrorMessage = styled(Text) `
33
+ font-size: 12px;
34
+ color: ${({ theme }) => theme.text.error};
35
+ `;
36
+ const FieldError = ({ children }) => {
37
+ return (React.createElement(ErrorWrapper, null,
38
+ React.createElement(ErrorMessage, null, children)));
39
+ };
40
+
29
41
  const AutocompleteContainer = styled.div `
30
42
  position: relative;
31
43
  width: 100%;
@@ -39,13 +51,13 @@ const InputWrapper$2 = styled.div `
39
51
  padding-left: 12px;
40
52
  transition: border-color 0.3s;
41
53
  border-radius: 32px;
42
- border: 1px solid ${({ theme }) => theme.colors.border};
54
+ border: 1px solid ${({ theme, $hasError }) => ($hasError ? theme.text.error : theme.colors.border)};
43
55
 
44
56
  &:hover {
45
- border-color: ${({ theme }) => theme.colors.secondary};
57
+ border-color: ${({ theme, $hasError }) => ($hasError ? theme.text.error_secondary : theme.colors.secondary)};
46
58
  }
47
59
  &:focus-within {
48
- border-color: ${({ theme }) => theme.colors.secondary};
60
+ border-color: ${({ theme, $hasError }) => ($hasError ? theme.text.error_secondary : theme.colors.secondary)};
49
61
  }
50
62
  `;
51
63
  const StyledInput$1 = styled.input `
@@ -146,7 +158,7 @@ const filterOptions = (optionsList, input) => {
146
158
  return acc;
147
159
  }, []);
148
160
  };
149
- const AutocompleteInput = ({ placeholder = 'Type to search...', options, selectedOption, onOptionSelect, defaultText, onTextChange, style, disabled, ...props }) => {
161
+ const AutocompleteInput = ({ placeholder = 'Type to search...', options, selectedOption, onOptionSelect, defaultText, onTextChange, style, disabled, errorMessage, ...props }) => {
150
162
  const [query, setQuery] = useState(selectedOption?.label || defaultText || '');
151
163
  const [filteredOptions, setFilteredOptions] = useState(filterOptions(options, query));
152
164
  const [showOptions, setShowOptions] = useState(false);
@@ -178,10 +190,11 @@ const AutocompleteInput = ({ placeholder = 'Type to search...', options, selecte
178
190
  return;
179
191
  };
180
192
  return (React.createElement(AutocompleteContainer, { style: style },
181
- React.createElement(InputWrapper$2, null,
193
+ React.createElement(InputWrapper$2, { "$hasError": !!errorMessage },
182
194
  Icon && React.createElement(Icon, null),
183
195
  React.createElement(StyledInput$1, { type: 'text', value: query, placeholder: placeholder, onChange: handleChange, onKeyDown: handleKeyDown, disabled: disabled, onBlur: () => !disabled && setShowOptions(false), onFocus: () => !disabled && setShowOptions(true), ...props })),
184
- showOptions && filteredOptions.length ? (React.createElement(OptionsList, null, filteredOptions.map((option) => (React.createElement(OptionItem, { key: option.type || option.label, option: option, onClick: handleOptionClick }))))) : null));
196
+ showOptions && filteredOptions.length ? (React.createElement(OptionsList, null, filteredOptions.map((option) => (React.createElement(OptionItem, { key: option.type || option.label, option: option, onClick: handleOptionClick }))))) : null,
197
+ errorMessage && React.createElement(FieldError, null, errorMessage)));
185
198
  };
186
199
  const OptionItem = ({ option, renderIcon = true, onClick }) => {
187
200
  const hasSubItems = !!option.items && option.items.length > 0;
@@ -455,18 +468,6 @@ const Popup = forwardRef(({ top, left, children }, ref) => {
455
468
  return ReactDOM.createPortal(React.createElement(PopupContainer, { ref: ref, "$top": top, "$left": left }, children), document.body);
456
469
  });
457
470
 
458
- const ErrorWrapper = styled.div `
459
- padding: 4px 0 0 0;
460
- `;
461
- const ErrorMessage = styled(Text) `
462
- font-size: 12px;
463
- color: ${({ theme }) => theme.text.error};
464
- `;
465
- const FieldError = ({ children }) => {
466
- return (React.createElement(ErrorWrapper, null,
467
- React.createElement(ErrorMessage, null, children)));
468
- };
469
-
470
471
  const Container$t = styled.div `
471
472
  display: flex;
472
473
  align-items: center;
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import Theme from './theme.js';
3
3
  import { E as EditIcon } from './index-CWbxXTof.js';
4
- import { B as BUTTON_TEXTS, D as DISPLAY_TITLES } from './index-B6FywnIf.js';
5
- import { B as Button, V as Text, J as NotificationNote } from './index-C_LWKMnO.js';
4
+ import { B as BUTTON_TEXTS, D as DISPLAY_TITLES } from './index-CTgLYGo-.js';
5
+ import { B as Button, V as Text, J as NotificationNote } from './index-CX75oR-h.js';
6
6
  import { StatusType } from './types.js';
7
7
  import './index-DMXaEyAB.js';
8
8
  import 'styled-components';
package/lib/snippets.js CHANGED
@@ -1,5 +1,5 @@
1
- export { A as AddButton } from './index-C_LWKMnO.js';
2
- export { E as EditButton, N as NoteBackToSummary } from './index-CWufhl9G.js';
1
+ export { A as AddButton } from './index-CX75oR-h.js';
2
+ export { E as EditButton, N as NoteBackToSummary } from './index-R9xRto5r.js';
3
3
  import 'react';
4
4
  import './theme.js';
5
5
  import './index-DMXaEyAB.js';
@@ -7,11 +7,11 @@ import './types.js';
7
7
  import 'styled-components';
8
8
  import './index-BJxaoI0G.js';
9
9
  import './index-BZS1ijMm.js';
10
- import './index-B6FywnIf.js';
10
+ import './index-CTgLYGo-.js';
11
11
  import './index-CFnxjzaW.js';
12
12
  import './index-DGel4E-Z.js';
13
13
  import './index-CJs4RDHU.js';
14
14
  import './index-IKusBlIE.js';
15
- import './useTransition-BPxqZqXu.js';
15
+ import './useTransition-BSKilkmZ.js';
16
16
  import 'react-dom';
17
17
  import './index-CWbxXTof.js';
@@ -3,8 +3,8 @@ import { useState, useEffect, useMemo } from 'react';
3
3
  import { g as useNotificationStore, f as useModalStore, b as useDrawerStore, c as useEntityStore, a as useDataStreamStore, j as useSetupStore } from './index-DMXaEyAB.js';
4
4
  import 'styled-components';
5
5
  import { i as isEmpty, s as safeJsonParse } from './index-BZS1ijMm.js';
6
- import { F as FORM_ALERTS } from './index-B6FywnIf.js';
7
- import { b as useGenericForm } from './useTransition-BPxqZqXu.js';
6
+ import { F as FORM_ALERTS } from './index-CTgLYGo-.js';
7
+ import { b as useGenericForm } from './useTransition-BSKilkmZ.js';
8
8
  import { g as getIdFromSseTarget } from './index-7-KCQK-x.js';
9
9
 
10
10
  const INITIAL$2 = {
@@ -373,10 +373,12 @@ const useSourceFormData = () => {
373
373
  };
374
374
 
375
375
  const mapSourceToAvailableSource = (source, selectedStreamName, selectAll) => {
376
+ const sourceIsInCurrentStream = source.dataStreamNames?.includes(selectedStreamName) || source.currentStreamName === selectedStreamName;
377
+ const selected = typeof selectAll === 'boolean' ? selectAll : sourceIsInCurrentStream ? source.selected : false;
376
378
  return {
377
379
  name: source.name,
378
380
  kind: source.kind,
379
- selected: typeof selectAll === 'boolean' ? selectAll : source.selected && source.dataStreamNames?.includes(selectedStreamName) ? source.selected : false,
381
+ selected,
380
382
  numberOfInstances: source.numberOfInstances,
381
383
  };
382
384
  };
@@ -386,18 +388,37 @@ const mapSourceToSelectedSource = (source, selectedStreamName, selectAll) => {
386
388
  currentStreamName: selectedStreamName,
387
389
  };
388
390
  };
391
+ const mergeAvailableAndSelectedSources = (available, selected, currentStreamName) => {
392
+ const payload = {};
393
+ Object.entries(available).forEach(([namespace, sources]) => {
394
+ payload[namespace] = sources.map((s) => mapSourceToSelectedSource(s, currentStreamName));
395
+ });
396
+ Object.entries(selected).forEach(([namespace, sources]) => {
397
+ sources.forEach((s) => {
398
+ const foundIdx = payload[namespace].findIndex((src) => src.name === s.name && src.kind === s.kind);
399
+ const mapped = mapSourceToSelectedSource(s, currentStreamName);
400
+ if (foundIdx !== -1) {
401
+ payload[namespace][foundIdx] = mapped;
402
+ }
403
+ else {
404
+ payload[namespace].push(mapped);
405
+ }
406
+ });
407
+ });
408
+ return payload;
409
+ };
389
410
  const useSourceSelectionFormData = (params) => {
390
411
  const { fetchSingleNamespace } = params || {};
391
412
  const { namespaces } = useEntityStore();
392
413
  const { selectedStreamName } = useDataStreamStore();
393
414
  // only for "onboarding" - get unsaved values and set to state
394
415
  // (this is to persist the values when user navigates back to this page)
395
- const { configuredSources, configuredFutureApps, availableSources } = useSetupStore();
416
+ const { configuredSources, configuredFutureApps, availableSources: availableSourcesFromStore } = useSetupStore();
396
417
  // Keeps intial values fetched from API, so we can later filter the user-specific-selections, therebey minimizing the amount of data sent to the API on "persist sources".
397
- const [recordedInitialSources, setRecordedInitialSources] = useState(availableSources);
418
+ const [availableSources, setRecordedInitialSources] = useState(availableSourcesFromStore);
398
419
  const [selectedNamespace, setSelectedNamespace] = useState('');
399
- const [selectedSources, setSelectedSources] = useState(configuredSources);
400
420
  const [selectedFutureApps, setSelectedFutureApps] = useState(configuredFutureApps);
421
+ const [selectedSources, setSelectedSources] = useState(mergeAvailableAndSelectedSources(availableSourcesFromStore, configuredSources, selectedStreamName));
401
422
  const fetchAndSetThisNamespace = (ns, selectAll) => {
402
423
  fetchSingleNamespace?.({ variables: { namespaceName: ns } }).then(({ data }) => {
403
424
  const { name, sources = [] } = data?.computePlatform?.k8sActualNamespace || {};
@@ -480,7 +501,7 @@ const useSourceSelectionFormData = (params) => {
480
501
  const payload = {};
481
502
  Object.entries(selectedSources).forEach(([namespace, sources]) => {
482
503
  sources.forEach((source) => {
483
- const foundInitial = recordedInitialSources[namespace]?.find((initialSource) => initialSource.name === source.name && initialSource.kind === source.kind);
504
+ const foundInitial = availableSources[namespace]?.find((initialSource) => initialSource.name === source.name && initialSource.kind === source.kind);
484
505
  if (foundInitial?.selected !== source.selected) {
485
506
  if (!payload[namespace])
486
507
  payload[namespace] = [];
@@ -502,7 +523,7 @@ const useSourceSelectionFormData = (params) => {
502
523
  return payload;
503
524
  };
504
525
  return {
505
- recordedInitialSources,
526
+ availableSources,
506
527
  filteredNamespacesAndSources,
507
528
  getApiSourcesPayload,
508
529
  getApiFutureAppsPayload,
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useRef, useEffect, useCallback } from 'react';
2
- import './index-B6FywnIf.js';
2
+ import './index-CTgLYGo-.js';
3
3
  import { g as useNotificationStore } from './index-DMXaEyAB.js';
4
4
  import { CodeAttributesKeyTypes, PayloadCollectionKeyTypes } from './types.js';
5
5
  import styled from 'styled-components';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odigos/ui-kit",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "author": "Odigos",
5
5
  "repository": {
6
6
  "type": "git",