@parallelworks/ui 0.19.0 → 0.19.1

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 (217) hide show
  1. package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
  2. package/dist/ai/adapter/mock/index.js +2 -80
  3. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  4. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  5. package/dist/ai/adapter/openai/errors.js +37 -0
  6. package/dist/ai/adapter/openai/index.js +5 -333
  7. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  8. package/dist/ai/adapter/openai/responses.js +108 -0
  9. package/dist/ai/adapter/openai/sse.js +112 -0
  10. package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
  11. package/dist/ai/agent/classifier.js +12 -0
  12. package/dist/ai/agent/diff.js +223 -0
  13. package/dist/ai/agent/diffHighlight.js +101 -0
  14. package/dist/ai/agent/permissions.js +29 -0
  15. package/dist/ai/agent/toolfmt.js +383 -0
  16. package/dist/ai/agent/transcript.js +127 -0
  17. package/dist/ai/components/AllocationSelector.js +56 -0
  18. package/dist/ai/components/AttachmentManager.js +144 -0
  19. package/dist/ai/components/AttachmentUpload.js +179 -0
  20. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  21. package/dist/ai/components/BranchNavigator.js +57 -0
  22. package/dist/ai/components/ChatEmptyState.js +171 -0
  23. package/dist/ai/components/ChatInput.js +265 -0
  24. package/dist/ai/components/ChatLayout.js +15 -0
  25. package/dist/ai/components/ChatMessage.js +338 -0
  26. package/dist/ai/components/ChatMessageList.js +301 -0
  27. package/dist/ai/components/ChatSidebar.js +345 -0
  28. package/dist/ai/components/ChatThread.js +198 -0
  29. package/dist/ai/components/ComposerChrome.js +50 -0
  30. package/dist/ai/components/ComposerFrame.js +33 -0
  31. package/dist/ai/components/DragOverlay.js +20 -0
  32. package/dist/ai/components/ModelSelector.js +343 -0
  33. package/dist/ai/components/ShareDialog.js +260 -0
  34. package/dist/ai/components/SlashMenu.js +91 -0
  35. package/dist/ai/components/agent/ActivityLine.js +151 -0
  36. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  37. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  38. package/dist/ai/components/attachmentKeys.js +10 -0
  39. package/dist/ai/core/ChatProvider.js +848 -0
  40. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  41. package/dist/ai/core/chatReducer.js +223 -0
  42. package/dist/ai/core/config.js +45 -0
  43. package/dist/ai/core/events.js +4 -0
  44. package/dist/ai/core/exportConversation.js +42 -0
  45. package/dist/ai/core/greeting.js +38 -0
  46. package/dist/ai/core/parts.js +84 -0
  47. package/dist/ai/core/useDragDrop.js +36 -0
  48. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  49. package/dist/ai/core/useSSEStream.js +98 -0
  50. package/dist/ai/index.js +43 -6644
  51. package/dist/ai/strings.js +175 -0
  52. package/dist/ai/ui/Avatar.js +35 -0
  53. package/dist/ai/ui/Dropdown.js +110 -0
  54. package/dist/ai/ui/Markdown.js +79 -0
  55. package/dist/ai/ui/Notice.js +77 -0
  56. package/dist/ai/ui/codeBreaks.js +36 -0
  57. package/dist/ai/ui/prose.js +13 -0
  58. package/dist/ai/ui/sidebar.js +148 -0
  59. package/dist/ai/utils.js +23 -0
  60. package/dist/components/AddMenu.js +46 -0
  61. package/dist/components/Avatar.js +46 -0
  62. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  63. package/dist/components/Breadcrumbs.js +83 -0
  64. package/dist/components/Button.js +83 -0
  65. package/dist/components/Callout.js +23 -0
  66. package/dist/components/Card.js +31 -0
  67. package/dist/components/CollapsiblePanel.js +77 -0
  68. package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
  69. package/dist/components/CopyToClipboard.js +81 -0
  70. package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
  71. package/dist/components/DescriptionList.js +42 -0
  72. package/dist/components/Dropdown.js +349 -0
  73. package/dist/components/EmptyState.js +27 -0
  74. package/dist/components/Filter.js +32 -0
  75. package/dist/components/FilterPill.js +13 -0
  76. package/dist/components/IconButton.js +34 -0
  77. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  78. package/dist/components/Input.js +88 -0
  79. package/dist/components/LetterBadge.js +13 -0
  80. package/dist/components/Listbox.js +123 -0
  81. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  82. package/dist/components/Markdown.js +15 -0
  83. package/dist/components/MultiSelect.js +171 -0
  84. package/dist/components/Overview.js +39 -0
  85. package/dist/components/PageHeader.js +194 -0
  86. package/dist/components/Pagination.js +35 -0
  87. package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +1 -1
  88. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  89. package/dist/components/SectionHeader.js +11 -0
  90. package/dist/components/SettingModeOption.js +30 -0
  91. package/dist/components/SettingRow.js +35 -0
  92. package/dist/components/SettingsCard.js +31 -0
  93. package/dist/components/SettingsGroup.js +17 -0
  94. package/dist/components/Sort.js +42 -0
  95. package/dist/components/StatusBadge.js +63 -0
  96. package/dist/components/SwitchToggle.js +59 -0
  97. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  98. package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
  99. package/dist/components/Toggle.js +20 -0
  100. package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
  101. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  102. package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
  103. package/dist/components/ghostButton.js +7 -0
  104. package/dist/components/inputClasses.js +4 -0
  105. package/dist/components/keys.js +27 -0
  106. package/dist/components/relativeTime.js +32 -0
  107. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  108. package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
  109. package/dist/editor/Editor.js +13 -0
  110. package/dist/editor/EditorField.js +53 -0
  111. package/dist/editor/FormCodePanel.js +173 -0
  112. package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +4 -2
  113. package/dist/editor/index.js +6 -1
  114. package/dist/editor/themes.js +91 -0
  115. package/dist/editor/workers.js +29 -0
  116. package/dist/editor/yaml.js +15 -0
  117. package/dist/file-explorer/FileExplorer.js +1402 -0
  118. package/dist/file-explorer/FileExplorerContext.js +370 -0
  119. package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  120. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  121. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  122. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  123. package/dist/file-explorer/FilePreview/index.js +266 -0
  124. package/dist/file-explorer/FilePreview/parse.js +63 -0
  125. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  126. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  127. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  128. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  129. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  130. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  131. package/dist/file-explorer/FileRow.js +165 -0
  132. package/dist/file-explorer/FileRowsWindow.js +92 -0
  133. package/dist/file-explorer/FileTable.js +172 -0
  134. package/dist/file-explorer/FileTableHeaders.js +49 -0
  135. package/dist/file-explorer/LoadMoreRow.js +46 -0
  136. package/dist/file-explorer/TreeView.js +376 -0
  137. package/dist/file-explorer/helpers.js +537 -0
  138. package/dist/file-explorer/index.js +7 -5671
  139. package/dist/file-explorer/lib/batch.js +39 -0
  140. package/dist/file-explorer/lib/errors.js +9 -0
  141. package/dist/file-explorer/lib/paging.js +124 -0
  142. package/dist/file-explorer/lib/utils.js +322 -0
  143. package/dist/file-explorer/toasts.js +400 -0
  144. package/dist/file-explorer/treeRows.js +73 -0
  145. package/dist/file-explorer/useNearEnd.js +27 -0
  146. package/dist/form/FieldWrapper.js +54 -0
  147. package/dist/form/Fields/BooleanField.js +51 -0
  148. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  149. package/dist/form/Fields/ColorField.js +33 -0
  150. package/dist/form/Fields/DropdownField.js +49 -0
  151. package/dist/form/Fields/DurationField.js +130 -0
  152. package/dist/form/Fields/LabelField.js +19 -0
  153. package/dist/form/Fields/MultiDropdownField.js +40 -0
  154. package/dist/form/Fields/NumberField.js +51 -0
  155. package/dist/form/Fields/ObjectField.js +54 -0
  156. package/dist/form/Fields/RadioField.js +49 -0
  157. package/dist/form/Fields/RangeField.js +58 -0
  158. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  159. package/dist/form/Fields/StepField.js +6 -0
  160. package/dist/form/Fields/StringField.js +37 -0
  161. package/dist/form/Fields/TextAreaField.js +31 -0
  162. package/dist/form/Fields/durationValidity.js +11 -0
  163. package/dist/form/Form.js +643 -0
  164. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  165. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  166. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  167. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  168. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  169. package/dist/form/Wizard/WizardContainer.js +138 -0
  170. package/dist/form/Wizard/WizardNavigation.js +92 -0
  171. package/dist/form/Wizard/WizardStepContent.js +35 -0
  172. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  173. package/dist/form/Wizard/useWizardState.js +118 -0
  174. package/dist/form/Wizard/utils.js +34 -0
  175. package/dist/form/fieldContext.js +26 -0
  176. package/dist/form/fieldRegistry.js +50 -0
  177. package/dist/form/index.js +17 -2321
  178. package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
  179. package/dist/form/useParsedOpts.js +62 -0
  180. package/dist/form/usePrevious.js +11 -0
  181. package/dist/form/utils/checkShowIfObject.js +14 -0
  182. package/dist/form/utils/duration.js +69 -0
  183. package/dist/form/utils/getParentValue.js +23 -0
  184. package/dist/form/utils/getPlaceholder.js +9 -0
  185. package/dist/form/utils/getValueUsingPath.js +23 -0
  186. package/dist/form/utils/secondaryField.js +22 -0
  187. package/dist/graph/AnnotationBanner.js +141 -0
  188. package/dist/graph/Collapse.js +41 -0
  189. package/dist/graph/DependencyGraph.js +1398 -0
  190. package/dist/graph/JobSummary.js +104 -0
  191. package/dist/graph/MatrixGroup.js +107 -0
  192. package/dist/graph/Reveal.js +57 -0
  193. package/dist/graph/TreeView.js +711 -0
  194. package/dist/graph/index.js +1 -2519
  195. package/dist/graph/types.js +6 -0
  196. package/dist/index.js +46 -599
  197. package/dist/list/ActionToolbar.js +184 -0
  198. package/dist/list/HoverCard.js +73 -0
  199. package/dist/list/ListPage.js +145 -0
  200. package/dist/list/ListPager.js +59 -0
  201. package/dist/list/ListTable.js +163 -0
  202. package/dist/list/ListViewControls.js +372 -0
  203. package/dist/list/RowContextMenu.js +350 -0
  204. package/dist/list/UserHoverCard.js +117 -0
  205. package/dist/list/index.js +11 -2
  206. package/dist/list/listSearch.js +137 -0
  207. package/dist/list/listView.js +210 -0
  208. package/dist/list/textEntry.js +10 -0
  209. package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
  210. package/dist/logviewer/index.js +2 -1
  211. package/dist/logviewer/segments.js +80 -0
  212. package/package.json +1 -1
  213. package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
  214. package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
  215. package/dist/chunks/editor-Dk1rbV75.js +0 -361
  216. package/dist/chunks/list-CJm875m7.js +0 -1418
  217. /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
@@ -1,52 +1,4 @@
1
- import { t as RequiredMark } from "./RequiredMark-DfLdYbYZ.js";
2
- import cx from "classnames";
3
- import { createContext, useContext, useId, useMemo } from "react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
5
- //#region src/form/fieldContext.tsx
6
- var FieldContext = createContext({ required: false });
7
- var FieldProvider = FieldContext.Provider;
8
- /** True when the surrounding FieldWrapper is showing the required asterisk. */
9
- function useFieldRequired() {
10
- return useContext(FieldContext).required;
11
- }
12
- /** Ties the single focusable control of a field to its FieldWrapper label. */
13
- function useFieldControlProps() {
14
- const { id, descriptionId } = useContext(FieldContext);
15
- return {
16
- id,
17
- "aria-describedby": descriptionId
18
- };
19
- }
20
- /** For controls and groups that can only be named through aria-labelledby. */
21
- function useFieldLabelledByProps() {
22
- const { labelId, descriptionId } = useContext(FieldContext);
23
- return {
24
- "aria-labelledby": labelId,
25
- "aria-describedby": descriptionId
26
- };
27
- }
28
- //#endregion
29
- //#region src/form/utils/secondaryField.ts
30
- function findSecondaryOption(options, value) {
31
- for (const candidate of options) {
32
- if (!candidate || typeof candidate !== "object") continue;
33
- const option = candidate;
34
- if (option.value === value) return option;
35
- if (Array.isArray(option.options)) {
36
- const nestedOption = findSecondaryOption(option.options, value);
37
- if (nestedOption) return nestedOption;
38
- }
39
- }
40
- }
41
- function applySecondaryField(secondaryField, secondaryValue, setFieldValue) {
42
- if (secondaryField === void 0 || secondaryValue === void 0) return;
43
- const fields = Array.isArray(secondaryField) ? secondaryField : [secondaryField];
44
- const values = Array.isArray(secondaryValue) ? secondaryValue : [secondaryValue];
45
- fields.forEach((field, index) => {
46
- setFieldValue(field, values[index]);
47
- });
48
- }
49
- //#endregion
1
+ import { applySecondaryField, findSecondaryOption } from "./utils/secondaryField.js";
50
2
  //#region src/form/lib.ts
51
3
  var EMPTY_ENTRY = {};
52
4
  function asRecord(value) {
@@ -201,51 +153,4 @@ function initializeValues(options, srcData = {}, blankDefault) {
201
153
  }, data);
202
154
  }
203
155
  //#endregion
204
- //#region src/form/FieldWrapper.tsx
205
- function FieldWrapper({ label, tooltipComponent, description, labelPosition = "left", spaceCompact = false, optional = false, children }) {
206
- const isOptional = Boolean(resolvedFlag(optional));
207
- const uid = useId();
208
- const id = `${uid}control`;
209
- const labelId = `${uid}label`;
210
- const descriptionId = description ? `${uid}description` : void 0;
211
- const field = useMemo(() => ({
212
- required: !isOptional,
213
- id,
214
- labelId,
215
- descriptionId
216
- }), [
217
- isOptional,
218
- id,
219
- labelId,
220
- descriptionId
221
- ]);
222
- return /* @__PURE__ */ jsxs("div", {
223
- className: cx("flex w-full", labelPosition === "left" ? "items-start" : "items-left flex-col"),
224
- children: [/* @__PURE__ */ jsxs("label", {
225
- htmlFor: id,
226
- id: labelId,
227
- className: cx("relative", labelPosition === "left" ? "form-label" : "form-label-top", spaceCompact && "form-label-compact"),
228
- children: [
229
- label,
230
- !isOptional && /* @__PURE__ */ jsx(RequiredMark, {}),
231
- tooltipComponent
232
- ]
233
- }), /* @__PURE__ */ jsxs("div", {
234
- className: "w-full",
235
- children: [/* @__PURE__ */ jsx(FieldProvider, {
236
- value: field,
237
- children: typeof children === "function" ? children({
238
- id,
239
- labelId,
240
- describedBy: descriptionId
241
- }) : children
242
- }), description && /* @__PURE__ */ jsx("div", {
243
- id: descriptionId,
244
- className: "text-xs theme-muted-text mt-1 leading-relaxed",
245
- children: description
246
- })]
247
- })]
248
- });
249
- }
250
- //#endregion
251
- export { initializeValues as a, findSecondaryOption as c, useFieldLabelledByProps as d, useFieldRequired as f, impureSetValueFromPath as i, FieldProvider as l, enforceOneMustBeTrue as n, resolvedFlag as o, flattenGroups as r, applySecondaryField as s, FieldWrapper as t, useFieldControlProps as u };
156
+ export { enforceOneMustBeTrue, flattenGroups, impureSetValueFromPath, initializeValues, resolvedFlag };
@@ -0,0 +1,62 @@
1
+ import { useWorkflowEngine } from "../components/Provider.js";
2
+ import { useRef } from "react";
3
+ import deepEqual from "fast-deep-equal";
4
+ //#region src/form/useParsedOpts.ts
5
+ var EMPTY_VARS = {};
6
+ var EMPTY_KEYS = [];
7
+ /**
8
+ * useMemo won't work here — Formik values changes on every keystroke, so this hook extracts which inputs.* keys the schema references and re-parses only when those change. Defaults `userVars`/`secretKeys` to empty — callers in React scope should pass them from `useUserVars()` so the parser leaves `${{ var.SECRET }}` literal during template eval (otherwise the recursive substitution turns `"https://${{ var.PAT }}@host/"` into `"https://@host/"`).
9
+ */
10
+ function useParsedOpts(rawOptions, values, organizationVariables, userVars = EMPTY_VARS, secretKeys = EMPTY_KEYS, remoteVars = EMPTY_VARS) {
11
+ const engine = useWorkflowEngine();
12
+ const c = useRef({
13
+ rawOptions: null,
14
+ orgVars: void 0,
15
+ userVars: null,
16
+ secretKeys: null,
17
+ remoteVars: null,
18
+ converted: {},
19
+ inputDeps: /* @__PURE__ */ new Set(),
20
+ hasExpressions: false,
21
+ relevantSnapshot: {},
22
+ result: null
23
+ }).current;
24
+ if (rawOptions !== c.rawOptions) {
25
+ c.rawOptions = rawOptions;
26
+ c.converted = engine.convertInputs(rawOptions);
27
+ const { inputDeps, hasExpressions } = engine.inputDependencies(c.converted);
28
+ c.inputDeps = inputDeps;
29
+ c.hasExpressions = hasExpressions;
30
+ c.result = null;
31
+ }
32
+ if (organizationVariables !== c.orgVars || userVars !== c.userVars || secretKeys !== c.secretKeys || remoteVars !== c.remoteVars) {
33
+ c.orgVars = organizationVariables;
34
+ c.userVars = userVars;
35
+ c.secretKeys = secretKeys;
36
+ c.remoteVars = remoteVars;
37
+ c.result = null;
38
+ }
39
+ if (c.result !== null) {
40
+ if (c.inputDeps.size === 0) return c.result;
41
+ let inputsChanged = false;
42
+ for (const key of c.inputDeps) if (!deepEqual(values[key], c.relevantSnapshot[key])) {
43
+ inputsChanged = true;
44
+ break;
45
+ }
46
+ if (!inputsChanged) return c.result;
47
+ }
48
+ const parsed = engine.evaluate({
49
+ inputs: values,
50
+ obj: c.converted,
51
+ orgVars: organizationVariables,
52
+ userVars,
53
+ secretKeys,
54
+ remoteVars
55
+ });
56
+ c.result = parsed;
57
+ c.relevantSnapshot = {};
58
+ for (const key of c.inputDeps) c.relevantSnapshot[key] = values[key];
59
+ return parsed;
60
+ }
61
+ //#endregion
62
+ export { useParsedOpts };
@@ -0,0 +1,11 @@
1
+ import { useEffect, useRef } from "react";
2
+ //#region src/form/usePrevious.ts
3
+ function usePrevious(value) {
4
+ const ref = useRef(void 0);
5
+ useEffect(() => {
6
+ ref.current = value;
7
+ });
8
+ return ref.current;
9
+ }
10
+ //#endregion
11
+ export { usePrevious };
@@ -0,0 +1,14 @@
1
+ import { getValueUsingPath } from "./getValueUsingPath.js";
2
+ //#region src/form/utils/checkShowIfObject.ts
3
+ function checkShowIfObject(showIfObject, formValues, index) {
4
+ const valueList = [];
5
+ for (let [key, value] of Object.entries(showIfObject)) {
6
+ if (index !== void 0) key = key.replace("[index]", `[${index}]`);
7
+ const dependsOnValue = getValueUsingPath(formValues, key);
8
+ if (typeof value === "boolean" || typeof value === "string" || typeof value === "number") valueList.push(dependsOnValue !== null && dependsOnValue !== void 0 && dependsOnValue.toString() === value.toString());
9
+ else if (Array.isArray(value)) valueList.push(value.includes(dependsOnValue));
10
+ }
11
+ return valueList;
12
+ }
13
+ //#endregion
14
+ export { checkShowIfObject };
@@ -0,0 +1,69 @@
1
+ import { Duration } from "luxon";
2
+ //#region src/form/utils/duration.ts
3
+ var WITH_DAYS = /^(\d+)-(\d{1,2})(?::(\d{1,2})(?::(\d{1,2}))?)?$/;
4
+ var WITHOUT_DAYS = /^(\d+):(\d{1,2}):(\d{1,2})$/;
5
+ function parseDuration(text) {
6
+ const trimmed = text.trim();
7
+ let days = 0;
8
+ let hours;
9
+ let minutes;
10
+ let seconds;
11
+ const withDays = trimmed.match(WITH_DAYS);
12
+ if (withDays) {
13
+ days = Number(withDays[1]);
14
+ hours = Number(withDays[2]);
15
+ minutes = Number(withDays[3] ?? 0);
16
+ seconds = Number(withDays[4] ?? 0);
17
+ if (hours > 23) return null;
18
+ } else {
19
+ const withoutDays = trimmed.match(WITHOUT_DAYS);
20
+ if (!withoutDays) return null;
21
+ hours = Number(withoutDays[1]);
22
+ minutes = Number(withoutDays[2]);
23
+ seconds = Number(withoutDays[3]);
24
+ }
25
+ if (minutes > 59 || seconds > 59) return null;
26
+ return days * 86400 + hours * 3600 + minutes * 60 + seconds;
27
+ }
28
+ function formatDuration(totalSeconds) {
29
+ if (!Number.isFinite(totalSeconds) || totalSeconds < 0) return "";
30
+ const parts = Duration.fromObject({ seconds: Math.floor(totalSeconds) }).shiftTo("days", "hours", "minutes", "seconds");
31
+ const pad = (n) => String(n).padStart(2, "0");
32
+ const time = `${pad(parts.hours)}:${pad(parts.minutes)}:${pad(parts.seconds)}`;
33
+ return parts.days > 0 ? `${parts.days}-${time}` : time;
34
+ }
35
+ var FLEX_MAX_DURATION_RANGE = {
36
+ min: 600,
37
+ max: 604800
38
+ };
39
+ var FLEX_WAIT_TIME_RANGE = {
40
+ min: 30,
41
+ max: 604800
42
+ };
43
+ var STANDARD_MAX_DURATION_RANGE = {
44
+ min: 30,
45
+ max: 10368e3
46
+ };
47
+ var DURATION_PATH = /^partitions\[\d+\]\.(maxDuration|flexStartWaitTime|suspendTime)$/;
48
+ function collectPartitionDurationIssues(partitions, invalidDurationPaths) {
49
+ const issues = new Set(invalidDurationPaths.filter((path) => DURATION_PATH.test(path)));
50
+ (partitions ?? []).forEach((partition, i) => {
51
+ const p = partition;
52
+ const check = (fieldName, range, required) => {
53
+ const raw = p?.[fieldName];
54
+ if (raw === void 0 || raw === null || raw === "") {
55
+ if (required) issues.add(`partitions[${i}].${fieldName}`);
56
+ return;
57
+ }
58
+ const value = Number(raw);
59
+ if (!Number.isFinite(value) || value < range.min || value > range.max) issues.add(`partitions[${i}].${fieldName}`);
60
+ };
61
+ if (p?.provisioningMode === "flex") {
62
+ check("maxDuration", FLEX_MAX_DURATION_RANGE, true);
63
+ check("flexStartWaitTime", FLEX_WAIT_TIME_RANGE, true);
64
+ } else check("maxDuration", STANDARD_MAX_DURATION_RANGE, false);
65
+ });
66
+ return [...issues];
67
+ }
68
+ //#endregion
69
+ export { FLEX_MAX_DURATION_RANGE, FLEX_WAIT_TIME_RANGE, STANDARD_MAX_DURATION_RANGE, collectPartitionDurationIssues, formatDuration, parseDuration };
@@ -0,0 +1,23 @@
1
+ import { getValueUsingPath } from "./getValueUsingPath.js";
2
+ import { checkShowIfObject } from "./checkShowIfObject.js";
3
+ //#region src/form/utils/getParentValue.ts
4
+ function getParentValue(index, targetField, values, dependentPath, field) {
5
+ let parentValue;
6
+ if (typeof targetField === "object" && targetField !== null && !Array.isArray(targetField)) parentValue = !checkShowIfObject(targetField, values, index).includes(false);
7
+ else if (field.depends_on) {
8
+ dependentPath = field.depends_on;
9
+ if (index !== void 0) dependentPath = field.depends_on.replace("[index]", `[${index}]`);
10
+ const dependsOnValue = getValueUsingPath(values, dependentPath);
11
+ const dependsOnText = dependsOnValue === null || dependsOnValue === void 0 ? void 0 : String(dependsOnValue);
12
+ if (Array.isArray(targetField)) parentValue = targetField.includes(dependsOnValue) || targetField.includes(dependsOnText);
13
+ else if (typeof targetField === "string") parentValue = dependsOnText !== void 0 && targetField.includes(dependsOnText);
14
+ else parentValue = targetField === dependsOnValue;
15
+ } else {
16
+ dependentPath = typeof targetField === "string" ? targetField : "";
17
+ if (index !== void 0 && typeof targetField === "string") dependentPath = targetField.replace("[index]", `[${index}]`);
18
+ parentValue = getValueUsingPath(values, dependentPath);
19
+ }
20
+ return parentValue;
21
+ }
22
+ //#endregion
23
+ export { getParentValue };
@@ -0,0 +1,9 @@
1
+ //#region src/form/utils/getPlaceholder.ts
2
+ /** `placeholder=""` (empty string) intentionally overrides the default; undefined does not. */
3
+ function getPlaceholder(placeholder, defaultValue) {
4
+ if (placeholder !== void 0) return placeholder;
5
+ if (defaultValue && (typeof defaultValue === "string" || typeof defaultValue === "number")) return defaultValue.toString();
6
+ return "";
7
+ }
8
+ //#endregion
9
+ export { getPlaceholder };
@@ -0,0 +1,23 @@
1
+ //#region src/form/utils/getValueUsingPath.ts
2
+ function getValueUsingPath(obj, path) {
3
+ if (typeof path !== "string" || !path) return;
4
+ const keys = path.split(".");
5
+ let current = obj;
6
+ for (const key of keys) {
7
+ if (!current || typeof current !== "object") return;
8
+ const container = current;
9
+ if (key.includes("[")) {
10
+ const [arrayKey = "", indexStr = ""] = key.split("[");
11
+ const index = parseInt(indexStr.slice(0, -1), 10);
12
+ const list = container[arrayKey];
13
+ if (!Array.isArray(list) || isNaN(index)) return;
14
+ current = list[index];
15
+ } else {
16
+ if (!(key in container)) return;
17
+ current = container[key];
18
+ }
19
+ }
20
+ return current;
21
+ }
22
+ //#endregion
23
+ export { getValueUsingPath };
@@ -0,0 +1,22 @@
1
+ //#region src/form/utils/secondaryField.ts
2
+ function findSecondaryOption(options, value) {
3
+ for (const candidate of options) {
4
+ if (!candidate || typeof candidate !== "object") continue;
5
+ const option = candidate;
6
+ if (option.value === value) return option;
7
+ if (Array.isArray(option.options)) {
8
+ const nestedOption = findSecondaryOption(option.options, value);
9
+ if (nestedOption) return nestedOption;
10
+ }
11
+ }
12
+ }
13
+ function applySecondaryField(secondaryField, secondaryValue, setFieldValue) {
14
+ if (secondaryField === void 0 || secondaryValue === void 0) return;
15
+ const fields = Array.isArray(secondaryField) ? secondaryField : [secondaryField];
16
+ const values = Array.isArray(secondaryValue) ? secondaryValue : [secondaryValue];
17
+ fields.forEach((field, index) => {
18
+ setFieldValue(field, values[index]);
19
+ });
20
+ }
21
+ //#endregion
22
+ export { applySecondaryField, findSecondaryOption };
@@ -0,0 +1,141 @@
1
+ import { ChevronDownIcon, ChevronRightIcon, ErrorIcon, InfoIcon, WarningIcon } from "../icons.js";
2
+ import { keyedByContent } from "../components/keys.js";
3
+ import cx from "classnames";
4
+ import { useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/graph/AnnotationBanner.tsx
7
+ var typeOrder = {
8
+ error: 0,
9
+ warning: 1,
10
+ notice: 2
11
+ };
12
+ var typeConfig = {
13
+ error: {
14
+ icon: ErrorIcon,
15
+ label: "Error",
16
+ accentClass: "text-red-500",
17
+ bgClass: "bg-red-500/5 dark:bg-red-500/10",
18
+ countBg: "bg-red-500/15 text-red-700 dark:text-red-400"
19
+ },
20
+ warning: {
21
+ icon: WarningIcon,
22
+ label: "Warning",
23
+ accentClass: "text-yellow-500",
24
+ bgClass: "bg-yellow-500/5 dark:bg-yellow-500/10",
25
+ countBg: "bg-yellow-500/15 text-yellow-700 dark:text-yellow-400"
26
+ },
27
+ notice: {
28
+ icon: InfoIcon,
29
+ label: "Notice",
30
+ accentClass: "text-blue-500",
31
+ bgClass: "bg-blue-500/5 dark:bg-blue-500/10",
32
+ countBg: "bg-blue-500/15 text-blue-700 dark:text-blue-400"
33
+ }
34
+ };
35
+ function collectAnnotations(executedJobs, parentPath) {
36
+ const annotations = [];
37
+ for (const [jobName, job] of Object.entries(executedJobs)) {
38
+ const fullJobName = parentPath ? `${parentPath} > ${jobName}` : jobName;
39
+ const steps = job?.steps;
40
+ if (!Array.isArray(steps)) continue;
41
+ for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
42
+ const step = steps[stepIndex];
43
+ const stepAnnotations = step?.annotations;
44
+ if (Array.isArray(stepAnnotations)) {
45
+ for (const annotation of stepAnnotations) if (annotation?.message) annotations.push({
46
+ type: annotation.type || "notice",
47
+ message: annotation.message,
48
+ title: annotation.title,
49
+ file: annotation.file,
50
+ line: annotation.line,
51
+ jobName: fullJobName,
52
+ stepName: step?.name,
53
+ stepIndex
54
+ });
55
+ }
56
+ const subJobs = step?.subworkflow?.jobs;
57
+ if (subJobs && typeof subJobs === "object") annotations.push(...collectAnnotations(subJobs, fullJobName));
58
+ }
59
+ }
60
+ annotations.sort((a, b) => (typeOrder[a.type] ?? 2) - (typeOrder[b.type] ?? 2));
61
+ return annotations;
62
+ }
63
+ function AnnotationBanner({ executedJobs }) {
64
+ const [expanded, setExpanded] = useState(false);
65
+ if (!executedJobs) return null;
66
+ const annotations = collectAnnotations(executedJobs);
67
+ if (annotations.length === 0) return null;
68
+ const counts = {
69
+ error: 0,
70
+ warning: 0,
71
+ notice: 0
72
+ };
73
+ for (const a of annotations) counts[a.type]++;
74
+ const ChevronIcon = expanded ? ChevronDownIcon : ChevronRightIcon;
75
+ return /* @__PURE__ */ jsxs("div", {
76
+ className: cx("rounded-lg border border-[var(--theme-border)] overflow-hidden", "bg-[var(--theme-panel-bg)]"),
77
+ children: [/* @__PURE__ */ jsxs("button", {
78
+ type: "button",
79
+ onClick: () => setExpanded((prev) => !prev),
80
+ className: cx("w-full flex items-center gap-3 px-4 py-2.5 text-left", "hover:bg-[var(--theme-hover)] transition-colors", expanded && "border-b border-[var(--theme-border)]"),
81
+ children: [
82
+ /* @__PURE__ */ jsx(ChevronIcon, { className: "w-3.5 h-3.5 text-[var(--theme-muted-text-color)] shrink-0" }),
83
+ /* @__PURE__ */ jsx("span", {
84
+ className: "text-sm font-medium text-[var(--theme-panel-color)]",
85
+ children: "Annotations"
86
+ }),
87
+ /* @__PURE__ */ jsx("div", {
88
+ className: "flex items-center gap-1.5",
89
+ children: [
90
+ "error",
91
+ "warning",
92
+ "notice"
93
+ ].map((type) => {
94
+ if (!counts[type]) return null;
95
+ const config = typeConfig[type];
96
+ const Icon = config.icon;
97
+ return /* @__PURE__ */ jsxs("span", {
98
+ className: cx("inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium", config.countBg),
99
+ children: [/* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }), counts[type]]
100
+ }, type);
101
+ })
102
+ })
103
+ ]
104
+ }), expanded && /* @__PURE__ */ jsx("div", {
105
+ className: "divide-y divide-[var(--theme-border)] max-h-[400px] overflow-y-auto",
106
+ children: keyedByContent(annotations, (a) => a.id ?? `${a.type}:${a.title}:${a.message}`).map(({ key, item: annotation }) => {
107
+ const config = typeConfig[annotation.type] || typeConfig.notice;
108
+ const Icon = config.icon;
109
+ return /* @__PURE__ */ jsxs("div", {
110
+ className: cx("flex items-start gap-2.5 px-4 py-2 text-sm", config.bgClass),
111
+ children: [/* @__PURE__ */ jsx(Icon, { className: cx("w-4 h-4 mt-0.5 shrink-0", config.accentClass) }), /* @__PURE__ */ jsxs("div", {
112
+ className: "flex-1 min-w-0",
113
+ children: [
114
+ /* @__PURE__ */ jsxs("span", {
115
+ className: cx("font-medium", config.accentClass),
116
+ children: [annotation.title || config.label, ":"]
117
+ }),
118
+ " ",
119
+ /* @__PURE__ */ jsx("span", {
120
+ className: "text-[var(--theme-panel-color)]",
121
+ children: annotation.message
122
+ }),
123
+ /* @__PURE__ */ jsxs("span", {
124
+ className: "text-[var(--theme-muted-text-color)] ml-2 text-xs",
125
+ children: [
126
+ "in ",
127
+ annotation.jobName,
128
+ " →",
129
+ " ",
130
+ annotation.stepName || `step ${annotation.stepIndex}`
131
+ ]
132
+ })
133
+ ]
134
+ })]
135
+ }, key);
136
+ })
137
+ })]
138
+ });
139
+ }
140
+ //#endregion
141
+ export { AnnotationBanner };
@@ -0,0 +1,41 @@
1
+ import { useState } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { AnimatePresence, motion } from "framer-motion";
4
+ //#region src/graph/Collapse.tsx
5
+ function Collapse({ expanded, children, releaseOverflow = true }) {
6
+ const [overflowVisible, setOverflowVisible] = useState(false);
7
+ return /* @__PURE__ */ jsx(AnimatePresence, {
8
+ initial: false,
9
+ children: expanded && /* @__PURE__ */ jsx(motion.div, {
10
+ initial: {
11
+ height: 0,
12
+ opacity: 0
13
+ },
14
+ animate: {
15
+ height: "auto",
16
+ opacity: 1
17
+ },
18
+ exit: {
19
+ height: 0,
20
+ opacity: 0
21
+ },
22
+ transition: {
23
+ duration: .2,
24
+ ease: [
25
+ .25,
26
+ .1,
27
+ .25,
28
+ 1
29
+ ]
30
+ },
31
+ style: { overflow: overflowVisible ? "visible" : "hidden" },
32
+ onAnimationStart: () => setOverflowVisible(false),
33
+ onAnimationComplete: () => {
34
+ if (expanded && releaseOverflow) setOverflowVisible(true);
35
+ },
36
+ children
37
+ }, "collapse")
38
+ });
39
+ }
40
+ //#endregion
41
+ export { Collapse };