@integry/sdk 4.7.39 → 4.7.41

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.
Files changed (267) hide show
  1. package/dist/esm/index.csm.js +1 -1
  2. package/dist/umd/index.umd.js +1 -1
  3. package/package.json +6 -1
  4. package/.eslintignore +0 -1
  5. package/.vscode/launch.json +0 -17
  6. package/CHANGELOG_INTERNAL.md +0 -134
  7. package/README_INTERNAL.md +0 -176
  8. package/THIRD_PARTY_LICENSES +0 -525
  9. package/generateTests.js +0 -80
  10. package/jest.config.cjs +0 -10
  11. package/src/components/AddTagButton/index.ts +0 -23
  12. package/src/components/BasicSelect/index.ts +0 -123
  13. package/src/components/BasicSelect/styles.module.scss +0 -44
  14. package/src/components/Button/index.ts +0 -97
  15. package/src/components/Button/styles.module.scss +0 -152
  16. package/src/components/CheckboxGroup/Checkbox.ts +0 -104
  17. package/src/components/CheckboxGroup/index.ts +0 -190
  18. package/src/components/CheckboxGroup/styles.module.scss +0 -63
  19. package/src/components/CollapsedMenu/index.ts +0 -104
  20. package/src/components/CollapsedMenu/styles.module.scss +0 -46
  21. package/src/components/ConfigureFieldWrapper/index.ts +0 -85
  22. package/src/components/ConfigureFieldWrapper/styles.module.scss +0 -57
  23. package/src/components/EditableText/index.ts +0 -121
  24. package/src/components/EditableText/styles.module.scss +0 -38
  25. package/src/components/EditableTextArea/index.ts +0 -143
  26. package/src/components/EditableTextArea/styles.module.scss +0 -91
  27. package/src/components/ErrorMessage/index.ts +0 -16
  28. package/src/components/ErrorMessage/styles.module.scss +0 -19
  29. package/src/components/ErrorPage/index.ts +0 -42
  30. package/src/components/ErrorPage/styles.module.scss +0 -26
  31. package/src/components/Footer/index.ts +0 -41
  32. package/src/components/Footer/styles.module.scss +0 -40
  33. package/src/components/HTMLContent/index.tsx +0 -205
  34. package/src/components/HTMLContent/styles.module.scss +0 -3
  35. package/src/components/InfoBox/index.ts +0 -48
  36. package/src/components/InfoBox/styles.module.scss +0 -21
  37. package/src/components/Input/BaseInput/index.ts +0 -170
  38. package/src/components/Input/BaseInput/styles.module.scss +0 -95
  39. package/src/components/Input/DateInput/index.ts +0 -103
  40. package/src/components/Input/DateInput/styles.module.scss +0 -50
  41. package/src/components/Input/Input/index.ts +0 -225
  42. package/src/components/Input/Input/styles.module.scss +0 -16
  43. package/src/components/Input/PasswordInput/index.ts +0 -164
  44. package/src/components/Input/PasswordInput/styles.module.scss +0 -37
  45. package/src/components/Input/index.ts +0 -7
  46. package/src/components/Label/index.ts +0 -61
  47. package/src/components/Label/styles.module.scss +0 -41
  48. package/src/components/LargeLoader/index.ts +0 -25
  49. package/src/components/LargeLoader/styles.module.scss +0 -16
  50. package/src/components/Listbox/ListBoxItem.ts +0 -57
  51. package/src/components/Listbox/index.ts +0 -488
  52. package/src/components/Listbox/styles.module.scss +0 -197
  53. package/src/components/Loader/index.ts +0 -25
  54. package/src/components/Loader/styles.module.scss +0 -16
  55. package/src/components/MediaGallery/MediaGalleryModal.ts +0 -82
  56. package/src/components/MediaGallery/MediaSlider.ts +0 -76
  57. package/src/components/MediaGallery/index.ts +0 -92
  58. package/src/components/MediaGallery/styles.module.scss +0 -156
  59. package/src/components/MediaUpload/index.ts +0 -233
  60. package/src/components/MediaUpload/styles.module.scss +0 -118
  61. package/src/components/Modal/index.ts +0 -87
  62. package/src/components/Modal/styles.module.scss +0 -441
  63. package/src/components/MultipurposeField/Dropdown/ListBoxItem.tsx +0 -59
  64. package/src/components/MultipurposeField/Dropdown/index.tsx +0 -1202
  65. package/src/components/MultipurposeField/Dropdown/styles.module.scss +0 -215
  66. package/src/components/MultipurposeField/TagMenu/index.ts +0 -536
  67. package/src/components/MultipurposeField/TagMenu/styles.module.scss +0 -175
  68. package/src/components/MultipurposeField/TagOptions/index.tsx +0 -83
  69. package/src/components/MultipurposeField/TagOptions/styles.module.scss +0 -95
  70. package/src/components/MultipurposeField/index.tsx +0 -944
  71. package/src/components/MultipurposeField/styles.module.scss +0 -77
  72. package/src/components/NewModal/index.ts +0 -69
  73. package/src/components/NewModal/styles.module.scss +0 -70
  74. package/src/components/OverflowTooltip/index.tsx +0 -59
  75. package/src/components/PopUp/ConfirmationPopUp/index.ts +0 -58
  76. package/src/components/PopUp/ConfirmationPopUp/styles.module.scss +0 -49
  77. package/src/components/PopUp/SuccessPopUp/index.ts +0 -62
  78. package/src/components/PopUp/SuccessPopUp/styles.module.scss +0 -38
  79. package/src/components/RadioGroup/Radio.ts +0 -128
  80. package/src/components/RadioGroup/index.ts +0 -169
  81. package/src/components/RadioGroup/styles.module.scss +0 -81
  82. package/src/components/Search/index.ts +0 -69
  83. package/src/components/Search/styles.module.scss +0 -149
  84. package/src/components/TabBar/Tab.ts +0 -33
  85. package/src/components/TabBar/index.ts +0 -64
  86. package/src/components/TabBar/styles.module.scss +0 -43
  87. package/src/components/Tag/index.ts +0 -29
  88. package/src/components/Tag/styles.module.scss +0 -57
  89. package/src/components/TagsMenu/index.ts +0 -1697
  90. package/src/components/TagsMenu/styles.module.scss +0 -350
  91. package/src/components/TestComponent/index.ts +0 -71
  92. package/src/components/TestComponent/styles.module.scss +0 -152
  93. package/src/components/TextArea/index.ts +0 -172
  94. package/src/components/TextArea/styles.module.scss +0 -72
  95. package/src/components/TextContent/index.tsx +0 -128
  96. package/src/components/TextContent/styles.module.scss +0 -6
  97. package/src/components/ThreeDotLoader/index.ts +0 -39
  98. package/src/components/ThreeDotLoader/styles.module.scss +0 -41
  99. package/src/components/TimeInput/index.ts +0 -129
  100. package/src/components/TimeInput/styles.module.scss +0 -16
  101. package/src/components/Toggle/index.ts +0 -34
  102. package/src/components/Toggle/styles.module.scss +0 -56
  103. package/src/components/Toggle-v2/index.ts +0 -40
  104. package/src/components/Toggle-v2/styles.module.scss +0 -86
  105. package/src/components/Tooltip/index.ts +0 -271
  106. package/src/components/Tooltip/styles.module.scss +0 -105
  107. package/src/components/form/FunctionField/index.ts +0 -816
  108. package/src/components/form/FunctionField/styles.module.scss +0 -478
  109. package/src/components/form/ObjectField/__snapshots__/index.ts.test.tsx.snap +0 -3
  110. package/src/components/form/ObjectField/index.ts +0 -593
  111. package/src/components/form/ObjectField/index.ts.test.tsx +0 -213
  112. package/src/components/form/ObjectField/styles.module.scss +0 -103
  113. package/src/components/form/index.ts +0 -4
  114. package/src/contexts/AppContext.ts +0 -12
  115. package/src/declaration.d.ts +0 -7
  116. package/src/extensions/HMAC.ts +0 -25
  117. package/src/extensions/IntegryAPIError.ts +0 -19
  118. package/src/features/common/AccountDropdown/index.ts +0 -291
  119. package/src/features/common/AccountDropdown/styles.module.scss +0 -19
  120. package/src/features/common/ActionForm/index.ts +0 -2602
  121. package/src/features/common/ActionForm/styles.module.scss +0 -35
  122. package/src/features/common/AppCard/index.ts +0 -207
  123. package/src/features/common/AppCard/styles.module.scss +0 -117
  124. package/src/features/common/AppCardCompact/index.ts +0 -189
  125. package/src/features/common/AppCardCompact/styles.module.scss +0 -141
  126. package/src/features/common/AuthSelector/index.ts +0 -537
  127. package/src/features/common/AuthSelector/styles.module.scss +0 -161
  128. package/src/features/common/AuthSelectorCompact/index.ts +0 -706
  129. package/src/features/common/AuthSelectorCompact/styles.module.scss +0 -219
  130. package/src/features/common/AuthSelectorDropdown/index.ts +0 -704
  131. package/src/features/common/AuthSelectorDropdown/styles.module.scss +0 -361
  132. package/src/features/common/AuthSelectorV2/index.ts +0 -336
  133. package/src/features/common/AuthSelectorV2/styles.module.scss +0 -235
  134. package/src/features/common/DynamicField/index.ts +0 -402
  135. package/src/features/common/DynamicField/styles.module.scss +0 -266
  136. package/src/features/common/DynamicTypedField/index.ts +0 -504
  137. package/src/features/common/DynamicTypedField/styles.module.scss +0 -135
  138. package/src/features/common/FunctionForm/index.ts +0 -1095
  139. package/src/features/common/FunctionForm/styles.module.scss +0 -225
  140. package/src/features/common/MappingUI/index.ts +0 -649
  141. package/src/features/common/MappingUI/styles.module.scss +0 -121
  142. package/src/features/common/MarketplaceAppCard/index.ts +0 -279
  143. package/src/features/common/MarketplaceAppCard/styles.module.scss +0 -231
  144. package/src/features/common/MarketplaceAppCardCompact/index.ts +0 -283
  145. package/src/features/common/MarketplaceAppCardCompact/styles.module.scss +0 -255
  146. package/src/features/common/NewMappingUI/index.ts +0 -515
  147. package/src/features/common/NewMappingUI/styles.module.scss +0 -113
  148. package/src/features/common/RequestAppWidget/RequestAppModal/index.ts +0 -67
  149. package/src/features/common/RequestAppWidget/RequestAppModal/styles.module.scss +0 -23
  150. package/src/features/common/RequestAppWidget/index.ts +0 -48
  151. package/src/features/common/RequestAppWidget/request-app-form.ts +0 -89
  152. package/src/features/common/RequestAppWidget/styles.module.scss +0 -43
  153. package/src/features/common/SectionField/index.ts +0 -272
  154. package/src/features/common/SectionField/styles.module.scss +0 -67
  155. package/src/features/common/Step/index.ts +0 -827
  156. package/src/features/common/Step/styles.module.scss +0 -12
  157. package/src/features/common/StepNavigation/CollapsedSteps.ts +0 -131
  158. package/src/features/common/StepNavigation/NavItem.ts +0 -111
  159. package/src/features/common/StepNavigation/index.ts +0 -261
  160. package/src/features/common/StepNavigation/styles.module.scss +0 -117
  161. package/src/features/common/Steps/index.ts +0 -1140
  162. package/src/features/common/Steps/styles.module.scss +0 -314
  163. package/src/features/containers/AppFlowContainer/AppFlowListing/compactStyles.module.scss +0 -404
  164. package/src/features/containers/AppFlowContainer/AppFlowListing/flow-instance.tsx +0 -367
  165. package/src/features/containers/AppFlowContainer/AppFlowListing/flowCard.test.tsx +0 -58
  166. package/src/features/containers/AppFlowContainer/AppFlowListing/flowCard.tsx +0 -208
  167. package/src/features/containers/AppFlowContainer/AppFlowListing/flowCardCompact.test.tsx +0 -49
  168. package/src/features/containers/AppFlowContainer/AppFlowListing/flowCardCompact.tsx +0 -421
  169. package/src/features/containers/AppFlowContainer/AppFlowListing/flowInstanceCompact.tsx +0 -577
  170. package/src/features/containers/AppFlowContainer/AppFlowListing/index.tsx +0 -83
  171. package/src/features/containers/AppFlowContainer/AppFlowListing/styles.module.scss +0 -233
  172. package/src/features/containers/AppFlowContainer/AppFlowWrap/app-page-loader.tsx +0 -45
  173. package/src/features/containers/AppFlowContainer/AppFlowWrap/index.tsx +0 -1085
  174. package/src/features/containers/AppFlowContainer/AppFlowWrap/styles.module.scss +0 -465
  175. package/src/features/containers/AppFlowContainer/Authentication/index.ts +0 -610
  176. package/src/features/containers/AppFlowContainer/Authentication/styles.module.scss +0 -468
  177. package/src/features/containers/AppFlowContainer/index.ts +0 -114
  178. package/src/features/containers/AppPageContainer/AppPage/index.tsx +0 -262
  179. package/src/features/containers/AppPageContainer/AppPage/styles.module.scss +0 -120
  180. package/src/features/containers/AppPageContainer/IntegrationCard/index.ts +0 -165
  181. package/src/features/containers/AppPageContainer/IntegrationCard/styles.module.scss +0 -81
  182. package/src/features/containers/AppPageContainer/index.tsx +0 -93
  183. package/src/features/containers/AppPageContainer/styles.module.scss +0 -0
  184. package/src/features/containers/AppsForFlows/index.ts +0 -161
  185. package/src/features/containers/AppsForFlows/styles.module.scss +0 -280
  186. package/src/features/containers/AppsForFlowsCompact/index.ts +0 -161
  187. package/src/features/containers/AppsForFlowsCompact/styles.module.scss +0 -279
  188. package/src/features/containers/AuthSetupContainer/AppSelection.ts +0 -73
  189. package/src/features/containers/AuthSetupContainer/AuthTypeSelection.ts +0 -67
  190. package/src/features/containers/AuthSetupContainer/Footer.ts +0 -32
  191. package/src/features/containers/AuthSetupContainer/Header.ts +0 -39
  192. package/src/features/containers/AuthSetupContainer/PostAdditionPopup.ts +0 -27
  193. package/src/features/containers/AuthSetupContainer/index.ts +0 -349
  194. package/src/features/containers/AuthSetupContainer/styles.module.scss +0 -229
  195. package/src/features/containers/FlowSetupContainer/index.ts +0 -391
  196. package/src/features/containers/FlowSetupContainer/styles.module.scss +0 -18
  197. package/src/features/containers/MarkeplaceApps/index.ts +0 -583
  198. package/src/features/containers/MarkeplaceApps/styles.module.scss +0 -558
  199. package/src/features/containers/MarketplaceAppsCompact/index.ts +0 -585
  200. package/src/features/containers/MarketplaceAppsCompact/styles.module.scss +0 -563
  201. package/src/features/containers/MarketplaceAppsContainer/index.ts +0 -91
  202. package/src/features/containers/MarketplaceContainer/AppCard/index.ts +0 -91
  203. package/src/features/containers/MarketplaceContainer/AppCard/styles.module.scss +0 -66
  204. package/src/features/containers/MarketplaceContainer/AppListing/index.ts +0 -34
  205. package/src/features/containers/MarketplaceContainer/AppListing/styles.module.scss +0 -10
  206. package/src/features/containers/MarketplaceContainer/MarketplaceContentWrap/index.ts +0 -132
  207. package/src/features/containers/MarketplaceContainer/MarketplaceContentWrap/styles.module.scss +0 -117
  208. package/src/features/containers/MarketplaceContainer/index.ts +0 -242
  209. package/src/features/containers/MarketplaceContainer/styles.module.scss +0 -84
  210. package/src/features/containers/SDKContainer/index.ts +0 -817
  211. package/src/features/containers/SDKContainer/styles.module.scss +0 -266
  212. package/src/features/containers/SDKDebugContainer/index.ts +0 -137
  213. package/src/features/containers/SDKDebugContainer/styles.module.scss +0 -37
  214. package/src/features/containers/SDKFailedContainer/index.ts +0 -117
  215. package/src/features/containers/SDKFailedContainer/styles.module.scss +0 -57
  216. package/src/features/integrations/IntegrationRow/Icons.ts +0 -77
  217. package/src/features/integrations/IntegrationRow/index.ts +0 -129
  218. package/src/features/integrations/IntegrationRow/styles.module.scss +0 -62
  219. package/src/features/integrations/IntegrationsHeader/index.ts +0 -34
  220. package/src/features/integrations/IntegrationsHeader/styles.module.scss +0 -47
  221. package/src/features/integrations/IntegrationsList/index.ts +0 -252
  222. package/src/features/integrations/IntegrationsList/styles.module.scss +0 -67
  223. package/src/features/templates/Template/index.ts +0 -295
  224. package/src/features/templates/Template/styles.module.scss +0 -226
  225. package/src/features/templates/TemplatesView/index.ts +0 -368
  226. package/src/features/templates/TemplatesView/styles.module.scss +0 -71
  227. package/src/features/templates/TemplatesViewCompact/index.ts +0 -364
  228. package/src/features/templates/TemplatesViewCompact/styles.module.scss +0 -141
  229. package/src/hooks/useAutosizeTextArea.ts +0 -22
  230. package/src/hooks/useCustomRef.ts +0 -13
  231. package/src/hooks/useDebounce.ts +0 -17
  232. package/src/hooks/useElementResize.ts +0 -40
  233. package/src/hooks/useEventListener.ts +0 -42
  234. package/src/hooks/useHover.ts +0 -40
  235. package/src/hooks/useOnClickOutside.ts +0 -32
  236. package/src/index.ts +0 -2244
  237. package/src/index.umd.ts +0 -13
  238. package/src/interfaces/index.ts +0 -938
  239. package/src/modules/api/index.ts +0 -1325
  240. package/src/modules/api/responseHandler.ts +0 -38
  241. package/src/modules/event-emitter/index.ts +0 -72
  242. package/src/modules/event-emitter/runners/abstract.ts +0 -21
  243. package/src/modules/event-emitter/runners/default.ts +0 -11
  244. package/src/modules/event-emitter/runners/ntimes.ts +0 -28
  245. package/src/modules/event-emitter/types.ts +0 -34
  246. package/src/store/actionFunctions.ts +0 -1578
  247. package/src/store/index.ts +0 -17
  248. package/src/store/initialState.ts +0 -58
  249. package/src/types/index.ts +0 -320
  250. package/src/types/preact-compat.d.ts +0 -4
  251. package/src/types/store.ts +0 -366
  252. package/src/types/utils.ts +0 -19
  253. package/src/utils/ActivityOutputUtils.ts +0 -176
  254. package/src/utils/common.ts +0 -20
  255. package/src/utils/copyToClipboard.ts +0 -24
  256. package/src/utils/datetime.ts +0 -101
  257. package/src/utils/getUrlParam.ts +0 -11
  258. package/src/utils/isAuthMessage.ts +0 -16
  259. package/src/utils/isBrowser.ts +0 -1
  260. package/src/utils/jsonEncodeDecode.ts +0 -15
  261. package/src/utils/objectUtils.ts +0 -117
  262. package/src/utils/popup.ts +0 -30
  263. package/src/utils/searchJson.ts +0 -51
  264. package/src/utils/stepUtils.ts +0 -45
  265. package/src/utils/truncate.ts +0 -6
  266. package/test/setup.ts +0 -1
  267. package/vitest.config.ts +0 -16
@@ -1,1697 +0,0 @@
1
- 'use client';
2
-
3
- import { html } from 'htm/preact';
4
- import { useState, useEffect } from 'preact/hooks';
5
- import { Hint } from '@/components/Tooltip';
6
- import styles from './styles.module.scss';
7
-
8
- // Update the TagNode interface to better handle various types
9
- interface TagNode {
10
- name?: string; // Step name or field name
11
- machineName?: string; // Machine-readable name for the step
12
- appIcon?: string; // URL for the step's app icon
13
- output?: Record<string, unknown> | unknown[]; // JSON data for step output
14
- tags?: Record<string, TagNode>; // Nested tags or fields
15
- ignoreParentKey?: boolean; // If true, omit parent key from final tag path
16
- [key: string]: unknown; // Allow for additional properties
17
- }
18
-
19
- // Define the structure of the entire data object
20
- interface TagData {
21
- [key: string]: TagNode;
22
- }
23
-
24
- // Add this interface for the Values tab items
25
- interface ValueItem {
26
- id: number;
27
- value: string;
28
- }
29
-
30
- // Define the props for the TagMenu component
31
- interface TagMenuProps {
32
- data: TagData;
33
- onSelect: (tag: TagNode | Record<string, unknown>) => void;
34
- onOptionClick?: (option: Record<string, unknown>) => void;
35
- }
36
-
37
- interface TagListProps {
38
- tags: Record<string, unknown> | unknown[];
39
- searchTerm: string;
40
- level?: number;
41
- path?: string;
42
- globalSearchMode?: boolean;
43
- onSelect?: (tag: Record<string, unknown>) => void;
44
- activeTab?: string;
45
- parentAppIcon?: string; // Add parent app icon to props
46
- ignoreParentKey?: boolean; // whether parent key should be ignored in tag path
47
- }
48
-
49
- interface TagsMenuProps {
50
- tagsTree: Record<string, unknown>;
51
- onSelect: (tag: Record<string, unknown>) => void;
52
- renderValuesTab?: boolean;
53
- options?: Record<string, unknown>;
54
- onOptionClick?: (option: Record<string, unknown>) => void;
55
- }
56
-
57
- // Helper function to convert nested tags arrays to objects
58
- function convertNestedTagsToObject(tags: TagNode[]): Record<string, TagNode> {
59
- const result: Record<string, TagNode> = {};
60
-
61
- tags.forEach((tag, index) => {
62
- const tagKey = tag.machineName || `[${index}]`;
63
-
64
- if (tag.tags && Array.isArray(tag.tags)) {
65
- result[tagKey] = {
66
- ...tag,
67
- tags: convertNestedTagsToObject(tag.tags),
68
- };
69
- } else {
70
- result[tagKey] = tag;
71
- }
72
- });
73
-
74
- return result;
75
- }
76
-
77
- // Add a type guard function to check if a value is a TagNode
78
- function isTagNode(value: unknown): value is TagNode {
79
- return (
80
- value !== null &&
81
- typeof value === 'object' &&
82
- !Array.isArray(value) &&
83
- Object.prototype.hasOwnProperty.call(value, 'machineName')
84
- );
85
- }
86
-
87
- // Update the arrayToObject function with proper typing
88
- const arrayToObject = (arr: unknown[]): Record<string, unknown> =>
89
- arr.reduce<Record<string, unknown>>((obj, item, index) => {
90
- const newObj = { ...obj };
91
- newObj[`[${index}]`] = item;
92
- return newObj;
93
- }, {});
94
-
95
- // Check if output data matches the search term
96
- const outputMatchesSearch = (output: unknown, term: string): boolean => {
97
- if (!term || !output) return false;
98
- const lowerTerm = term.toLowerCase();
99
-
100
- if (typeof output === 'string') {
101
- return output.toLowerCase().includes(lowerTerm);
102
- }
103
-
104
- if (Array.isArray(output)) {
105
- return output.some(
106
- (item) =>
107
- (typeof item === 'string' && item.toLowerCase().includes(lowerTerm)) ||
108
- (typeof item === 'object' &&
109
- item !== null &&
110
- outputMatchesSearch(item, lowerTerm)),
111
- );
112
- }
113
-
114
- if (typeof output === 'object' && output !== null) {
115
- return Object.entries(output as Record<string, unknown>).some(
116
- ([key, val]) => {
117
- if (key.toLowerCase().includes(lowerTerm)) return true;
118
-
119
- if (typeof val === 'string') {
120
- return val.toLowerCase().includes(lowerTerm);
121
- }
122
-
123
- if (typeof val === 'object' && val !== null) {
124
- return outputMatchesSearch(val, lowerTerm);
125
- }
126
-
127
- return false;
128
- },
129
- );
130
- }
131
-
132
- return false;
133
- };
134
-
135
- // Function to count matches in a generic object
136
- const countMatchesInObject = (obj: unknown, term: string): number => {
137
- if (!obj || typeof obj !== 'object') return 0;
138
-
139
- let count = 0;
140
-
141
- // Handle arrays specifically
142
- if (Array.isArray(obj)) {
143
- obj.forEach((item) => {
144
- if (typeof item === 'string' && item.toLowerCase().includes(term)) {
145
- count += 1;
146
- } else if (typeof item === 'object' && item !== null) {
147
- count += countMatchesInObject(item, term);
148
- }
149
- });
150
- return count;
151
- }
152
-
153
- Object.entries(obj as Record<string, unknown>).forEach(([key, value]) => {
154
- if (key.toLowerCase().includes(term)) {
155
- count += 1;
156
- }
157
-
158
- if (typeof value === 'string' && value.toLowerCase().includes(term)) {
159
- count += 1;
160
- } else if (typeof value === 'object' && value !== null) {
161
- count += countMatchesInObject(value, term);
162
- }
163
- });
164
-
165
- return count;
166
- };
167
-
168
- // Count matches in a nested structure
169
- const countSearchMatches = (
170
- tags: Record<string, TagNode>,
171
- term: string,
172
- ): number => {
173
- let count = 0;
174
-
175
- Object.entries(tags).forEach(([key, value]) => {
176
- // Check if the key, name, or machineName matches
177
- if (
178
- key.toLowerCase().includes(term) ||
179
- (isTagNode(value) &&
180
- value.name &&
181
- value.name.toLowerCase().includes(term)) ||
182
- (isTagNode(value) &&
183
- value.machineName &&
184
- value.machineName.toLowerCase().includes(term))
185
- ) {
186
- count += 1;
187
- }
188
-
189
- // Check output data for matches
190
- if (value.output) {
191
- count += countMatchesInObject(value.output, term);
192
- }
193
-
194
- // Check nested tags
195
- if (value.tags) {
196
- count += countSearchMatches(value.tags, term);
197
- }
198
- });
199
-
200
- return count;
201
- };
202
-
203
- // Type icon component to render different icons based on data type
204
- const TypeIcon = ({ value }: { value: unknown }) => {
205
- // Determine the type of value
206
- const getTypeIcon = (iconValue: unknown) => {
207
- if (iconValue === null || iconValue === undefined) {
208
- return html`
209
- <svg
210
- xmlns="http://www.w3.org/2000/svg"
211
- width="24"
212
- height="24"
213
- viewBox="0 0 24 24"
214
- fill="none"
215
- stroke="currentColor"
216
- strokeWidth="2"
217
- strokeLinecap="round"
218
- strokeLinejoin="round"
219
- class="lucide lucide-ban h-4 w-4"
220
- >
221
- <circle cx="12" cy="12" r="10"></circle>
222
- <path d="m4.93 4.93 14.14 14.14"></path>
223
- </svg>
224
- `;
225
- }
226
-
227
- if (typeof iconValue === 'string') {
228
- return html`
229
- <img
230
- src="data:image/svg+xml,%3csvg%20width='23'%20height='15'%20viewBox='0%200%2023%2015'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M4.12408%2010.2498H9.09622L9.5856%2011.7004H9.08601C8.59375%2011.7004%208.24266%2011.8106%208.03275%2012.0311C7.82284%2012.2516%207.71835%2012.536%207.71835%2012.8844C7.71835%2013.24%207.82284%2013.5289%208.03275%2013.7493C8.24266%2013.9698%208.59375%2014.08%209.08601%2014.08H11.8424C12.3347%2014.08%2012.6839%2013.9698%2012.8902%2013.7493C13.0964%2013.5289%2013.2%2013.2444%2013.2%2012.896C13.2%2012.4782%2013.0469%2012.1413%2012.7408%2011.8862C12.5877%2011.7627%2012.2714%2011.7004%2011.792%2011.7004L7.71839%200.0115555L3.29537%200C2.80219%200%202.45111%200.110217%202.2412%200.330662C2.03221%200.551119%201.92679%200.840001%201.92679%201.19556C1.92679%201.55111%202.0322%201.84001%202.2412%202.06045C2.45111%202.28089%202.80219%202.39112%203.29537%202.39112H4.63279L1.41807%2011.7004C0.912084%2011.6853%200.549076%2011.7893%200.329075%2012.0142C0.110001%2012.2382%200%2012.5289%200%2012.8844C0%2013.24%200.104491%2013.5289%200.314408%2013.7493C0.524319%2013.9698%200.875405%2014.08%201.36767%2014.08H4.12408C4.61634%2014.08%204.96743%2013.9698%205.17734%2013.7493C5.38725%2013.5289%205.49175%2013.2444%205.49175%2012.896C5.49175%2012.5404%205.38725%2012.2515%205.17734%2012.0311C4.96743%2011.8107%204.61634%2011.7004%204.12408%2011.7004H3.62449L4.12408%2010.2498ZM6.60013%203.1573L8.24738%207.87022H4.94279L6.60013%203.1573Z'%20fill='%23999999'/%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M19.523%2013.1856V13.7089L21.6596%2013.7089C22.0995%2013.7089%2022.4124%2013.6051%2022.5991%2013.3983C22.7866%2013.1916%2022.88%2012.9248%2022.88%2012.597C22.88%2012.2633%2022.7866%2011.9922%2022.5991%2011.7855C22.4124%2011.5787%2022.0995%2011.4749%2021.6596%2011.4749H21.3485V6.87643C21.3485%205.83759%2021.0347%205.01831%2020.409%204.41862C19.7823%203.8198%2018.9025%203.51953%2017.7685%203.51953C17.3883%203.51953%2016.9639%203.565%2016.4946%203.65594C16.0262%203.74688%2015.5655%203.86871%2015.1143%204.02141C14.7764%204.13723%2014.5534%204.23761%2014.4471%204.32082C14.34%204.40404%2014.257%204.51471%2014.1974%204.65283C14.1377%204.79095%2014.1083%204.95481%2014.1083%205.14355C14.1083%205.47813%2014.193%205.75181%2014.3624%205.96628C14.531%206.18075%2014.7375%206.28799%2014.9813%206.28799C15.1593%206.28799%2015.4082%206.2408%2015.7289%206.14643C16.5897%205.88477%2017.2906%205.75351%2017.8308%205.75351C18.4894%205.75351%2018.9362%205.85903%2019.1713%206.07007C19.4055%206.28027%2019.523%206.55309%2019.523%206.88681V7.42128C18.7988%207.27544%2018.1601%207.20337%2017.6078%207.20337C16.231%207.20337%2015.1515%207.60489%2014.3711%208.40702C13.5906%209.21007%2013.2%2010.08%2013.2%2011.0177C13.2%2011.7872%2013.5059%2012.4907%2014.1169%2013.1264C14.7288%2013.7621%2015.524%2014.0795%2016.5041%2014.0795C16.9552%2014.0795%2017.4565%2014.0049%2018.0088%2013.8565C18.561%2013.7072%2019.0658%2013.4842%2019.523%2013.1856ZM17.5015%209.4477C18.1185%209.4477%2018.7927%209.53521%2019.523%209.70936V10.6685C19.0891%2011.0322%2018.5948%2011.3188%2018.0399%2011.5298C17.485%2011.74%2016.9872%2011.8455%2016.5482%2011.8455C16.0322%2011.8455%2015.6251%2011.7254%2015.3287%2011.4861C15.1679%2011.3548%2015.0875%2011.1841%2015.0875%2010.9739C15.0875%2010.6831%2015.2543%2010.3965%2015.5862%2010.1126C16.1212%209.66989%2016.759%209.4477%2017.5015%209.4477Z'%20fill='%23999999'/%3e%3c/svg%3e"
231
- alt="alt-icon"
232
- class="type-icon"
233
- />
234
- `;
235
- }
236
-
237
- if (typeof iconValue === 'number') {
238
- return html`
239
- <img
240
- src="data:image/svg+xml,%3csvg%20width='15'%20height='8'%20viewBox='0%200%2015%208'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M3.37681%207.86147H1.83754V1.92808L0%202.49799V1.24633L3.2117%200.0958716H3.37681V7.86147Z'%20fill='%23999999'/%3e%3cpath%20d='M9.39897%207.86147H4.08342V6.80688L6.59206%204.13313C6.93649%203.75675%207.19037%203.4283%207.35371%203.14778C7.5206%202.86727%207.60404%202.60096%207.60404%202.34885C7.60404%202.00443%207.51704%201.73457%207.34305%201.53927C7.16907%201.34043%206.92051%201.241%206.59739%201.241C6.24941%201.241%205.97422%201.36173%205.77183%201.60319C5.57298%201.84109%205.47356%202.15534%205.47356%202.54592H3.92896C3.92896%202.07367%204.04081%201.64225%204.26451%201.25166C4.49176%200.861069%204.81133%200.5557%205.22323%200.335551C5.63512%200.11185%206.10205%200%206.62402%200C7.42295%200%208.04256%200.191743%208.48286%200.57523C8.92671%200.958716%209.14864%201.50021%209.14864%202.19972C9.14864%202.58321%209.04921%202.9738%208.85037%203.37148C8.65152%203.76917%208.31065%204.23255%207.82774%204.76162L6.06477%206.62047H9.39897V7.86147Z'%20fill='%23999999'/%3e%3cpath%20d='M11.3675%203.30224H12.1878C12.5784%203.30224%2012.8677%203.2046%2013.0559%203.0093C13.2441%202.81401%2013.3382%202.5548%2013.3382%202.23168C13.3382%201.91921%2013.2441%201.67598%2013.0559%201.50199C12.8713%201.328%2012.6156%201.241%2012.289%201.241C11.9942%201.241%2011.7475%201.32267%2011.5486%201.48601C11.3498%201.6458%2011.2504%201.85529%2011.2504%202.1145H9.71108C9.71108%201.70971%209.81938%201.34753%2010.036%201.02796C10.2561%200.704834%2010.5615%200.452727%2010.9521%200.271636C11.3462%200.0905454%2011.7794%200%2012.2517%200C13.0719%200%2013.7146%200.197069%2014.1798%200.591208C14.6449%200.981796%2014.8775%201.52152%2014.8775%202.21037C14.8775%202.56545%2014.7692%202.89213%2014.5526%203.19039C14.336%203.48866%2014.0519%203.71769%2013.7004%203.87747C14.1372%204.03371%2014.4621%204.26806%2014.6751%204.58053C14.8917%204.893%2015%205.26229%2015%205.68838C15%206.37724%2014.7479%206.92939%2014.2437%207.34483C13.743%207.76027%2013.079%207.968%2012.2517%207.968C11.4776%207.968%2010.8438%207.76382%2010.3502%207.35548C9.86022%206.94714%209.61521%206.40742%209.61521%205.73632H11.1545C11.1545%206.02748%2011.2628%206.26539%2011.4794%206.45003C11.6995%206.63467%2011.9694%206.72699%2012.289%206.72699C12.6547%206.72699%2012.9405%206.63112%2013.1465%206.43938C13.356%206.24408%2013.4607%205.98665%2013.4607%205.66708C13.4607%204.893%2013.0346%204.50597%2012.1824%204.50597H11.3675V3.30224Z'%20fill='%23999999'/%3e%3c/svg%3e"
241
- alt="alt-icon"
242
- class="type-icon"
243
- />
244
- `;
245
- }
246
-
247
- if (typeof iconValue === 'boolean') {
248
- // Single icon for all boolean values
249
- return html`
250
- <svg
251
- xmlns="http://www.w3.org/2000/svg"
252
- width="24"
253
- height="24"
254
- viewBox="0 0 24 24"
255
- fill="none"
256
- stroke="#71717a"
257
- strokeWidth="2"
258
- strokeLinecap="round"
259
- strokeLinejoin="round"
260
- class="lucide lucide-toggle-right h-4 w-4"
261
- >
262
- <rect width="20" height="12" x="2" y="6" rx="6" ry="6"></rect>
263
- <circle cx="16" cy="12" r="2"></circle>
264
- </svg>
265
- `;
266
- }
267
-
268
- if (Array.isArray(iconValue)) {
269
- return html`
270
- <svg
271
- xmlns="http://www.w3.org/2000/svg"
272
- width="24"
273
- height="24"
274
- viewBox="0 0 24 24"
275
- fill="none"
276
- stroke="#71717a"
277
- stroke-width="2"
278
- stroke-linecap="round"
279
- stroke-linejoin="round"
280
- class="lucide lucide-layers"
281
- >
282
- <path
283
- d="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z"
284
- />
285
- <path
286
- d="M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12"
287
- />
288
- <path
289
- d="M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17"
290
- />
291
- </svg>
292
- `;
293
- }
294
-
295
- if (typeof iconValue === 'object') {
296
- return html`
297
- <img
298
- src="data:image/svg+xml,%3csvg%20width='14'%20height='15'%20viewBox='0%200%2014%2015'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20d='M12.8419%203.40522L7.78708%200.494922C7.3822%200.269922%206.88708%200.269922%206.49684%200.494922L1.44199%203.40522C1.03711%203.63022%200.796875%204.06498%200.796875%204.53022V10.3649C0.796875%2010.8302%201.05175%2011.2497%201.44199%2011.4899L6.49684%2014.3996C6.69197%2014.5197%206.91696%2014.5795%207.14196%2014.5795C7.36696%2014.5795%207.59196%2014.5197%207.78708%2014.3996L12.8419%2011.4746C13.2468%2011.2496%2013.4871%2010.8149%2013.4871%2010.3496V4.53007C13.4871%204.06483%2013.2322%203.63007%2012.8419%203.40507V3.40522ZM7.00723%201.38022C7.05235%201.35034%207.09747%201.35034%207.142%201.35034C7.18712%201.35034%207.23223%201.36557%207.27677%201.38022L11.9421%204.08022L7.14207%206.83992L2.34207%204.08022L7.00723%201.38022ZM1.96693%2010.5899C1.89193%2010.5448%201.83217%2010.4552%201.83217%2010.3649V4.96492L6.63217%207.73992V13.2746L1.96693%2010.5899ZM12.3169%2010.5899L7.65163%2013.2899V7.73992L12.4516%204.96492V10.3496C12.4516%2010.4551%2012.4071%2010.5301%2012.3169%2010.5899L12.3169%2010.5899Z'%20fill='%23999999'/%3e%3c/svg%3e"
299
- alt="alt-icon"
300
- class="type-icon"
301
- />
302
- `;
303
- }
304
-
305
- // Default tag icon for any other type
306
- return html`
307
- <svg
308
- xmlns="http://www.w3.org/2000/svg"
309
- width="24"
310
- height="24"
311
- viewBox="0 0 24 24"
312
- fill="none"
313
- stroke="currentColor"
314
- strokeWidth="2"
315
- strokeLinecap="round"
316
- strokeLinejoin="round"
317
- class="lucide lucide-tag h-4 w-4"
318
- >
319
- <path
320
- d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"
321
- ></path>
322
- <circle cx="7.5" cy="7.5" r=".5" fill="currentColor"></circle>
323
- </svg>
324
- `;
325
- };
326
-
327
- return html`<span class="${styles.tagIcon}">${getTypeIcon(value)}</span>`;
328
- };
329
-
330
- // Add a new component to render the flat list of values
331
- const ValuesList = ({
332
- values,
333
- onSelect,
334
- onOptionClick,
335
- }: {
336
- values: ValueItem[];
337
- onSelect: (item: Record<string, unknown>) => void;
338
- onOptionClick: (option: Record<string, unknown>) => void;
339
- }) =>
340
- html`
341
- <div class="${styles.valuesList}">
342
- <ul>
343
- ${values.map(
344
- (item) => html`
345
- <li
346
- key=${item.id}
347
- class="${styles.valueItem}"
348
- onClick=${() =>
349
- onOptionClick({
350
- id: item.id,
351
- value: item.value,
352
- })}
353
- >
354
- <span class="${styles.valueText}">${item.value}</span>
355
- </li>
356
- `,
357
- )}
358
- </ul>
359
- </div>
360
- `;
361
-
362
- // Update the TagList component to pass parent app icon and include it in selections
363
- const TagList = ({
364
- tags,
365
- searchTerm,
366
- level = 0,
367
- path = '',
368
- globalSearchMode = false,
369
- onSelect = (tag: Record<string, unknown>): void => {
370
- /* Default empty implementation */
371
- },
372
- activeTab = '',
373
- parentAppIcon = undefined, // Add parent app icon parameter
374
- ignoreParentKey = false,
375
- }: TagListProps) => {
376
- // Track which nodes are expanded to show nested steps
377
- const [expandedNodes, setExpandedNodes] = useState<Record<string, boolean>>(
378
- {},
379
- );
380
-
381
- // Track which steps have their output expanded
382
- const [expandedOutputs, setExpandedOutputs] = useState<
383
- Record<string, boolean>
384
- >({});
385
-
386
- // Track which node is being hovered
387
- const [hoveredNode, setHoveredNode] = useState<string | null>(null);
388
-
389
- // Handle arrays by converting them to objects with indices as keys
390
- const processedTags = Array.isArray(tags)
391
- ? arrayToObject(tags)
392
- : (tags as Record<string, unknown>);
393
-
394
- // Update the nodeMatchesSearch function with proper type checking
395
- const nodeMatchesSearch = (
396
- key: string,
397
- node: unknown,
398
- term: string,
399
- ): boolean => {
400
- if (!term) return false;
401
- const lowerTerm = term.toLowerCase();
402
-
403
- return (
404
- key?.toLowerCase().includes(lowerTerm) ||
405
- (isTagNode(node) &&
406
- node.name &&
407
- node.name.toLowerCase().includes(lowerTerm)) ||
408
- (isTagNode(node) &&
409
- node.machineName &&
410
- node.machineName.toLowerCase().includes(lowerTerm)) ||
411
- false
412
- );
413
- };
414
-
415
- // Update the childrenMatchSearch function with proper type checking
416
- const childrenMatchSearch = (node: unknown, term: string): boolean => {
417
- if (!term) return false;
418
-
419
- // Check if node is an array
420
- if (Array.isArray(node)) {
421
- return node.some(
422
- (item) =>
423
- (typeof item === 'string' && item.toLowerCase().includes(term)) ||
424
- (typeof item === 'object' &&
425
- item !== null &&
426
- outputMatchesSearch(item, term)),
427
- );
428
- }
429
-
430
- // Check if node has tags
431
- if (isTagNode(node) && node.tags) {
432
- return Object.entries(node.tags).some(
433
- ([childKey, childNode]) =>
434
- nodeMatchesSearch(childKey, childNode, term) ||
435
- childrenMatchSearch(childNode, term) ||
436
- (isTagNode(childNode) &&
437
- childNode.output &&
438
- outputMatchesSearch(childNode.output, term)),
439
- );
440
- }
441
-
442
- return false;
443
- };
444
-
445
- // Add the isExpandable function with proper type checking
446
- const isExpandable = (value: unknown): boolean => {
447
- if (value === null || value === undefined) return false;
448
-
449
- // Arrays with items are expandable
450
- if (Array.isArray(value)) return value.length > 0;
451
-
452
- // Objects with properties are expandable
453
- if (typeof value === 'object') {
454
- // Check if it's a TagNode with tags
455
- if (isTagNode(value)) {
456
- // Check if it has tags
457
- if (value.tags && Object.keys(value.tags).length > 0) {
458
- return true;
459
- }
460
-
461
- // Check if it has output that is expandable
462
- if (value.output) {
463
- if (Array.isArray(value.output) && value.output.length > 0) {
464
- return true;
465
- }
466
- if (
467
- typeof value.output === 'object' &&
468
- value.output !== null &&
469
- Object.keys(value.output as Record<string, unknown>).length > 0
470
- ) {
471
- return true;
472
- }
473
- }
474
- }
475
-
476
- // Regular object with properties
477
- return Object.keys(value as Record<string, unknown>).length > 0;
478
- }
479
-
480
- return false;
481
- };
482
-
483
- // Initialize expandedNodes for steps with nested steps and handle search expansion
484
- useEffect(() => {
485
- const initialExpanded: Record<string, boolean> = {};
486
- const initialOutputs: Record<string, boolean> = {};
487
-
488
- Object.entries(processedTags).forEach(([key, value]) => {
489
- // Auto-expand steps that have nested steps
490
- if (
491
- isTagNode(value) &&
492
- value.tags &&
493
- Object.keys(value.tags).length > 0
494
- ) {
495
- initialExpanded[key] = true;
496
- }
497
-
498
- // If in search mode, check if this node or its children match the search
499
- if (
500
- searchTerm &&
501
- (nodeMatchesSearch(key, value, searchTerm) ||
502
- childrenMatchSearch(value, searchTerm))
503
- ) {
504
- initialExpanded[key] = true;
505
-
506
- // If the node has output and the output matches the search, expand the output too
507
- if (
508
- isTagNode(value) &&
509
- value.output &&
510
- outputMatchesSearch(value.output, searchTerm)
511
- ) {
512
- initialOutputs[key] = true;
513
- }
514
- }
515
- });
516
-
517
- setExpandedNodes((prev) => ({ ...prev, ...initialExpanded }));
518
- setExpandedOutputs((prev) => ({ ...prev, ...initialOutputs }));
519
- }, [processedTags, searchTerm]);
520
-
521
- // Update the toggleExpand function with proper type checking
522
- const toggleExpand = (key: string, event?: Event) => {
523
- if (event) {
524
- event.stopPropagation(); // Prevent event bubbling
525
- }
526
-
527
- // Get the node that we want to toggle
528
- const node = processedTags[key];
529
-
530
- if (isTagNode(node)) {
531
- // If it's a TagNode with tags, toggle output expansion
532
- if (node.tags && Object.keys(node.tags).length > 0) {
533
- // Toggle the output expansion
534
- setExpandedOutputs((prev) => ({
535
- ...prev,
536
- [key]: !prev[key],
537
- }));
538
- return;
539
- }
540
-
541
- // If it's a TagNode with expandable output, toggle node expansion
542
- if (node.output && isExpandable(node.output)) {
543
- setExpandedNodes((prev) => ({
544
- ...prev,
545
- [key]: !prev[key],
546
- }));
547
- return;
548
- }
549
- }
550
-
551
- // For arrays, objects, or steps without nested tags - toggle normal expansion
552
- setExpandedNodes((prev) => {
553
- const newExpandedNodes = { ...prev };
554
- // Toggle the value
555
- newExpandedNodes[key] = !prev[key];
556
- return newExpandedNodes;
557
- });
558
- };
559
-
560
- const toggleOutputExpand = (key: string, e: Event) => {
561
- e.stopPropagation(); // Prevent the click from affecting the parent
562
- setExpandedOutputs((prev) => ({
563
- ...prev,
564
- [key]: !prev[key],
565
- }));
566
- };
567
-
568
- const escapeHTMLIfNeeded = (input: any) => {
569
- if (typeof input !== 'string') {
570
- return input;
571
- }
572
- const isHTML = /<\/?[a-z][\s\S]*>/i.test(input);
573
-
574
- const output = isHTML
575
- ? input
576
- .replace(/&/g, '&amp;')
577
- .replace(/</g, '&lt;')
578
- .replace(/>/g, '&gt;')
579
- .replace(/"/g, '&quot;')
580
- .replace(/'/g, '&#039;')
581
- : input;
582
-
583
- return output.length > 200 ? `${output.slice(0, 200)}...` : output;
584
- };
585
-
586
- const highlightSearchTerm = (text: string, term: string) => {
587
- const textModified = escapeHTMLIfNeeded(text);
588
- if (!term) return textModified;
589
- const regex = new RegExp(`(${term})`, 'gi');
590
- return textModified.replace(regex, '<mark>$1</mark>');
591
- };
592
-
593
- const extractStepsFromOutputPath = (pathToExtract: string) => {
594
- const parts = pathToExtract.split('.'); // Split the string by dots
595
-
596
- // Find the first occurrence of 'output'
597
- const firstOutputIndex = parts.indexOf('output');
598
-
599
- if (firstOutputIndex === -1 || firstOutputIndex === 0) {
600
- return ''; // Return empty if 'output' is not found or it's at the start
601
- }
602
-
603
- // Get the step name (part before the first 'output')
604
- const stepName = parts[firstOutputIndex - 1];
605
-
606
- // Get all parts after the first 'output', including any other 'output' keys
607
- const remainingParts = parts.slice(firstOutputIndex + 1);
608
-
609
- // If there are remaining parts, combine the step name with them
610
- if (remainingParts.length > 0) {
611
- return `${stepName}.${remainingParts.join('.')}`;
612
- }
613
-
614
- // If there are no remaining parts, just return the step name
615
- return stepName;
616
- };
617
-
618
- // Modified function to handle selecting a tag with parent app icon
619
- const handleSelectTag = (
620
- key: string,
621
- value: unknown,
622
- currentPath: string,
623
- nodeAppIcon?: string,
624
- ignoreKey = false,
625
- ) => {
626
- const basePath = extractStepsFromOutputPath(currentPath);
627
- const tagPath = ignoreKey ? basePath : `${activeTab}.${basePath}`;
628
-
629
- // Determine which app icon to use - prioritize node's own icon, then parent icon
630
- const appIconToUse = nodeAppIcon || parentAppIcon;
631
-
632
- onSelect({
633
- currentPath: tagPath
634
- .replace(/\bparameters\.parameters\b/g, 'parameters')
635
- .replace(/\bauthorization\.authorization\b/g, 'authorization'),
636
- key,
637
- value: escapeHTMLIfNeeded(value),
638
- parentAppIcon: appIconToUse, // Include parent app icon in the response
639
- });
640
- };
641
-
642
- // Update the filterTags function with proper type checking
643
- const filterTags = (
644
- tagsToFilter: Record<string, unknown> | unknown[],
645
- termToSearch: string,
646
- pathPrefix: string,
647
- ): Record<string, unknown> | unknown[] => {
648
- if (!termToSearch) return tagsToFilter;
649
-
650
- // Handle arrays
651
- if (Array.isArray(tagsToFilter)) {
652
- const filteredArray = tagsToFilter.filter((item, index) => {
653
- const currentPath = pathPrefix
654
- ? `${pathPrefix}[${index}]`
655
- : `[${index}]`;
656
-
657
- // Check if this item matches the search
658
- if (
659
- typeof item === 'string' &&
660
- item.toLowerCase().includes(termToSearch.toLowerCase())
661
- ) {
662
- return true;
663
- }
664
-
665
- // Check if this is an object that matches
666
- if (typeof item === 'object' && item !== null) {
667
- const filteredItem = filterTags(
668
- item as Record<string, unknown>,
669
- termToSearch,
670
- currentPath,
671
- );
672
- return (
673
- (typeof filteredItem === 'object' &&
674
- Object.keys(filteredItem as Record<string, unknown>).length >
675
- 0) ||
676
- outputMatchesSearch(item, termToSearch)
677
- );
678
- }
679
-
680
- return false;
681
- });
682
-
683
- return filteredArray.length > 0 ? arrayToObject(filteredArray) : {};
684
- }
685
-
686
- const filteredTags: Record<string, unknown> = {};
687
- const lowerTerm = termToSearch.toLowerCase();
688
-
689
- Object.entries(tagsToFilter).forEach(([key, value]) => {
690
- const currentPath = pathPrefix ? `${pathPrefix}.${key}` : key;
691
-
692
- // Check if this node matches the search
693
- const nodeMatches = nodeMatchesSearch(key, value, lowerTerm);
694
-
695
- // Check if output matches the search
696
- const outputMatches =
697
- isTagNode(value) &&
698
- value.output &&
699
- outputMatchesSearch(value.output, lowerTerm);
700
-
701
- // Check if children match the search
702
- let filteredChildren: Record<string, unknown> = {};
703
-
704
- // Handle array in output
705
- if (isTagNode(value) && value.output && Array.isArray(value.output)) {
706
- const filteredOutput = filterTags(
707
- value.output,
708
- termToSearch,
709
- `${currentPath}.output`,
710
- );
711
- const outputMatch =
712
- typeof filteredOutput === 'object' &&
713
- Object.keys(filteredOutput as Record<string, unknown>).length > 0;
714
- if (outputMatch) {
715
- const clonedNode = { ...value };
716
- clonedNode.output = value.output; // Keep original array for proper rendering
717
- filteredTags[key] = clonedNode;
718
- return;
719
- }
720
- }
721
-
722
- // Handle regular tags
723
- if (isTagNode(value) && value.tags) {
724
- filteredChildren = filterTags(
725
- value.tags,
726
- termToSearch,
727
- currentPath,
728
- ) as Record<string, unknown>;
729
- }
730
-
731
- const childrenMatch =
732
- typeof filteredChildren === 'object' &&
733
- Object.keys(filteredChildren).length > 0;
734
-
735
- // Include this node if it matches or has matching children
736
- if (nodeMatches || outputMatches || childrenMatch) {
737
- // Clone the node to avoid modifying the original
738
- const clonedNode = isTagNode(value) ? { ...value } : value;
739
-
740
- // If children match, include the filtered children
741
- if (childrenMatch && isTagNode(clonedNode)) {
742
- clonedNode.tags = filteredChildren as Record<string, TagNode>;
743
- }
744
-
745
- filteredTags[key] = clonedNode;
746
- }
747
- });
748
-
749
- return filteredTags;
750
- };
751
-
752
- // Only filter if in global search mode, otherwise show all
753
- const filteredTags = globalSearchMode
754
- ? filterTags(processedTags, searchTerm, path)
755
- : processedTags;
756
-
757
- // Simplified rendering to fix syntax issues
758
- return html`
759
- <ul style="padding-left: ${1 * 20}px;">
760
- ${Object.entries(filteredTags as Record<string, unknown>).map(
761
- ([key, value]) => {
762
- const isStep = isTagNode(value);
763
- // We don't use isOutput but keep it for future reference
764
- const isArrayItem = key.startsWith('[') && key.endsWith(']');
765
- const hasNestedSteps =
766
- isStep &&
767
- isTagNode(value) &&
768
- value.tags &&
769
- Object.keys(value.tags).length > 0;
770
- const hasOutput =
771
- isTagNode(value) &&
772
- value.output &&
773
- typeof value.output === 'object';
774
- // Determine if this item has children that can be expanded
775
- let hasChildren = hasNestedSteps || hasOutput;
776
-
777
- // Check if this is an array or object (even if it's inside a step's output)
778
- // This will allow us to show expand/collapse icons for arrays and objects
779
- const isArray = Array.isArray(value);
780
- const isObject =
781
- !isArray &&
782
- typeof value === 'object' &&
783
- value !== null &&
784
- Object.keys(value as Record<string, unknown>).length > 0;
785
-
786
- // If this is an array or object (not a step), mark it as having children
787
- if (!isStep && (isArray || isObject)) {
788
- hasChildren = true;
789
- }
790
-
791
- // If this is a step with output that is an array or object, also mark it as having children
792
- if (isStep && isTagNode(value) && value.output) {
793
- // The output could be any data type - check if it's an array or object with content
794
- const outputIsArray =
795
- Array.isArray(value.output) && value.output.length > 0;
796
- const outputIsObject =
797
- !outputIsArray &&
798
- typeof value.output === 'object' &&
799
- value.output !== null &&
800
- Object.keys(value.output as Record<string, unknown>).length > 0;
801
-
802
- if (outputIsArray || outputIsObject) {
803
- hasChildren = true;
804
- }
805
- }
806
- const isExpanded = expandedNodes[key];
807
- const isOutputExpanded = expandedOutputs[key];
808
- let currentPath: string;
809
- if (path) {
810
- if (key.startsWith('[') && key.endsWith(']')) {
811
- currentPath = `${path}${key}`;
812
- } else {
813
- currentPath = `${path}.${key}`;
814
- }
815
- } else {
816
- currentPath = key;
817
- }
818
- const nodeMatches =
819
- searchTerm && nodeMatchesSearch(key, value, searchTerm);
820
- let text: string;
821
-
822
- if (isArrayItem) {
823
- text = key;
824
- } else if (isTagNode(value) && value.name) {
825
- text = value.name;
826
- } else {
827
- text = key;
828
- }
829
-
830
- let tagsParam: unknown = {};
831
-
832
- if (isTagNode(value)) {
833
- // If the output exists, use it directly regardless of its type
834
- if (value.output !== undefined) {
835
- tagsParam = value.output;
836
- }
837
- }
838
-
839
- let tagsParamForOutput: unknown;
840
-
841
- if (Array.isArray(value)) {
842
- tagsParamForOutput = value;
843
- } else if (isTagNode(value) && value.tags) {
844
- tagsParamForOutput = value.tags;
845
- } else {
846
- tagsParamForOutput = value as Record<string, unknown>;
847
- }
848
-
849
- // Determine the app icon to pass down - use current node's icon or parent's icon
850
- const currentNodeAppIcon = isTagNode(value)
851
- ? value.appIcon
852
- : undefined;
853
- const appIconToPass = currentNodeAppIcon || parentAppIcon;
854
- const childIgnoreParentKey =
855
- ignoreParentKey || (isTagNode(value) && value.ignoreParentKey === true);
856
-
857
- const handleMenuRowClcik = (e: Event) => {
858
- if (isStep && hasOutput) {
859
- // For step nodes with output, toggle output expansion
860
- setExpandedOutputs((prev) => ({
861
- ...prev,
862
- [key]: !prev[key],
863
- }));
864
- } else if (hasChildren) {
865
- // For array/object nodes, toggle node expansion
866
- toggleExpand(key);
867
- toggleOutputExpand(key, e);
868
- } else {
869
- // For leaf nodes, select the value
870
- handleSelectTag(
871
- key,
872
- value,
873
- currentPath,
874
- currentNodeAppIcon,
875
- childIgnoreParentKey,
876
- );
877
- }
878
- };
879
-
880
- // Check if this is an edge node (leaf node with no children)
881
- const isEdgeNode = !hasChildren;
882
-
883
- // Determine if we should show the add tag button
884
- // Don't show for step name nodes, only for non-edge nodes that aren't step names
885
- const shouldShowAddButton =
886
- !isEdgeNode && hoveredNode === key && !isStep;
887
-
888
- return html`
889
- <li key=${key} class="${nodeMatches ? styles.searchMatch : ''}">
890
- <div
891
- onClick=${(e: Event) => {
892
- if (isStep && hasOutput) {
893
- // For step nodes with output, toggle output expansion
894
- setExpandedOutputs((prev) => ({
895
- ...prev,
896
- [key]: !prev[key],
897
- }));
898
- } else if (hasChildren) {
899
- // For array/object nodes, toggle node expansion
900
- toggleExpand(key);
901
- toggleOutputExpand(key, e);
902
- } else {
903
- // For leaf nodes, select the value
904
- handleSelectTag(
905
- key,
906
- value,
907
- currentPath,
908
- currentNodeAppIcon,
909
- childIgnoreParentKey,
910
- );
911
- }
912
- }}
913
- class="${styles.listItemContent}"
914
- onMouseEnter=${() => setHoveredNode(key)}
915
- onMouseLeave=${() => setHoveredNode(null)}
916
- >
917
- ${!isStep ? html`<${TypeIcon} value=${value} />` : ''}
918
- ${isTagNode(value) && value.appIcon
919
- ? html`<img src=${value.appIcon} alt="App Icon" />`
920
- : ''}
921
-
922
- <span
923
- class="${styles.key}"
924
- dangerouslySetInnerHTML=${{
925
- __html: highlightSearchTerm(text, searchTerm),
926
- }}
927
- ></span>
928
-
929
- ${!hasChildren &&
930
- value !== undefined &&
931
- (typeof value === 'string' ||
932
- typeof value === 'number' ||
933
- typeof value === 'boolean')
934
- ? html`<${Hint}
935
- dismissOnClick=${false}
936
- position="top"
937
- deltaY=${0}
938
- className=${styles.hint}
939
- ><span class="${styles.value}">
940
- ${value ? ' ' : ''}
941
- <span
942
- data-hint=${value ? String(value) : ''}
943
- dangerouslySetInnerHTML=${{
944
- __html: highlightSearchTerm(
945
- String(value),
946
- searchTerm,
947
- ),
948
- }}
949
- ></span> </span
950
- ><//>`
951
- : ''}
952
- ${isStep &&
953
- value !== undefined &&
954
- isTagNode(value) &&
955
- value.machineName
956
- ? html`<span class="${styles.value}">
957
- ${' '}
958
- <span
959
- dangerouslySetInnerHTML=${{
960
- __html: highlightSearchTerm(
961
- value.machineName,
962
- searchTerm,
963
- ),
964
- }}
965
- ></span>
966
- </span>`
967
- : ''}
968
- ${isArrayItem && typeof value === 'object' && !isStep
969
- ? html`<span class="${styles.value}">
970
- ${' '}
971
- <span>
972
- ${Array.isArray(value)
973
- ? `Array(${value.length})`
974
- : `Object${
975
- value && typeof value === 'object'
976
- ? ` (${
977
- Object.keys(
978
- value as Record<string, unknown>,
979
- ).length
980
- } keys)`
981
- : ''
982
- }`}
983
- </span>
984
- </span>`
985
- : ''}
986
-
987
- <!-- Add Tag button for non-edge nodes that aren't step names -->
988
- ${shouldShowAddButton
989
- ? html`
990
- <button
991
- class="${styles.addTagButton}"
992
- onClick=${(e: Event) => {
993
- e.stopPropagation();
994
- handleSelectTag(
995
- key,
996
- value,
997
- currentPath,
998
- currentNodeAppIcon,
999
- childIgnoreParentKey,
1000
- );
1001
- }}
1002
- title="Add this tag"
1003
- >
1004
- <svg
1005
- xmlns="http://www.w3.org/2000/svg"
1006
- width="16"
1007
- height="16"
1008
- viewBox="0 0 24 24"
1009
- fill="none"
1010
- stroke="currentColor"
1011
- strokeWidth="2"
1012
- strokeLinecap="round"
1013
- strokeLinejoin="round"
1014
- >
1015
- <path d="M12 5v14"></path>
1016
- <path d="M5 12h14"></path>
1017
- </svg>
1018
- </button>
1019
- `
1020
- : ''}
1021
-
1022
- <!-- Expand/collapse icon for arrays -->
1023
- ${Array.isArray(value) && value.length > 0
1024
- ? html`<span
1025
- class="${styles.outputIndicator} ${styles.objectExpandIcon}"
1026
- onClick=${(e: Event) => handleMenuRowClcik(e)}
1027
- title="Toggle expand output"
1028
- >
1029
- <svg
1030
- xmlns="http://www.w3.org/2000/svg"
1031
- width="24"
1032
- height="24"
1033
- viewBox="0 0 24 24"
1034
- fill="none"
1035
- stroke="currentColor"
1036
- strokeWidth="2"
1037
- strokeLinecap="round"
1038
- strokeLinejoin="round"
1039
- style="transform: ${isOutputExpanded
1040
- ? 'rotate(180deg)'
1041
- : 'rotate(0deg)'};
1042
- transition: transform 0.2s;"
1043
- >
1044
- <path d="m6 9 6 6 6-6"></path>
1045
- </svg>
1046
- </span>`
1047
- : ''}
1048
-
1049
- <!-- Expand/collapse icon for objects -->
1050
- ${!isStep &&
1051
- !Array.isArray(value) &&
1052
- typeof value === 'object' &&
1053
- value !== null &&
1054
- Object.keys(value as Record<string, unknown>).length > 0
1055
- ? html`<span
1056
- class="${styles.outputIndicator} ${styles.objectExpandIcon}"
1057
- onClick=${(e: Event) => {
1058
- handleMenuRowClcik(e);
1059
- }}
1060
- title="Toggle expand output"
1061
- >
1062
- <svg
1063
- xmlns="http://www.w3.org/2000/svg"
1064
- width="24"
1065
- height="24"
1066
- viewBox="0 0 24 24"
1067
- fill="none"
1068
- stroke="currentColor"
1069
- strokeWidth="2"
1070
- strokeLinecap="round"
1071
- strokeLinejoin="round"
1072
- style="transform: ${isOutputExpanded
1073
- ? 'rotate(180deg)'
1074
- : 'rotate(0deg)'};
1075
- transition: transform 0.2s;"
1076
- >
1077
- <path d="m6 9 6 6 6-6"></path>
1078
- </svg>
1079
- </span>`
1080
- : ''}
1081
-
1082
- <!-- Expand/collapse icon for step output that contains arrays or objects -->
1083
- ${isStep &&
1084
- isTagNode(value) &&
1085
- value.output &&
1086
- ((Array.isArray(value.output) && value.output.length > 0) ||
1087
- (!Array.isArray(value.output) &&
1088
- typeof value.output === 'object' &&
1089
- value.output !== null &&
1090
- Object.keys(value.output as Record<string, unknown>)
1091
- .length > 0))
1092
- ? html`<span
1093
- class="${styles.outputIndicator} ${styles.objectExpandIcon}"
1094
- onClick=${(e: Event) => toggleOutputExpand(key, e)}
1095
- title="Toggle expand output"
1096
- >
1097
- <svg
1098
- xmlns="http://www.w3.org/2000/svg"
1099
- width="24"
1100
- height="24"
1101
- viewBox="0 0 24 24"
1102
- fill="none"
1103
- stroke="currentColor"
1104
- strokeWidth="2"
1105
- strokeLinecap="round"
1106
- strokeLinejoin="round"
1107
- style="transform: ${isOutputExpanded
1108
- ? 'rotate(180deg)'
1109
- : 'rotate(0deg)'};
1110
- transition: transform 0.2s;"
1111
- >
1112
- <path d="m6 9 6 6 6-6"></path>
1113
- </svg>
1114
- </span>`
1115
- : ''}
1116
- </div>
1117
-
1118
- ${isStep && hasOutput && isOutputExpanded
1119
- ? html`<div class="${styles.outputSection}">
1120
- <div style="position: relative;">
1121
- <!-- SPECIAL CASE: Force array handling -->
1122
- ${(() => {
1123
- // For arrays specifically, render them directly
1124
- if (Array.isArray(tagsParam)) {
1125
- // Create a wrapper div to show each array item
1126
- return html`
1127
- <div class="${styles.arrayOutput}">
1128
- <ul>
1129
- ${tagsParam.map(
1130
- (item, index) => html`
1131
- <li key=${index}>
1132
- <div class="${styles.listItemContent}">
1133
- <span class="${styles.key}"
1134
- >[${index}]</span
1135
- >
1136
- ${typeof item === 'object' &&
1137
- item !== null
1138
- ? html`
1139
- <span class="${styles.value}">
1140
- ${Array.isArray(item)
1141
- ? `Array(${item.length})`
1142
- : `Object(${
1143
- Object.keys(
1144
- item as Record<
1145
- string,
1146
- unknown
1147
- >,
1148
- ).length
1149
- } keys)`}
1150
- </span>
1151
- <span
1152
- class="${styles.outputIndicator} ${styles.objectExpandIcon}"
1153
- onClick=${(e: Event) =>
1154
- toggleOutputExpand(key, e)}
1155
- title="Toggle expand output"
1156
- >
1157
- <svg
1158
- xmlns="http://www.w3.org/2000/svg"
1159
- width="24"
1160
- height="24"
1161
- viewBox="0 0 24 24"
1162
- fill="none"
1163
- stroke="currentColor"
1164
- strokeWidth="2"
1165
- strokeLinecap="round"
1166
- strokeLinejoin="round"
1167
- style="transform: ${isOutputExpanded
1168
- ? 'rotate(180deg)'
1169
- : 'rotate(0deg)'};
1170
- transition: transform 0.2s;"
1171
- >
1172
- <path d="m6 9 6 6 6-6"></path>
1173
- </svg>
1174
- </span>
1175
- `
1176
- : html`
1177
- <span class="${styles.value}">
1178
- ${String(item)}
1179
- </span>
1180
- `}
1181
- </div>
1182
- </li>
1183
- `,
1184
- )}
1185
- </ul>
1186
- </div>
1187
- `;
1188
- }
1189
-
1190
- // For objects, render keys and values
1191
- if (
1192
- typeof tagsParam === 'object' &&
1193
- tagsParam !== null
1194
- ) {
1195
- return html`
1196
- <${TagList}
1197
- tags=${tagsParam as Record<string, unknown>}
1198
- searchTerm=${searchTerm}
1199
- level=${level + 1}
1200
- path=${`${currentPath}.output`}
1201
- globalSearchMode=${globalSearchMode}
1202
- onSelect=${onSelect}
1203
- activeTab=${activeTab}
1204
- parentAppIcon=${appIconToPass}
1205
- ignoreParentKey=${childIgnoreParentKey}
1206
- />
1207
- `;
1208
- }
1209
-
1210
- // For primitive values, just show the string representation
1211
- return html`
1212
- <div style="padding: 4px; color: #666;">
1213
- ${String(tagsParam)}
1214
- </div>
1215
- `;
1216
- })()}
1217
- </div>
1218
- </div>`
1219
- : ''}
1220
- ${hasNestedSteps && isExpanded
1221
- ? html`<${TagList}
1222
- tags=${isTagNode(value) ? value.tags || {} : {}}
1223
- searchTerm=${searchTerm}
1224
- level=${level + 1}
1225
- path=${currentPath}
1226
- globalSearchMode=${globalSearchMode}
1227
- onSelect=${onSelect}
1228
- activeTab=${activeTab}
1229
- parentAppIcon=${appIconToPass}
1230
- ignoreParentKey=${value.ignoreParentKey || ignoreParentKey}
1231
- />`
1232
- : ''}
1233
- <!-- Display expanded array content with additional debug info -->
1234
- ${Array.isArray(value) && value.length > 0 && isExpanded
1235
- ? html`<div class="${styles.outputSection}">
1236
- <${TagList}
1237
- tags=${value}
1238
- searchTerm=${searchTerm}
1239
- level=${level + 1}
1240
- path=${currentPath}
1241
- globalSearchMode=${globalSearchMode}
1242
- onSelect=${onSelect}
1243
- activeTab=${activeTab}
1244
- parentAppIcon=${appIconToPass}
1245
- ignoreParentKey=${childIgnoreParentKey}
1246
- />
1247
- </div>`
1248
- : ''}
1249
-
1250
- <!-- Display expanded object content with additional debug info -->
1251
- ${!isStep &&
1252
- !Array.isArray(value) &&
1253
- typeof value === 'object' &&
1254
- value !== null &&
1255
- Object.keys(value as Record<string, unknown>).length > 0 &&
1256
- isExpanded
1257
- ? html`<div class="${styles.outputSection}">
1258
- <${TagList}
1259
- tags=${value as Record<string, unknown>}
1260
- searchTerm=${searchTerm}
1261
- level=${level + 1}
1262
- path=${currentPath}
1263
- globalSearchMode=${globalSearchMode}
1264
- onSelect=${onSelect}
1265
- activeTab=${activeTab}
1266
- parentAppIcon=${appIconToPass}
1267
- ignoreParentKey=${childIgnoreParentKey}
1268
- />
1269
- </div>`
1270
- : ''}
1271
- </li>
1272
- `;
1273
- },
1274
- )}
1275
- </ul>
1276
- `;
1277
- };
1278
-
1279
- // Update the TabMenu component to search across all tabs and pass data to TagList
1280
- const TabMenu = ({ data, onSelect, onOptionClick }: TagMenuProps) => {
1281
- const [activeTab, setActiveTab] = useState<string>(Object.keys(data)[0]);
1282
- const [searchTerm, setSearchTerm] = useState<string>('');
1283
- const [searchResults, setSearchResults] = useState<Record<string, number>>(
1284
- {},
1285
- );
1286
- const [globalSearchMode, setGlobalSearchMode] = useState<boolean>(false);
1287
-
1288
- // Search across all tabs and count matches
1289
- useEffect(() => {
1290
- if (!searchTerm) {
1291
- setSearchResults({});
1292
- setGlobalSearchMode(false);
1293
- return;
1294
- }
1295
-
1296
- const results: Record<string, number> = {};
1297
-
1298
- Object.keys(data).forEach((tabKey) => {
1299
- // Skip counting for Values tab - handle it differently
1300
- if (tabKey === 'Values') {
1301
- const valuesData = (data[tabKey] as unknown) as { values: ValueItem[] };
1302
- if (valuesData.values) {
1303
- const matches = valuesData.values.filter((item) =>
1304
- item.value.toLowerCase().includes(searchTerm.toLowerCase()),
1305
- ).length;
1306
- results[tabKey] = matches;
1307
- }
1308
- return;
1309
- }
1310
-
1311
- const matches = countSearchMatches(
1312
- data[tabKey].tags || {},
1313
- searchTerm.toLowerCase(),
1314
- );
1315
- results[tabKey] = matches;
1316
- });
1317
-
1318
- setSearchResults(results);
1319
- setGlobalSearchMode(searchTerm.length > 0);
1320
- }, [searchTerm, data]);
1321
-
1322
- const getTabIcon = (tabName: string) => {
1323
- const name = tabName.toLowerCase();
1324
-
1325
- if (name === 'values') {
1326
- return html`
1327
- <svg
1328
- xmlns="http://www.w3.org/2000/svg"
1329
- width="16"
1330
- height="16"
1331
- viewBox="0 0 24 24"
1332
- fill="none"
1333
- stroke="currentColor"
1334
- strokeWidth="2"
1335
- strokeLinecap="round"
1336
- strokeLinejoin="round"
1337
- class="mr-1"
1338
- >
1339
- <path d="M8 3H5a2 2 0 0 0-2 2v3"></path>
1340
- <path d="M21 8V5a2 2 0 0 0-2-2h-3"></path>
1341
- <path d="M3 16v3a2 2 0 0 0 2 2h3"></path>
1342
- <path d="M16 21h3a2 2 0 0 0 2-2v-3"></path>
1343
- <rect width="10" height="10" x="7" y="7" rx="2"></rect>
1344
- </svg>
1345
- `;
1346
- }
1347
-
1348
- if (name.includes('trigger')) {
1349
- return html`
1350
- <svg
1351
- xmlns="http://www.w3.org/2000/svg"
1352
- width="16"
1353
- height="16"
1354
- viewBox="0 0 24 24"
1355
- fill="none"
1356
- stroke="currentColor"
1357
- strokeWidth="2"
1358
- strokeLinecap="round"
1359
- strokeLinejoin="round"
1360
- class="mr-1"
1361
- >
1362
- <path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"></path>
1363
- </svg>
1364
- `;
1365
- }
1366
-
1367
- if (name.includes('storage') || name.includes('variable')) {
1368
- return html`
1369
- <svg
1370
- xmlns="http://www.w3.org/2000/svg"
1371
- width="16"
1372
- height="16"
1373
- viewBox="0 0 24 24"
1374
- fill="none"
1375
- stroke="currentColor"
1376
- strokeWidth="2"
1377
- strokeLinecap="round"
1378
- strokeLinejoin="round"
1379
- class="mr-1"
1380
- >
1381
- <ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>
1382
- <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"></path>
1383
- <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
1384
- </svg>
1385
- `;
1386
- }
1387
-
1388
- if (name.includes('form') || name.includes('setup')) {
1389
- return html`
1390
- <svg
1391
- xmlns="http://www.w3.org/2000/svg"
1392
- width="16"
1393
- height="16"
1394
- viewBox="0 0 24 24"
1395
- fill="none"
1396
- stroke="currentColor"
1397
- strokeWidth="2"
1398
- strokeLinecap="round"
1399
- strokeLinejoin="round"
1400
- class="mr-1"
1401
- >
1402
- <rect width="18" height="18" x="3" y="3" rx="2"></rect>
1403
- <path d="M9 9h6"></path>
1404
- <path d="M9 13h6"></path>
1405
- <path d="M9 17h6"></path>
1406
- </svg>
1407
- `;
1408
- }
1409
-
1410
- if (name.includes('auth') || name.includes('authorization')) {
1411
- return html`
1412
- <svg
1413
- xmlns="http://www.w3.org/2000/svg"
1414
- width="16"
1415
- height="16"
1416
- viewBox="0 0 24 24"
1417
- fill="none"
1418
- stroke="currentColor"
1419
- strokeWidth="2"
1420
- strokeLinecap="round"
1421
- strokeLinejoin="round"
1422
- class="mr-1"
1423
- >
1424
- <rect width="18" height="11" x="3" y="11" rx="2" ry="2"></rect>
1425
- <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
1426
- <path d="M12 16v3"></path>
1427
- </svg>
1428
- `;
1429
- }
1430
-
1431
- if (name.includes('parameter')) {
1432
- return html`
1433
- <svg
1434
- xmlns="http://www.w3.org/2000/svg"
1435
- width="20"
1436
- height="20"
1437
- viewBox="0 0 24 24"
1438
- fill="none"
1439
- stroke="currentColor"
1440
- stroke-width="2"
1441
- stroke-linecap="round"
1442
- stroke-linejoin="round"
1443
- class="lucide lucide-variable"
1444
- >
1445
- <path d="M8 21s-4-3-4-9 4-9 4-9" />
1446
- <path d="M16 3s4 3 4 9-4 9-4 9" />
1447
- <line x1="15" x2="9" y1="9" y2="15" />
1448
- <line x1="9" x2="15" y1="9" y2="15" />
1449
- </svg>
1450
- `;
1451
- }
1452
-
1453
- // Default icon
1454
- return html`
1455
- <svg
1456
- xmlns="http://www.w3.org/2000/svg"
1457
- width="16"
1458
- height="16"
1459
- viewBox="0 0 24 24"
1460
- fill="none"
1461
- stroke="currentColor"
1462
- strokeWidth="2"
1463
- strokeLinecap="round"
1464
- strokeLinejoin="round"
1465
- class="mr-1"
1466
- >
1467
- <path
1468
- d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"
1469
- ></path>
1470
- </svg>
1471
- `;
1472
- };
1473
-
1474
- const renderTabs = () =>
1475
- html`
1476
- <div class="${styles.tabsWrapper}">
1477
- ${Object.keys(data).map(
1478
- (key) => html`
1479
- <div
1480
- class="${styles.tab} ${activeTab === key
1481
- ? styles.activeTab
1482
- : ''} ${searchResults[key] > 0 ? styles.tabWithResults : ''}"
1483
- onClick=${() => setActiveTab(key)}
1484
- >
1485
- ${getTabIcon(data[key].name || key)} ${data[key].name || key}
1486
- ${searchResults[key] > 0
1487
- ? html`<span class="${styles.resultBadge}"
1488
- >${searchResults[key]}</span
1489
- >`
1490
- : ''}
1491
- </div>
1492
- `,
1493
- )}
1494
- </div>
1495
- `;
1496
-
1497
- const renderContent = () => {
1498
- // Special handling for Values tab
1499
- if (activeTab === 'Values') {
1500
- const valuesData = (data[activeTab] as unknown) as {
1501
- values: ValueItem[];
1502
- };
1503
- const filteredValues = searchTerm
1504
- ? valuesData.values.filter((item) =>
1505
- item.value.toLowerCase().includes(searchTerm.toLowerCase()),
1506
- )
1507
- : valuesData.values;
1508
-
1509
- return html`
1510
- <div class="${styles.tabContent}">
1511
- <div class="${styles.searchWrapper}">
1512
- <input
1513
- type="text"
1514
- placeholder="Search values..."
1515
- value=${searchTerm}
1516
- onInput=${(e: Event) =>
1517
- setSearchTerm((e.target as HTMLInputElement).value)}
1518
- />
1519
- ${searchTerm
1520
- ? html`
1521
- <button
1522
- class="${styles.clearSearch}"
1523
- onClick=${() => setSearchTerm('')}
1524
- title="Clear search"
1525
- >
1526
- <svg
1527
- xmlns="http://www.w3.org/2000/svg"
1528
- width="16"
1529
- height="16"
1530
- viewBox="0 0 24 24"
1531
- fill="none"
1532
- stroke="currentColor"
1533
- strokeWidth="2"
1534
- strokeLinecap="round"
1535
- strokeLinejoin="round"
1536
- >
1537
- <line x1="18" y1="6" x2="6" y2="18"></line>
1538
- <line x1="6" y1="6" x2="18" y2="18"></line>
1539
- </svg>
1540
- </button>
1541
- `
1542
- : ''}
1543
- </div>
1544
- <div class="${styles.tagsListWrapper}">
1545
- <${ValuesList}
1546
- values=${filteredValues}
1547
- onSelect=${onSelect}
1548
- onOptionClick=${onOptionClick}
1549
- />
1550
- </div>
1551
- </div>
1552
- `;
1553
- }
1554
-
1555
- // Regular tab handling
1556
- const activeData = data[activeTab];
1557
- const steps = activeData.tags || [];
1558
- const hasSingleEmptyStep =
1559
- !Array.isArray(steps) && // Handle the case where steps is an object
1560
- Object.keys(steps).length === 1 &&
1561
- isTagNode(Object.values(steps)[0]) &&
1562
- Object.keys((Object.values(steps)[0] as TagNode).output || {}).length ===
1563
- 0;
1564
- return html`
1565
- <div class="${styles.tabContent}">
1566
- <div class="${styles.searchWrapper}">
1567
- <input
1568
- type="text"
1569
- placeholder="Search across all steps and fields..."
1570
- value=${searchTerm}
1571
- onInput=${(e: Event) =>
1572
- setSearchTerm((e.target as HTMLInputElement).value)}
1573
- />
1574
- ${searchTerm
1575
- ? html`
1576
- <button
1577
- class="${styles.clearSearch}"
1578
- onClick=${() => setSearchTerm('')}
1579
- title="Clear search"
1580
- >
1581
- <svg
1582
- xmlns="http://www.w3.org/2000/svg"
1583
- width="16"
1584
- height="16"
1585
- viewBox="0 0 24 24"
1586
- fill="none"
1587
- stroke="currentColor"
1588
- strokeWidth="2"
1589
- strokeLinecap="round"
1590
- strokeLinejoin="round"
1591
- >
1592
- <line x1="18" y1="6" x2="6" y2="18"></line>
1593
- <line x1="6" y1="6" x2="18" y2="18"></line>
1594
- </svg>
1595
- </button>
1596
- `
1597
- : ''}
1598
- </div>
1599
- ${hasSingleEmptyStep
1600
- ? html`<div class="${styles.emptyStep}">
1601
- <span>No tags found</span>
1602
- </div>`
1603
- : html` <div class="${styles.tagsListWrapper}">
1604
- <${TagList}
1605
- tags=${activeData.tags}
1606
- searchTerm=${searchTerm}
1607
- globalSearchMode=${globalSearchMode}
1608
- onSelect=${onSelect}
1609
- activeTab=${data[activeTab].machineName || activeTab}
1610
- parentAppIcon=${isTagNode(activeData)
1611
- ? activeData.appIcon
1612
- : undefined}
1613
- ignoreParentKey=${false}
1614
- />
1615
- </div>`}
1616
- </div>
1617
- `;
1618
- };
1619
-
1620
- return html`<div>${renderTabs()} ${renderContent()}</div>`;
1621
- };
1622
-
1623
- // Function to convert TagData to include the Values tab
1624
- function convertTagsToObject(tagData: Record<string, unknown>): TagData {
1625
- const result: TagData = {};
1626
-
1627
- Object.keys(tagData).forEach((key) => {
1628
- const section = tagData[key] as TagNode;
1629
- const newSection: TagNode = {
1630
- ...section,
1631
- };
1632
-
1633
- // Convert tags array to object if needed
1634
- if (section.tags && Array.isArray(section.tags)) {
1635
- const tagsObject: Record<string, TagNode> = {};
1636
-
1637
- section.tags.forEach((tag: TagNode, index: number) => {
1638
- // Use machineName as key if available, otherwise use index
1639
- const tagKey = tag.machineName || `[${index}]`;
1640
-
1641
- // Recursively convert nested tags
1642
- if (tag.tags && Array.isArray(tag.tags)) {
1643
- tagsObject[tagKey] = {
1644
- ...tag,
1645
- tags: convertNestedTagsToObject(tag.tags),
1646
- };
1647
- } else {
1648
- tagsObject[tagKey] = tag;
1649
- }
1650
- });
1651
-
1652
- newSection.tags = tagsObject;
1653
- }
1654
-
1655
- result[key] = newSection;
1656
- });
1657
-
1658
- return result;
1659
- }
1660
-
1661
- // Update the TagsMenu function to add the Values tab
1662
- export function TagsMenu({
1663
- tagsTree,
1664
- onSelect,
1665
- renderValuesTab,
1666
- options,
1667
- onOptionClick,
1668
- }: TagsMenuProps) {
1669
- let modifiedData = convertTagsToObject(tagsTree);
1670
-
1671
- if (
1672
- renderValuesTab &&
1673
- options &&
1674
- Array.isArray(options) &&
1675
- options.length > 0
1676
- ) {
1677
- // Add the Values tab with sample data
1678
- // In a real implementation, this would come from props
1679
- modifiedData = {
1680
- Values: {
1681
- name: 'Values',
1682
- machineName: 'values',
1683
- values: options,
1684
- } as TagNode,
1685
- ...modifiedData, // Spread the remaining tabs after "Values"
1686
- };
1687
- }
1688
- return html`
1689
- <div class="${styles.tagsMenuWrapper}">
1690
- <${TabMenu}
1691
- data=${modifiedData}
1692
- onSelect=${onSelect}
1693
- onOptionClick=${onOptionClick}
1694
- />
1695
- </div>
1696
- `;
1697
- }