@parallelworks/ui 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/editor.worker-CuBRIwi-.js +14776 -0
- package/dist/assets/json.worker-8ytS02vz.js +22161 -0
- package/dist/assets/yaml.worker-DJC-VUcv.js +48367 -0
- package/dist/chunks/Indicator-fF8AVbjQ.js +158 -0
- package/dist/chunks/Loader-DQiZ75fa.js +25 -0
- package/dist/chunks/MarkdownImpl-Bq4QhrtA.js +33 -0
- package/dist/chunks/Monaco-CP_cL9gp.js +745 -0
- package/dist/chunks/Provider-C2VtPnh5.js +151 -0
- package/dist/chunks/SwitchToggleSmall-FcsaYSTs.js +14 -0
- package/dist/chunks/Table-DWuRINhu.js +855 -0
- package/dist/chunks/Tooltip-WgbiC_nd.js +71 -0
- package/dist/chunks/lib-DTgL8klR.js +191 -0
- package/dist/chunks/workers-Cjfjb8E7.js +119 -0
- package/dist/components/CollapsiblePanel.d.ts +27 -0
- package/dist/components/CopyToClipboard.d.ts +17 -0
- package/dist/components/Dropdown.d.ts +24 -0
- package/dist/components/Indicator.d.ts +4 -0
- package/dist/components/Listbox.d.ts +18 -0
- package/dist/components/Markdown.d.ts +7 -0
- package/dist/components/MarkdownImpl.d.ts +2 -0
- package/dist/components/MultiSelect.d.ts +19 -0
- package/dist/components/Overview.d.ts +12 -0
- package/dist/components/Provider.d.ts +145 -0
- package/dist/components/SectionHeader.d.ts +6 -0
- package/dist/components/SwitchToggle.d.ts +12 -0
- package/dist/components/SwitchToggleSmall.d.ts +6 -0
- package/dist/components/dropdownUtils.d.ts +18 -0
- package/dist/editor/Editor.d.ts +2 -0
- package/dist/editor/EditorField.d.ts +11 -0
- package/dist/editor/FormCodePanel.d.ts +8 -0
- package/dist/editor/Monaco.d.ts +31 -0
- package/dist/editor/index.d.ts +6 -0
- package/dist/editor/index.js +219 -0
- package/dist/editor/themes.d.ts +4 -0
- package/dist/editor/workers.d.ts +6 -0
- package/dist/form/FieldWrapper.d.ts +10 -0
- package/dist/form/Fields/BooleanField.d.ts +12 -0
- package/dist/form/Fields/BucketReadOnlyField.d.ts +7 -0
- package/dist/form/Fields/CheckboxGroupField.d.ts +18 -0
- package/dist/form/Fields/ColorField.d.ts +8 -0
- package/dist/form/Fields/DropdownField.d.ts +24 -0
- package/dist/form/Fields/DurationField.d.ts +13 -0
- package/dist/form/Fields/LabelField.d.ts +9 -0
- package/dist/form/Fields/MultiDropdownField.d.ts +18 -0
- package/dist/form/Fields/NumberField.d.ts +13 -0
- package/dist/form/Fields/ObjectField.d.ts +8 -0
- package/dist/form/Fields/RadioField.d.ts +9 -0
- package/dist/form/Fields/RangeField.d.ts +11 -0
- package/dist/form/Fields/ResourceOptionIcon.d.ts +11 -0
- package/dist/form/Fields/StepField.d.ts +3 -0
- package/dist/form/Fields/StringField.d.ts +17 -0
- package/dist/form/Fields/TextAreaField.d.ts +8 -0
- package/dist/form/Fields/durationValidity.d.ts +2 -0
- package/dist/form/Form.d.ts +105 -0
- package/dist/form/SpecialTypes/DropdownWrapper.d.ts +14 -0
- package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +53 -0
- package/dist/form/SpecialTypes/FormikCustomInput.d.ts +17 -0
- package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +13 -0
- package/dist/form/SpecialTypes/FormikNumericInput.d.ts +9 -0
- package/dist/form/SpecialTypes/index.d.ts +3 -0
- package/dist/form/Wizard/WizardContainer.d.ts +5 -0
- package/dist/form/Wizard/WizardNavigation.d.ts +2 -0
- package/dist/form/Wizard/WizardStepContent.d.ts +8 -0
- package/dist/form/Wizard/WizardStepIndicator.d.ts +2 -0
- package/dist/form/Wizard/types.d.ts +171 -0
- package/dist/form/Wizard/useWizardState.d.ts +28 -0
- package/dist/form/Wizard/utils.d.ts +2 -0
- package/dist/form/fieldRegistry.d.ts +7 -0
- package/dist/form/index.d.ts +16 -0
- package/dist/form/index.js +2317 -0
- package/dist/form/lib.d.ts +15 -0
- package/dist/form/types/fieldComponentTypes.d.ts +32 -0
- package/dist/form/types/fieldTypes.d.ts +80 -0
- package/dist/form/types/workflow-schema.d.ts +1107 -0
- package/dist/form/useParsedOpts.d.ts +5 -0
- package/dist/form/usePrevious.d.ts +1 -0
- package/dist/form/utils/checkShowIfObject.d.ts +1 -0
- package/dist/form/utils/getParentValue.d.ts +1 -0
- package/dist/form/utils/getPlaceholder.d.ts +2 -0
- package/dist/form/utils/getValueUsingPath.d.ts +1 -0
- package/dist/form/utils/pwResolver.d.ts +18 -0
- package/dist/form/utils/secondaryField.d.ts +8 -0
- package/dist/form/utils/slurmDuration.d.ts +15 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +2 -2
- package/dist/index.d.ts +17 -0
- package/dist/index.js +107 -323
- package/dist/logviewer/LogViewer.d.ts +18 -0
- package/dist/logviewer/index.d.ts +1 -0
- package/dist/logviewer/index.js +534 -0
- package/dist/logviewer/logviewer.css +70 -0
- package/dist/styles.css +1 -1
- package/dist/workflow/AnnotationBanner.d.ts +5 -0
- package/dist/workflow/Collapse.d.ts +6 -0
- package/dist/workflow/DependencyGraph.d.ts +15 -0
- package/dist/workflow/JobSummary.d.ts +38 -0
- package/dist/workflow/MatrixGroup.d.ts +41 -0
- package/dist/workflow/Reveal.d.ts +7 -0
- package/dist/workflow/TreeView.d.ts +42 -0
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.js +2330 -0
- package/package.json +60 -6
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { TooltipIcon } from "../icons.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment as Fragment$1 } from "react";
|
|
4
|
+
import { Tooltip } from "react-tooltip";
|
|
5
|
+
//#region src/components/Tooltip.tsx
|
|
6
|
+
var TOOLTIP_ID = "global-tooltip";
|
|
7
|
+
var linkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
|
|
8
|
+
function formatLine(line) {
|
|
9
|
+
const nodes = [];
|
|
10
|
+
let last = 0;
|
|
11
|
+
for (const match of line.matchAll(linkRegex)) {
|
|
12
|
+
if (match.index > last) nodes.push(line.slice(last, match.index));
|
|
13
|
+
nodes.push(/* @__PURE__ */ jsx("a", {
|
|
14
|
+
href: match[2],
|
|
15
|
+
target: "_blank",
|
|
16
|
+
rel: "noopener noreferrer",
|
|
17
|
+
className: "underline",
|
|
18
|
+
children: match[1]
|
|
19
|
+
}, match.index));
|
|
20
|
+
last = match.index + match[0].length;
|
|
21
|
+
}
|
|
22
|
+
if (last < line.length) nodes.push(line.slice(last));
|
|
23
|
+
return nodes;
|
|
24
|
+
}
|
|
25
|
+
/** Tooltip text can come from untrusted sources (workflow YAML), so all markup is literal text — only `[text](url)` links and newlines are parsed. */
|
|
26
|
+
function formatTooltipContent(content) {
|
|
27
|
+
if (typeof content !== "string") return content || null;
|
|
28
|
+
if (!content) return null;
|
|
29
|
+
return content.split(/<br\s*\/?>|\n/i).map((line, idx) => /* @__PURE__ */ jsxs(Fragment$1, { children: [idx > 0 && /* @__PURE__ */ jsx("br", {}), formatLine(line)] }, idx));
|
|
30
|
+
}
|
|
31
|
+
function KbdShortcut({ keys }) {
|
|
32
|
+
return /* @__PURE__ */ jsx("span", {
|
|
33
|
+
className: "inline-flex items-center gap-1 align-middle",
|
|
34
|
+
children: keys.split("+").map((part) => part.trim()).filter(Boolean).map((part, idx) => /* @__PURE__ */ jsxs(Fragment$1, { children: [idx > 0 && /* @__PURE__ */ jsx("span", {
|
|
35
|
+
className: "opacity-60 text-[11px]",
|
|
36
|
+
children: "+"
|
|
37
|
+
}), /* @__PURE__ */ jsx("kbd", {
|
|
38
|
+
className: "inline-flex items-center justify-center min-w-[18px] h-[18px] px-1 rounded border border-white/30 bg-white/10 font-sans text-[11px] font-semibold leading-none",
|
|
39
|
+
children: part
|
|
40
|
+
})] }, `${part}-${idx}`))
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/** Singleton rendered at layout root; anchors opt in via data-tooltip-id={TOOLTIP_ID}, data-tooltip-content, and data-tooltip-shortcut. */
|
|
44
|
+
function GlobalTooltip() {
|
|
45
|
+
return /* @__PURE__ */ jsx(Tooltip, {
|
|
46
|
+
id: TOOLTIP_ID,
|
|
47
|
+
className: "max-w-lg break-words config-tips normal-case text-left z-[10000]",
|
|
48
|
+
place: "top",
|
|
49
|
+
render: ({ content, activeAnchor }) => {
|
|
50
|
+
const body = formatTooltipContent(content);
|
|
51
|
+
const shortcut = activeAnchor?.getAttribute("data-tooltip-shortcut");
|
|
52
|
+
if (!shortcut) return body;
|
|
53
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
54
|
+
className: "inline-flex items-center gap-2",
|
|
55
|
+
children: [body, /* @__PURE__ */ jsx(KbdShortcut, { keys: shortcut })]
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function TooltipInfo({ text, className = "", children, place = "top", tabIndex }) {
|
|
61
|
+
return /* @__PURE__ */ jsx("div", {
|
|
62
|
+
"data-tooltip-id": TOOLTIP_ID,
|
|
63
|
+
"data-tooltip-content": text,
|
|
64
|
+
"data-tooltip-place": place,
|
|
65
|
+
className,
|
|
66
|
+
tabIndex,
|
|
67
|
+
children: children || /* @__PURE__ */ jsx(TooltipIcon, { className: "tooltip" })
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { formatTooltipContent as i, TOOLTIP_ID as n, TooltipInfo as r, GlobalTooltip as t };
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import cx from "classnames";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/form/FieldWrapper.tsx
|
|
4
|
+
function FieldWrapper({ label, tooltipComponent, description, labelPosition = "left", spaceCompact = false, optional = false, children }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
6
|
+
className: cx("flex w-full", labelPosition === "left" ? "items-start" : "items-left flex-col"),
|
|
7
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
8
|
+
className: cx("relative", labelPosition === "left" ? "form-label" : "form-label-top", spaceCompact && "form-label-compact"),
|
|
9
|
+
children: [
|
|
10
|
+
label,
|
|
11
|
+
!optional && /* @__PURE__ */ jsx("span", { children: "*" }),
|
|
12
|
+
tooltipComponent
|
|
13
|
+
]
|
|
14
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
15
|
+
className: "w-full",
|
|
16
|
+
children: [children, description && /* @__PURE__ */ jsx("div", {
|
|
17
|
+
className: "text-xs theme-muted-text mt-1 leading-relaxed",
|
|
18
|
+
children: description
|
|
19
|
+
})]
|
|
20
|
+
})]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region src/form/utils/secondaryField.ts
|
|
25
|
+
function findSecondaryOption(options, value) {
|
|
26
|
+
for (const candidate of options) {
|
|
27
|
+
if (!candidate || typeof candidate !== "object") continue;
|
|
28
|
+
const option = candidate;
|
|
29
|
+
if (option.value === value) return option;
|
|
30
|
+
if (Array.isArray(option.options)) {
|
|
31
|
+
const nestedOption = findSecondaryOption(option.options, value);
|
|
32
|
+
if (nestedOption) return nestedOption;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function applySecondaryField(secondaryField, secondaryValue, setFieldValue) {
|
|
37
|
+
if (secondaryField === void 0 || secondaryValue === void 0) return;
|
|
38
|
+
const fields = Array.isArray(secondaryField) ? secondaryField : [secondaryField];
|
|
39
|
+
const values = Array.isArray(secondaryValue) ? secondaryValue : [secondaryValue];
|
|
40
|
+
fields.forEach((field, index) => {
|
|
41
|
+
setFieldValue(field, values[index]);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/form/lib.ts
|
|
46
|
+
/**
|
|
47
|
+
* Drops a schema flag the expression parser could not resolve. workflow.schema.json types
|
|
48
|
+
* `optional`/`hidden`/`ignore` as ["string", "boolean"], so a flag whose expression depends
|
|
49
|
+
* on something unavailable at form-render time (a list `[index]` outside a row, `needs.`,
|
|
50
|
+
* `env.`, a secret `var.`) arrives as the raw `${{…}}` string. That string is truthy, which
|
|
51
|
+
* inverts each flag's documented `false` default. Returning undefined lets the caller apply
|
|
52
|
+
* that default instead of reading an expression it never evaluated as "yes".
|
|
53
|
+
*/
|
|
54
|
+
function resolvedFlag(value) {
|
|
55
|
+
return typeof value === "string" && value.includes("${{") ? void 0 : value;
|
|
56
|
+
}
|
|
57
|
+
function enforceOneMustBeTrue(items, options, promoteIndex) {
|
|
58
|
+
if (items.length === 0) return items;
|
|
59
|
+
const clampedIndex = Math.max(0, Math.min(promoteIndex, items.length - 1));
|
|
60
|
+
const oneMustBeTrueFields = Object.keys(options).filter((key) => typeof options[key] === "object" && options[key] !== null && "one_must_be_true" in options[key] && options[key].one_must_be_true);
|
|
61
|
+
for (const fieldKey of oneMustBeTrueFields) {
|
|
62
|
+
const fieldSchema = options[fieldKey];
|
|
63
|
+
if (typeof fieldSchema === "object" && fieldSchema && "options" in fieldSchema) {
|
|
64
|
+
const opts = fieldSchema.options;
|
|
65
|
+
const trueOption = typeof opts === "object" && opts && !Array.isArray(opts) && "onOption" in opts ? opts.onOption || true : true;
|
|
66
|
+
if (!items.some((item) => item[fieldKey] === trueOption)) items[clampedIndex][fieldKey] = trueOption;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return items;
|
|
70
|
+
}
|
|
71
|
+
function flattenGroups(schema) {
|
|
72
|
+
if (!schema) return {};
|
|
73
|
+
let flattenedFields = {};
|
|
74
|
+
Object.keys(schema).forEach((key) => {
|
|
75
|
+
if (schema[key].type === "group") {
|
|
76
|
+
const flattenedGroup = flattenGroups(schema[key].options);
|
|
77
|
+
flattenedFields = {
|
|
78
|
+
...flattenedFields,
|
|
79
|
+
...flattenedGroup
|
|
80
|
+
};
|
|
81
|
+
} else if (schema[key].type === "object") {
|
|
82
|
+
const flattenedGroup = flattenGroups(schema[key].options);
|
|
83
|
+
flattenedFields = {
|
|
84
|
+
...flattenedFields,
|
|
85
|
+
[key]: flattenedGroup
|
|
86
|
+
};
|
|
87
|
+
} else flattenedFields[key] = schema[key];
|
|
88
|
+
});
|
|
89
|
+
return flattenedFields;
|
|
90
|
+
}
|
|
91
|
+
/**Not a pure function. Edits 'obj' passed into function */
|
|
92
|
+
function impureSetValueFromPath(obj, path, value) {
|
|
93
|
+
const pathArray = path.split(".");
|
|
94
|
+
if (pathArray.length === 1) {
|
|
95
|
+
obj[pathArray[0]] = value;
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let current = obj;
|
|
99
|
+
for (let i = 0; i < pathArray.length - 1; i++) {
|
|
100
|
+
const segment = pathArray[i];
|
|
101
|
+
const arrayMatch = segment.match(/^(.+)\[(\d+)\]$/);
|
|
102
|
+
if (arrayMatch) {
|
|
103
|
+
const key = arrayMatch[1];
|
|
104
|
+
const index = Number(arrayMatch[2]);
|
|
105
|
+
if (!current[key]) current[key] = [];
|
|
106
|
+
if (!current[key][index]) current[key][index] = {};
|
|
107
|
+
current = current[key][index];
|
|
108
|
+
} else {
|
|
109
|
+
if (!current[segment]) current[segment] = {};
|
|
110
|
+
current = current[segment];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
current[pathArray[pathArray.length - 1]] = value;
|
|
114
|
+
}
|
|
115
|
+
function initializeValues(options, srcData = {}, ignoreDefaultStrings = false) {
|
|
116
|
+
if (!options) return;
|
|
117
|
+
const data = structuredClone(srcData);
|
|
118
|
+
return Object.keys(options).reduce((acc, field) => {
|
|
119
|
+
if (field.startsWith("$")) return acc;
|
|
120
|
+
if (options[field].type === "group") {
|
|
121
|
+
const values = initializeValues(options[field].options, data);
|
|
122
|
+
if (!values) return acc;
|
|
123
|
+
Object.keys(values).forEach((key) => {
|
|
124
|
+
acc[key] = data[key] ?? values[key];
|
|
125
|
+
});
|
|
126
|
+
return acc;
|
|
127
|
+
}
|
|
128
|
+
if (options[field].type === "step") {
|
|
129
|
+
if (options.$meta?.wizard?.flatten !== false) {
|
|
130
|
+
const values = initializeValues(options[field].options, data);
|
|
131
|
+
if (!values) return acc;
|
|
132
|
+
Object.keys(values).forEach((key) => {
|
|
133
|
+
acc[key] = data[key] ?? values[key];
|
|
134
|
+
});
|
|
135
|
+
} else acc[field] = initializeValues(options[field].options, data[field] || {});
|
|
136
|
+
return acc;
|
|
137
|
+
}
|
|
138
|
+
if (options[field].type === "object") {
|
|
139
|
+
acc[field] = initializeValues(options[field].options, data[field] || {});
|
|
140
|
+
return acc;
|
|
141
|
+
}
|
|
142
|
+
if (options[field].type === "list") {
|
|
143
|
+
if (options[field].options === "string") {
|
|
144
|
+
acc[field] = Array.isArray(data[field]) ? [...data[field]] : [];
|
|
145
|
+
return acc;
|
|
146
|
+
}
|
|
147
|
+
const arr = [];
|
|
148
|
+
if (data[field]) for (let i = 0; i < data[field].length; i++) arr.push(initializeValues(options[field].options, data[field][i] || {}));
|
|
149
|
+
acc[field] = arr;
|
|
150
|
+
return acc;
|
|
151
|
+
}
|
|
152
|
+
if (data[field] !== void 0) {
|
|
153
|
+
acc[field] = data[field];
|
|
154
|
+
if ((options[field].type === "dropdown" || options[field].type === "storage") && options[field].secondaryField && options[field].options && Array.isArray(options[field].options)) {
|
|
155
|
+
const option = findSecondaryOption(options[field].options, data[field]);
|
|
156
|
+
applySecondaryField(options[field].secondaryField, option?.secondaryValue, (secondaryField, secondaryValue) => {
|
|
157
|
+
if (!(options[field].type === "storage" && Object.prototype.hasOwnProperty.call(options, secondaryField) && srcData[secondaryField] !== void 0)) impureSetValueFromPath(acc, secondaryField, secondaryValue);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return acc;
|
|
161
|
+
}
|
|
162
|
+
if (options[field].type === "label") return acc;
|
|
163
|
+
if (options[field].optional && options[field].default === void 0) return acc;
|
|
164
|
+
acc[field] = "";
|
|
165
|
+
if (options[field].autoselect) acc[field] = void 0;
|
|
166
|
+
if (options[field].type === "boolean") if (options[field].options?.offOption && options[field].options?.onOption) acc[field] = options[field].options.offOption;
|
|
167
|
+
else acc[field] = false;
|
|
168
|
+
if (options[field].type === "dropdown") {
|
|
169
|
+
if (options[field].options && Array.isArray(options[field].options) && options[field].options.length > 0) acc[field] = options[field].options[0].value;
|
|
170
|
+
if (options[field].type === "dropdown" && options[field].secondaryField && options[field].options && Array.isArray(options[field].options)) {
|
|
171
|
+
const option = options[field].options.find((option) => option.value === data[field]);
|
|
172
|
+
const secondaryField = Array.isArray(options[field].secondaryField) ? options[field].secondaryField : [options[field].secondaryField];
|
|
173
|
+
const secondaryValue = Array.isArray(option?.secondaryValue) ? option?.secondaryValue : [option?.secondaryValue];
|
|
174
|
+
secondaryField.forEach((field, index) => {
|
|
175
|
+
impureSetValueFromPath(data, field, secondaryValue[index]);
|
|
176
|
+
impureSetValueFromPath(acc, field, secondaryValue[index]);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (options[field].type === "multi-dropdown" || options[field].type === "checkbox-group") acc[field] = [];
|
|
181
|
+
if (options[field].default !== void 0) {
|
|
182
|
+
const dflt = options[field].default;
|
|
183
|
+
const isPwResource = typeof dflt === "string" && dflt.startsWith("pw://");
|
|
184
|
+
acc[field] = options[field].type === "string" || ignoreDefaultStrings && !isPwResource && (options[field].type === "textarea" || options[field].type === "compute-clusters" || options[field].type === "compute-resources") ? "" : dflt;
|
|
185
|
+
}
|
|
186
|
+
if (options[field].prefillDefault && options[field].default !== void 0) acc[field] = options[field].default;
|
|
187
|
+
return acc;
|
|
188
|
+
}, data);
|
|
189
|
+
}
|
|
190
|
+
//#endregion
|
|
191
|
+
export { resolvedFlag as a, FieldWrapper as c, initializeValues as i, flattenGroups as n, applySecondaryField as o, impureSetValueFromPath as r, findSecondaryOption as s, enforceOneMustBeTrue as t };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
//#region src/editor/themes.ts
|
|
2
|
+
function expandShorthandHex(color) {
|
|
3
|
+
return /^#([0-9a-fA-F]{3,4})$/.test(color) ? "#" + color.slice(1).split("").map((c) => c + c).join("") : color;
|
|
4
|
+
}
|
|
5
|
+
function normalizeThemeColors(colors) {
|
|
6
|
+
return Object.fromEntries(Object.entries(colors).map(([key, value]) => [key, expandShorthandHex(value)]));
|
|
7
|
+
}
|
|
8
|
+
function themeVar(name, fallback) {
|
|
9
|
+
if (typeof window === "undefined") return fallback;
|
|
10
|
+
return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
|
|
11
|
+
}
|
|
12
|
+
function createEditorThemes() {
|
|
13
|
+
const dark = {
|
|
14
|
+
foreground: themeVar("--theme-app", "#e6edf3"),
|
|
15
|
+
background: themeVar("--theme-panel-bg", "#161b22"),
|
|
16
|
+
border: themeVar("--theme-border", "#30363d"),
|
|
17
|
+
lineHighlight: themeVar("--theme-muted-panel-bg", "#21262d"),
|
|
18
|
+
lineNumber: themeVar("--theme-muted-text-color", "#8b949e"),
|
|
19
|
+
selection: themeVar("--theme-element", "#2f81f7"),
|
|
20
|
+
selectionFg: themeVar("--theme-element-text", "#ffffff"),
|
|
21
|
+
disabledBg: themeVar("--theme-input-disabled-bg", "#1c2128"),
|
|
22
|
+
disabledFg: themeVar("--theme-muted-text-color", "#8b949e")
|
|
23
|
+
};
|
|
24
|
+
const light = {
|
|
25
|
+
disabledBg: themeVar("--theme-input-disabled-bg", "#f3f4f6"),
|
|
26
|
+
disabledFg: themeVar("--theme-muted-text-color", "#6c757d"),
|
|
27
|
+
border: themeVar("--theme-border", "#d1d5db"),
|
|
28
|
+
selection: themeVar("--theme-element", "#2f81f7"),
|
|
29
|
+
selectionFg: themeVar("--theme-element-text", "#ffffff")
|
|
30
|
+
};
|
|
31
|
+
return {
|
|
32
|
+
"app-dark": {
|
|
33
|
+
base: "vs-dark",
|
|
34
|
+
inherit: true,
|
|
35
|
+
rules: [],
|
|
36
|
+
colors: {
|
|
37
|
+
"editor.foreground": dark.foreground,
|
|
38
|
+
"editor.background": dark.background,
|
|
39
|
+
"editor.border": dark.border,
|
|
40
|
+
"editorCursor.foreground": dark.foreground,
|
|
41
|
+
"editor.lineHighlightBackground": dark.lineHighlight,
|
|
42
|
+
"editorLineNumber.foreground": dark.lineNumber,
|
|
43
|
+
"editor.selectionBackground": dark.selection,
|
|
44
|
+
"editor.selectionForeground": dark.selectionFg
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"app-dark-disabled": {
|
|
48
|
+
base: "vs-dark",
|
|
49
|
+
inherit: true,
|
|
50
|
+
rules: [],
|
|
51
|
+
colors: {
|
|
52
|
+
"editor.foreground": dark.disabledFg,
|
|
53
|
+
"editor.background": dark.disabledBg,
|
|
54
|
+
"editor.border": dark.border,
|
|
55
|
+
"editorCursor.foreground": "transparent",
|
|
56
|
+
"editor.lineHighlightBackground": dark.disabledBg,
|
|
57
|
+
"editorLineNumber.foreground": dark.disabledFg,
|
|
58
|
+
"editor.selectionBackground": dark.selection,
|
|
59
|
+
"editor.selectionForeground": dark.selectionFg
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"app-light-disabled": {
|
|
63
|
+
base: "vs",
|
|
64
|
+
inherit: true,
|
|
65
|
+
rules: [],
|
|
66
|
+
colors: {
|
|
67
|
+
"editor.foreground": light.disabledFg,
|
|
68
|
+
"editor.background": light.disabledBg,
|
|
69
|
+
"editor.border": light.border,
|
|
70
|
+
"editorCursor.foreground": "transparent",
|
|
71
|
+
"editor.lineHighlightBackground": light.disabledBg,
|
|
72
|
+
"editorLineNumber.foreground": light.disabledFg,
|
|
73
|
+
"editor.selectionBackground": light.selection,
|
|
74
|
+
"editor.selectionForeground": light.selectionFg
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function defineEditorThemes(monacoEditor) {
|
|
80
|
+
const themes = createEditorThemes();
|
|
81
|
+
for (const [name, themeData] of Object.entries(themes)) monacoEditor.defineTheme(name, {
|
|
82
|
+
...themeData,
|
|
83
|
+
colors: normalizeThemeColors(themeData.colors)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function getThemeName(isDark, disabled) {
|
|
87
|
+
if (isDark) return disabled ? "app-dark-disabled" : "app-dark";
|
|
88
|
+
return disabled ? "app-light-disabled" : "vs";
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/editor/workers.ts
|
|
92
|
+
var monacoEnvironment = { getWorker(_moduleId, label) {
|
|
93
|
+
if (label === "json") return new Worker(new URL(
|
|
94
|
+
/* @vite-ignore */
|
|
95
|
+
"/assets/json.worker-8ytS02vz.js",
|
|
96
|
+
"" + import.meta.url
|
|
97
|
+
), { type: "module" });
|
|
98
|
+
if (label === "yaml") return new Worker(new URL(
|
|
99
|
+
/* @vite-ignore */
|
|
100
|
+
"/assets/yaml.worker-DJC-VUcv.js",
|
|
101
|
+
"" + import.meta.url
|
|
102
|
+
), { type: "module" });
|
|
103
|
+
return new Worker(new URL(
|
|
104
|
+
/* @vite-ignore */
|
|
105
|
+
"/assets/editor.worker-CuBRIwi-.js",
|
|
106
|
+
"" + import.meta.url
|
|
107
|
+
), { type: "module" });
|
|
108
|
+
} };
|
|
109
|
+
/**
|
|
110
|
+
* Points window.MonacoEnvironment at the bundled workers. Idempotent, and a
|
|
111
|
+
* host that already configured its own MonacoEnvironment wins — the editor
|
|
112
|
+
* calls this on first load only when nothing is configured.
|
|
113
|
+
*/
|
|
114
|
+
function setupMonacoWorkers() {
|
|
115
|
+
if (window.MonacoEnvironment) return;
|
|
116
|
+
window.MonacoEnvironment = monacoEnvironment;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { defineEditorThemes as n, getThemeName as r, setupMonacoWorkers as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface IControlledCollapsiblePanelProps {
|
|
3
|
+
title?: string | React.ReactNode | ((open: boolean, setOpen: React.Dispatch<React.SetStateAction<boolean>>) => React.ReactNode);
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
open: boolean | undefined;
|
|
6
|
+
setOpen?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
7
|
+
onClick?: () => void;
|
|
8
|
+
wrapperElement?: React.ElementType;
|
|
9
|
+
shown?: boolean;
|
|
10
|
+
setShown?: (shown: boolean) => void;
|
|
11
|
+
customizedButton?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function ControlledCollapsiblePanel({ title, children, open, setOpen, onClick, wrapperElement, customizedButton, className, }: IControlledCollapsiblePanelProps): React.JSX.Element;
|
|
15
|
+
export declare function UncontrolledCollapsiblePanel({ title, children, onClick, wrapperElement, initialState, className, customizedButton, }: Omit<IControlledCollapsiblePanelProps, 'setOpen' | 'open'> & {
|
|
16
|
+
initialState?: boolean;
|
|
17
|
+
}): React.JSX.Element;
|
|
18
|
+
type MaybeCollapsibleProps = {
|
|
19
|
+
className?: string;
|
|
20
|
+
initialState?: boolean;
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
title?: React.ReactNode;
|
|
23
|
+
customizedButton?: React.ReactNode;
|
|
24
|
+
collapsible?: boolean;
|
|
25
|
+
};
|
|
26
|
+
export declare function MaybeCollapsible({ className, initialState, children, title, customizedButton, collapsible, }: MaybeCollapsibleProps): React.JSX.Element;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface ICopyToClipboardProps {
|
|
2
|
+
as?: 'div' | 'button';
|
|
3
|
+
text: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
showIcon?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export default function CopyToClipboard({ as, text, className, children, showIcon, }: ICopyToClipboardProps): import("react").JSX.Element;
|
|
9
|
+
interface CopyCodeBlockProps {
|
|
10
|
+
textToCopy: string;
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
secret?: boolean;
|
|
13
|
+
isRevealed?: boolean;
|
|
14
|
+
onRevealToggle?: () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function CopyCodeBlock({ textToCopy, children, secret, isRevealed, onRevealToggle, }: CopyCodeBlockProps): import("react").JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type SetStateAction } from 'react';
|
|
2
|
+
import { type IOptions, type ICategory } from './dropdownUtils.js';
|
|
3
|
+
export interface IProps {
|
|
4
|
+
options: (ICategory | IOptions | string)[];
|
|
5
|
+
onActiveChange?: (option: unknown) => void;
|
|
6
|
+
onChange: React.Dispatch<SetStateAction<unknown>>;
|
|
7
|
+
onRangeChange?: (range: {
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
}) => void;
|
|
11
|
+
value: IOptions | string | Record<string, unknown>;
|
|
12
|
+
id?: string;
|
|
13
|
+
ariaLabel?: string;
|
|
14
|
+
className?: string;
|
|
15
|
+
wrapperClassName?: string;
|
|
16
|
+
textBoxClassName?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
placeholder?: string;
|
|
19
|
+
loading?: boolean;
|
|
20
|
+
allowCustomValue?: boolean;
|
|
21
|
+
customValueLabel?: string;
|
|
22
|
+
portalEl?: HTMLElement;
|
|
23
|
+
}
|
|
24
|
+
export default function Dropdown(props: IProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface ICustomListboxProps {
|
|
2
|
+
/** Only used visually to inform what you're selecting */
|
|
3
|
+
type: string;
|
|
4
|
+
options: {
|
|
5
|
+
label: string;
|
|
6
|
+
secondaryLabel?: string;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
value: any;
|
|
9
|
+
selected: boolean;
|
|
10
|
+
}[];
|
|
11
|
+
closeOnSelect?: boolean;
|
|
12
|
+
allowSearch?: boolean;
|
|
13
|
+
handleOptionSelected: (value: any) => void;
|
|
14
|
+
className?: string;
|
|
15
|
+
invalid?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export default function CustomListbox({ options, handleOptionSelected, type, allowSearch, closeOnSelect, className, invalid, }: ICustomListboxProps): import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ICategory, type IOptions } from './dropdownUtils.js';
|
|
2
|
+
type MultiSelectDropdownProps<T = string> = {
|
|
3
|
+
options: (ICategory<T> | IOptions<T> | string)[];
|
|
4
|
+
value: T[];
|
|
5
|
+
onChange: (next: T[]) => void;
|
|
6
|
+
id?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
wrapperClassName?: string;
|
|
9
|
+
textBoxClassName?: string;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
searchable?: boolean;
|
|
14
|
+
maxTagCount?: number;
|
|
15
|
+
/** Custom comparator for object values. Defaults to strict equality. */
|
|
16
|
+
compareBy?: (a: T, b: T) => boolean;
|
|
17
|
+
};
|
|
18
|
+
export default function MultiSelectDropdown<T = string>({ options, value, onChange, id, className, wrapperClassName, textBoxClassName, disabled, placeholder, loading, searchable, maxTagCount, compareBy, }: MultiSelectDropdownProps<T>): import("react").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function Overview({ Icon, name, type, children, right, className, loading, iconSize, }: {
|
|
2
|
+
Icon: React.ReactNode;
|
|
3
|
+
name: string | React.ReactNode;
|
|
4
|
+
type?: string | React.ReactNode;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
/** Right-aligned content on the header row (e.g. a detail-page action bar),
|
|
7
|
+
* vertically centered against the name block. */
|
|
8
|
+
right?: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
loading?: boolean;
|
|
11
|
+
iconSize?: number;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface UINotify {
|
|
3
|
+
info: (message: string) => void;
|
|
4
|
+
success: (message: string) => void;
|
|
5
|
+
error: (message: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface UIStrings {
|
|
8
|
+
loading: string;
|
|
9
|
+
common: {
|
|
10
|
+
copy: string;
|
|
11
|
+
copied: string;
|
|
12
|
+
copyFailed: string;
|
|
13
|
+
showHiddenFields: string;
|
|
14
|
+
showHiddenFieldsHint: string;
|
|
15
|
+
jsonHasErrors: string;
|
|
16
|
+
};
|
|
17
|
+
dropdown: {
|
|
18
|
+
select: (type: string) => string;
|
|
19
|
+
noOptionsFound: string;
|
|
20
|
+
};
|
|
21
|
+
logviewer: {
|
|
22
|
+
error: string;
|
|
23
|
+
warning: string;
|
|
24
|
+
notice: string;
|
|
25
|
+
top: string;
|
|
26
|
+
clearSelection: string;
|
|
27
|
+
copyLines: (count: number) => string;
|
|
28
|
+
copyAll: string;
|
|
29
|
+
hideDebug: string;
|
|
30
|
+
showDebug: string;
|
|
31
|
+
filterLogs: string;
|
|
32
|
+
download: string;
|
|
33
|
+
};
|
|
34
|
+
dag: {
|
|
35
|
+
workflow: string;
|
|
36
|
+
run: string;
|
|
37
|
+
status: string;
|
|
38
|
+
runtime: string;
|
|
39
|
+
submitted: string;
|
|
40
|
+
expandAll: string;
|
|
41
|
+
collapseAll: string;
|
|
42
|
+
statusLabel: (status: string) => string;
|
|
43
|
+
statusReason: (reason: string | undefined | null) => string | undefined;
|
|
44
|
+
};
|
|
45
|
+
jobActions: {
|
|
46
|
+
openSubworkflowLogs: string;
|
|
47
|
+
openOriginalWorkflow: string;
|
|
48
|
+
openInNewGraph: string;
|
|
49
|
+
};
|
|
50
|
+
form: {
|
|
51
|
+
invalidDuration: string;
|
|
52
|
+
durationOutOfRange: (min: string, max: string) => string;
|
|
53
|
+
durationBelowMin: (min: string) => string;
|
|
54
|
+
readOnly: string;
|
|
55
|
+
readWrite: string;
|
|
56
|
+
readOnlyDescription: string;
|
|
57
|
+
readOnlyForced: string;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface UINavigation {
|
|
61
|
+
toWorkflow: (name: string) => void;
|
|
62
|
+
toMarketItem: (name: string) => void;
|
|
63
|
+
openExternal: (href: string) => void;
|
|
64
|
+
}
|
|
65
|
+
export type WorkflowJsonRef = {
|
|
66
|
+
kind: 'marketplace';
|
|
67
|
+
slug: string;
|
|
68
|
+
version: string;
|
|
69
|
+
} | {
|
|
70
|
+
kind: 'workflow';
|
|
71
|
+
name: string;
|
|
72
|
+
};
|
|
73
|
+
export interface RunFileResult {
|
|
74
|
+
data: string | undefined;
|
|
75
|
+
isLoading: boolean;
|
|
76
|
+
error: unknown;
|
|
77
|
+
}
|
|
78
|
+
export interface UIData {
|
|
79
|
+
/**
|
|
80
|
+
* Host-bound hook resolving a file in a run's artifact tree (logs, scripts).
|
|
81
|
+
* A null path skips fetching; refreshInterval polls while set. Must be a
|
|
82
|
+
* stable function reference — components call it as a hook.
|
|
83
|
+
*/
|
|
84
|
+
useRunFile: (slug: string, path: string | null, options?: {
|
|
85
|
+
refreshInterval?: number;
|
|
86
|
+
}) => RunFileResult;
|
|
87
|
+
/**
|
|
88
|
+
* Resolves a workflow reference to its parsed JSON definition, for the YAML
|
|
89
|
+
* editor's input completion. Absent, that completion silently no-ops.
|
|
90
|
+
*/
|
|
91
|
+
resolveWorkflowJson?: (ref: WorkflowJsonRef) => Promise<unknown>;
|
|
92
|
+
}
|
|
93
|
+
import type { FieldComponent } from '../form/fieldRegistry.js';
|
|
94
|
+
export interface UISlots {
|
|
95
|
+
/**
|
|
96
|
+
* Host-supplied form field components, merged over the form engine's core
|
|
97
|
+
* registry by field type. Lazy components are supported — the registry
|
|
98
|
+
* renders fields inside a Suspense boundary.
|
|
99
|
+
*/
|
|
100
|
+
formFields?: Record<string, FieldComponent>;
|
|
101
|
+
/** Sessions block for a run's sidebar; absent hides the section. */
|
|
102
|
+
runSessions?: (args: {
|
|
103
|
+
runId: string;
|
|
104
|
+
runNumber: number;
|
|
105
|
+
runActive: boolean;
|
|
106
|
+
}) => ReactNode;
|
|
107
|
+
/** Rich read-only YAML viewer; absent falls back to a plain <pre>. */
|
|
108
|
+
yamlViewer?: (args: {
|
|
109
|
+
value: string;
|
|
110
|
+
height: number;
|
|
111
|
+
width: number;
|
|
112
|
+
contentKey: string;
|
|
113
|
+
}) => ReactNode;
|
|
114
|
+
/** Icon for a subworkflow step; absent hides icon-bound affordances. */
|
|
115
|
+
workflowIcon?: (args: {
|
|
116
|
+
image?: string;
|
|
117
|
+
type?: string;
|
|
118
|
+
className?: string;
|
|
119
|
+
}) => ReactNode;
|
|
120
|
+
}
|
|
121
|
+
export interface UIProviderValue {
|
|
122
|
+
notify: UINotify;
|
|
123
|
+
strings: UIStrings;
|
|
124
|
+
navigation: UINavigation;
|
|
125
|
+
data: UIData;
|
|
126
|
+
slots: UISlots;
|
|
127
|
+
}
|
|
128
|
+
export declare function useNotify(): UINotify;
|
|
129
|
+
export declare function useStrings(): UIStrings;
|
|
130
|
+
export declare function useNavigation(): UINavigation;
|
|
131
|
+
export declare function useSlots(): UISlots;
|
|
132
|
+
export declare function useWorkflowJsonResolver(): ((ref: WorkflowJsonRef) => Promise<unknown>) | undefined;
|
|
133
|
+
export declare function useRunFile(slug: string, path: string | null, options?: {
|
|
134
|
+
refreshInterval?: number;
|
|
135
|
+
}): RunFileResult;
|
|
136
|
+
export declare function UIProvider({ notify, strings, navigation, data, slots, children, }: {
|
|
137
|
+
notify?: Partial<UINotify>;
|
|
138
|
+
strings?: {
|
|
139
|
+
[G in keyof UIStrings]?: UIStrings[G] extends object ? Partial<UIStrings[G]> : UIStrings[G];
|
|
140
|
+
};
|
|
141
|
+
navigation?: Partial<UINavigation>;
|
|
142
|
+
data?: Partial<UIData>;
|
|
143
|
+
slots?: UISlots;
|
|
144
|
+
children: React.ReactNode;
|
|
145
|
+
}): import("react").JSX.Element;
|