@parallelworks/ui 0.51.0 → 0.53.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/README.md +197 -17
- package/dist/ai/agent/toolStrings.d.ts +2 -0
- package/dist/ai/agent/toolStrings.js +20 -18
- package/dist/ai/ai.css +17 -3
- package/dist/ai/components/AllocationSelector.js +5 -1
- package/dist/ai/components/AttachmentManager.js +51 -42
- package/dist/ai/components/AttachmentUpload.d.ts +4 -2
- package/dist/ai/components/AttachmentUpload.js +9 -9
- package/dist/ai/components/BlockedGroupBanner.js +8 -14
- package/dist/ai/components/BranchNavigator.js +11 -12
- package/dist/ai/components/ChatEmptyState.js +12 -19
- package/dist/ai/components/ChatInput.d.ts +4 -3
- package/dist/ai/components/ChatInput.js +27 -13
- package/dist/ai/components/ChatMessage.js +45 -121
- package/dist/ai/components/ChatMessageList.d.ts +5 -2
- package/dist/ai/components/ChatMessageList.js +89 -51
- package/dist/ai/components/ChatSidebar.js +11 -7
- package/dist/ai/components/ChatThread.js +1 -13
- package/dist/ai/components/DragOverlay.js +3 -3
- package/dist/ai/components/MessageAttachments.d.ts +10 -0
- package/dist/ai/components/MessageAttachments.js +78 -0
- package/dist/ai/components/ModelSelector.js +3 -3
- package/dist/ai/components/PastedText.js +2 -2
- package/dist/ai/components/ProviderIssueBanner.js +19 -23
- package/dist/ai/components/ShareDialog.js +2 -2
- package/dist/ai/components/agent/ActivityLine.d.ts +0 -2
- package/dist/ai/components/agent/ActivityLine.js +8 -51
- package/dist/ai/components/agent/AgentMessageParts.js +114 -53
- package/dist/ai/core/ChatProvider.d.ts +16 -5
- package/dist/ai/core/ChatProvider.js +41 -8
- package/dist/ai/core/config.js +4 -3
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.js +3 -3
- package/dist/ai/strings.d.ts +29 -3
- package/dist/ai/strings.js +80 -26
- package/dist/ai/types.d.ts +4 -0
- package/dist/ai/ui/Notice.d.ts +2 -2
- package/dist/ai/ui/Notice.js +29 -62
- package/dist/ai/ui/sidebar.d.ts +5 -3
- package/dist/ai/ui/sidebar.js +22 -10
- package/dist/components/ActionMenu.d.ts +1 -0
- package/dist/components/ActionMenu.js +6 -1
- package/dist/components/AppLink.d.ts +26 -0
- package/dist/components/AppLink.js +51 -0
- package/dist/components/Avatar.d.ts +2 -1
- package/dist/components/Avatar.js +4 -2
- package/dist/components/Button.d.ts +15 -5
- package/dist/components/Button.js +47 -40
- package/dist/components/Callout.d.ts +31 -7
- package/dist/components/Callout.js +50 -19
- package/dist/components/Card.d.ts +11 -6
- package/dist/components/Card.js +14 -8
- package/dist/components/Checkbox.js +2 -1
- package/dist/components/ColorInput.js +5 -3
- package/dist/components/Combobox.js +49 -19
- package/dist/components/ConfirmModal.d.ts +19 -8
- package/dist/components/ConfirmModal.js +31 -53
- package/dist/components/CopyButton.d.ts +38 -0
- package/dist/components/CopyButton.js +68 -0
- package/dist/components/CreateModal.js +118 -111
- package/dist/components/DatePicker.js +12 -8
- package/dist/components/DescriptionList.d.ts +25 -5
- package/dist/components/DescriptionList.js +56 -22
- package/dist/components/Disclosure.js +1 -1
- package/dist/components/Drawer.js +10 -16
- package/dist/components/Field.d.ts +16 -5
- package/dist/components/Field.js +63 -8
- package/dist/components/IconButton.d.ts +14 -5
- package/dist/components/IconButton.js +25 -14
- package/dist/components/InfoTip.d.ts +12 -1
- package/dist/components/InfoTip.js +13 -2
- package/dist/components/Input.d.ts +14 -8
- package/dist/components/Input.js +46 -31
- package/dist/components/Loader.js +1 -1
- package/dist/components/MarkdownImpl.d.ts +1 -0
- package/dist/components/MarkdownImpl.js +1 -0
- package/dist/components/MenuEntries.d.ts +4 -0
- package/dist/components/MenuEntries.js +11 -12
- package/dist/components/Meter.js +5 -4
- package/dist/components/Modal.d.ts +28 -4
- package/dist/components/Modal.js +37 -14
- package/dist/components/Overview.d.ts +20 -12
- package/dist/components/Overview.js +14 -9
- package/dist/components/PageHeader.d.ts +47 -65
- package/dist/components/PageHeader.js +275 -153
- package/dist/components/PageHeaderAction.d.ts +67 -0
- package/dist/components/PageHeaderAction.js +107 -0
- package/dist/components/Pagination.js +6 -16
- package/dist/components/Popover.d.ts +4 -1
- package/dist/components/Popover.js +5 -3
- package/dist/components/Provider.d.ts +79 -19
- package/dist/components/Provider.js +140 -130
- package/dist/components/Radio.js +2 -1
- package/dist/components/RefreshButton.js +7 -8
- package/dist/components/RequiredMark.js +1 -1
- package/dist/components/Section.js +1 -1
- package/dist/components/Select.d.ts +4 -9
- package/dist/components/Select.js +24 -11
- package/dist/components/SettingModeOption.d.ts +1 -1
- package/dist/components/SettingModeOption.js +7 -1
- package/dist/components/SettingsCard.d.ts +5 -3
- package/dist/components/SettingsCard.js +27 -20
- package/dist/components/Slider.js +1 -1
- package/dist/components/StatusBadge.js +2 -2
- package/dist/components/Switch.js +5 -4
- package/dist/components/Table.d.ts +30 -20
- package/dist/components/Table.js +50 -73
- package/dist/components/Tabs.d.ts +3 -7
- package/dist/components/Tabs.js +6 -10
- package/dist/components/ThemeEditor.js +18 -8
- package/dist/components/Toast.d.ts +11 -3
- package/dist/components/Toast.js +45 -20
- package/dist/components/buttonClasses.js +1 -1
- package/dist/components/comboboxItems.d.ts +4 -0
- package/dist/components/comboboxItems.js +6 -1
- package/dist/components/dismiss.d.ts +12 -0
- package/dist/components/dismiss.js +19 -0
- package/dist/components/fieldBox.d.ts +4 -0
- package/dist/components/fieldBox.js +7 -3
- package/dist/components/floating.d.ts +3 -3
- package/dist/components/floating.js +1 -1
- package/dist/components/focus.d.ts +5 -0
- package/dist/components/focus.js +21 -1
- package/dist/components/markdownCodeBreaks.js +3 -4
- package/dist/components/pageHeaderStore.d.ts +41 -0
- package/dist/components/pageHeaderStore.js +67 -0
- package/dist/components/pathBreaks.d.ts +8 -0
- package/dist/components/pathBreaks.js +28 -0
- package/dist/components/segmented.js +1 -1
- package/dist/components/shortcutKey.d.ts +2 -1
- package/dist/components/shortcutKey.js +19 -2
- package/dist/components/splitter.js +1 -1
- package/dist/components/useCssIsDark.js +40 -18
- package/dist/components/useTheme.js +9 -10
- package/dist/dev.d.ts +9 -0
- package/dist/dev.js +14 -0
- package/dist/editor/Editor.d.ts +3 -2
- package/dist/editor/Editor.js +24 -5
- package/dist/editor/EditorField.d.ts +2 -1
- package/dist/editor/EditorField.js +11 -29
- package/dist/editor/FormCodePanel.d.ts +7 -3
- package/dist/editor/FormCodePanel.js +14 -7
- package/dist/editor/Monaco.d.ts +22 -6
- package/dist/editor/Monaco.js +177 -113
- package/dist/editor/editorModel.d.ts +1 -1
- package/dist/editor/editorModel.js +1 -1
- package/dist/editor/index.d.ts +6 -5
- package/dist/editor/index.js +5 -4
- package/dist/editor/languages.d.ts +24 -0
- package/dist/editor/languages.js +31 -0
- package/dist/editor/monacoFeatures.d.ts +7 -0
- package/dist/editor/monacoFeatures.js +19 -0
- package/dist/editor/themes.d.ts +8 -5
- package/dist/editor/themes.js +65 -32
- package/dist/editor/workers.d.ts +3 -3
- package/dist/editor/workers.js +8 -4
- package/dist/editor/yaml.d.ts +6 -2
- package/dist/editor/yaml.js +11 -2
- package/dist/editor/yamlLanguage.js +55 -38
- package/dist/file-explorer/FileExplorer.d.ts +18 -4
- package/dist/file-explorer/FileExplorer.js +204 -142
- package/dist/file-explorer/FileExplorerContext.js +1 -1
- package/dist/file-explorer/FilePreview/StreamedBadge.js +3 -1
- package/dist/file-explorer/FilePreview/Viewer.js +14 -10
- package/dist/file-explorer/FilePreview/index.js +4 -4
- package/dist/file-explorer/FileRow.d.ts +6 -2
- package/dist/file-explorer/FileRow.js +35 -17
- package/dist/file-explorer/FileRowsWindow.d.ts +2 -1
- package/dist/file-explorer/FileRowsWindow.js +36 -4
- package/dist/file-explorer/FileTable.d.ts +3 -1
- package/dist/file-explorer/FileTable.js +6 -3
- package/dist/file-explorer/TreeView.d.ts +5 -1
- package/dist/file-explorer/TreeView.js +86 -39
- package/dist/file-explorer/helpers.d.ts +2 -1
- package/dist/file-explorer/helpers.js +24 -23
- package/dist/file-explorer/lib/utils.d.ts +3 -0
- package/dist/file-explorer/lib/utils.js +6 -1
- package/dist/file-explorer/toasts.js +27 -19
- package/dist/file-explorer/treeRows.d.ts +6 -0
- package/dist/file-explorer/treeRows.js +19 -1
- package/dist/file-explorer/useNearEnd.js +3 -6
- package/dist/form/Fields/CheckboxGroupField.js +12 -5
- package/dist/form/Fields/DurationField.js +1 -1
- package/dist/form/Fields/LabelField.js +1 -1
- package/dist/form/Fields/ObjectField.d.ts +1 -1
- package/dist/form/Fields/ObjectField.js +3 -2
- package/dist/form/Fields/StringField.js +16 -29
- package/dist/form/Fields/TextAreaField.js +3 -4
- package/dist/form/Form.js +3 -8
- package/dist/form/Wizard/WizardNavigation.js +0 -3
- package/dist/form/Wizard/utils.js +2 -1
- package/dist/form/fieldFrame.d.ts +1 -1
- package/dist/form/fieldFrame.js +2 -2
- package/dist/form/types/fieldComponentTypes.d.ts +2 -1
- package/dist/graph/AnnotationBanner.d.ts +1 -2
- package/dist/graph/AnnotationBanner.js +30 -32
- package/dist/graph/Connectors.js +4 -1
- package/dist/graph/DependencyGraph.js +2 -2
- package/dist/graph/GraphEditor.js +11 -9
- package/dist/graph/GraphEditorDialogs.js +1 -1
- package/dist/graph/GraphNode.js +7 -4
- package/dist/graph/InputDialog.js +1 -1
- package/dist/graph/InputsEditor.js +14 -11
- package/dist/graph/MatrixGroup.js +9 -3
- package/dist/graph/Reveal.js +18 -10
- package/dist/graph/ShortcutsButton.d.ts +11 -2
- package/dist/graph/ShortcutsButton.js +14 -3
- package/dist/graph/TreeView.js +35 -18
- package/dist/graph/WorkflowSettingsDialog.js +1 -1
- package/dist/graph/editorFields.js +1 -1
- package/dist/graph/editorRows.js +16 -10
- package/dist/graph/editorStrings.d.ts +7 -0
- package/dist/graph/editorStrings.js +8 -1
- package/dist/graph/inputRefs.js +1 -1
- package/dist/graph/settingsViews.js +11 -18
- package/dist/graph/stepWith.js +1 -1
- package/dist/icons.d.ts +2 -0
- package/dist/icons.js +4 -2
- package/dist/index.d.ts +12 -12
- package/dist/index.js +16 -16
- package/dist/list/ActionToolbar.d.ts +42 -6
- package/dist/list/ActionToolbar.js +298 -101
- package/dist/list/ListPage.d.ts +15 -23
- package/dist/list/ListPage.js +42 -43
- package/dist/list/ListTable.d.ts +37 -7
- package/dist/list/ListTable.js +52 -12
- package/dist/list/ListViewControls.js +1 -1
- package/dist/list/UserHoverCard.js +7 -15
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +2 -2
- package/dist/list/listSearch.js +12 -10
- package/dist/list/listView.d.ts +10 -1
- package/dist/list/listView.js +15 -1
- package/dist/logviewer/LogViewer.d.ts +4 -2
- package/dist/logviewer/LogViewer.js +87 -69
- package/dist/logviewer/logviewer.css +3 -2
- package/dist/reducedMotion.d.ts +5 -0
- package/dist/reducedMotion.js +20 -0
- package/dist/safeUrl.d.ts +1 -1
- package/dist/safeUrl.js +4 -2
- package/dist/styles.css +1 -1
- package/package.json +5 -2
- package/dist/components/Breadcrumbs.d.ts +0 -37
- package/dist/components/Breadcrumbs.js +0 -90
- package/dist/components/CopyToClipboard.d.ts +0 -17
- package/dist/components/CopyToClipboard.js +0 -66
- package/dist/components/Sort.d.ts +0 -9
- package/dist/components/Sort.js +0 -42
- package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +0 -6
- package/dist/file-explorer/FilePreview/CodePreviewEditor.js +0 -64
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { modeOf, resolveMode, schemeFor } from "../theme/model.js";
|
|
2
2
|
import { generateTheme } from "../theme/derive.js";
|
|
3
3
|
import { applyTheme } from "../theme/index.js";
|
|
4
|
-
import {
|
|
4
|
+
import { useLayoutEffect, useSyncExternalStore } from "react";
|
|
5
5
|
//#region src/components/useTheme.ts
|
|
6
6
|
var DARK = "(prefers-color-scheme: dark)";
|
|
7
7
|
var prefersDark = () => typeof matchMedia === "function" && matchMedia(DARK).matches;
|
|
8
|
+
function subscribeToScheme(onChange) {
|
|
9
|
+
if (typeof matchMedia !== "function") return () => {};
|
|
10
|
+
const media = matchMedia(DARK);
|
|
11
|
+
media.addEventListener("change", onChange);
|
|
12
|
+
return () => media.removeEventListener("change", onChange);
|
|
13
|
+
}
|
|
14
|
+
var ignore = () => () => {};
|
|
8
15
|
/** The mode a preference shows now, following the device while it's `system`. */
|
|
9
16
|
function useColorMode(preference) {
|
|
10
|
-
const
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
if (preference !== "system" || typeof matchMedia !== "function") return;
|
|
13
|
-
const media = matchMedia(DARK);
|
|
14
|
-
const update = () => setDark(media.matches);
|
|
15
|
-
update();
|
|
16
|
-
media.addEventListener("change", update);
|
|
17
|
-
return () => media.removeEventListener("change", update);
|
|
18
|
-
}, [preference]);
|
|
17
|
+
const dark = useSyncExternalStore(preference === "system" ? subscribeToScheme : ignore, prefersDark, () => false);
|
|
19
18
|
return resolveMode(preference, dark);
|
|
20
19
|
}
|
|
21
20
|
/**
|
package/dist/dev.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the host runs a development build, for checks that warn about misuse and cost too much
|
|
3
|
+
* to run in production.
|
|
4
|
+
*
|
|
5
|
+
* It reads `process.env.NODE_ENV`, which the host's bundler replaces, so a production build drops
|
|
6
|
+
* the checks and a development build keeps them. Vite's `DEV` flag would not do: this
|
|
7
|
+
* package's own library build replaces it with `false`, so no host would ever see the warning.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isDev(): boolean;
|
package/dist/dev.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/dev.ts
|
|
2
|
+
/**
|
|
3
|
+
* Whether the host runs a development build, for checks that warn about misuse and cost too much
|
|
4
|
+
* to run in production.
|
|
5
|
+
*
|
|
6
|
+
* It reads `process.env.NODE_ENV`, which the host's bundler replaces, so a production build drops
|
|
7
|
+
* the checks and a development build keeps them. Vite's `DEV` flag would not do: this
|
|
8
|
+
* package's own library build replaces it with `false`, so no host would ever see the warning.
|
|
9
|
+
*/
|
|
10
|
+
function isDev() {
|
|
11
|
+
return process.env.NODE_ENV !== "production";
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { isDev };
|
package/dist/editor/Editor.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type { EditorProps } from './Monaco.js';
|
|
2
|
+
/** A Monaco code editor, loaded on first render so Monaco stays out of the host's first bundle. */
|
|
3
|
+
export declare function Editor(props: EditorProps): import("react").JSX.Element;
|
package/dist/editor/Editor.js
CHANGED
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
import { Loader } from "../components/Loader.js";
|
|
2
|
+
import { editorLanguagesLoading } from "./languages.js";
|
|
2
3
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Suspense, lazy } from "react";
|
|
4
|
+
import { Suspense, lazy, use } from "react";
|
|
4
5
|
//#region src/editor/Editor.tsx
|
|
5
|
-
var
|
|
6
|
+
var loadMonaco = () => import("./Monaco.js");
|
|
7
|
+
var MonacoEditor = lazy(loadMonaco);
|
|
8
|
+
function LoadedEditor(props) {
|
|
9
|
+
const languages = editorLanguagesLoading();
|
|
10
|
+
if (languages) {
|
|
11
|
+
loadMonaco();
|
|
12
|
+
use(languages);
|
|
13
|
+
}
|
|
14
|
+
return /* @__PURE__ */ jsx(MonacoEditor, { ...props });
|
|
15
|
+
}
|
|
16
|
+
/** A Monaco code editor, loaded on first render so Monaco stays out of the host's first bundle. */
|
|
6
17
|
function Editor(props) {
|
|
18
|
+
const { width = "100%", height = "100%" } = props;
|
|
7
19
|
return /* @__PURE__ */ jsx(Suspense, {
|
|
8
|
-
fallback: /* @__PURE__ */ jsx(
|
|
9
|
-
|
|
20
|
+
fallback: /* @__PURE__ */ jsx("div", {
|
|
21
|
+
style: {
|
|
22
|
+
width,
|
|
23
|
+
height
|
|
24
|
+
},
|
|
25
|
+
className: "flex items-center justify-center",
|
|
26
|
+
children: /* @__PURE__ */ jsx(Loader, {})
|
|
27
|
+
}),
|
|
28
|
+
children: /* @__PURE__ */ jsx(LoadedEditor, { ...props })
|
|
10
29
|
});
|
|
11
30
|
}
|
|
12
31
|
//#endregion
|
|
13
|
-
export { Editor
|
|
32
|
+
export { Editor };
|
|
@@ -7,4 +7,5 @@ export interface IEditorField extends BaseField {
|
|
|
7
7
|
language?: string;
|
|
8
8
|
};
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
/** A form field that edits its value as code, in the language its `options` name (shell by default). */
|
|
11
|
+
export declare function EditorField(props: FieldComponentProps<IEditorField>): import("react").JSX.Element;
|
|
@@ -1,45 +1,27 @@
|
|
|
1
|
-
import { cx } from "../cx.js";
|
|
2
1
|
import { Field } from "../components/Field.js";
|
|
3
2
|
import { fieldFrame } from "../form/fieldFrame.js";
|
|
4
3
|
import { useFieldValue } from "../form/useFieldValue.js";
|
|
5
|
-
import Editor from "./Editor.js";
|
|
4
|
+
import { Editor } from "./Editor.js";
|
|
6
5
|
import { jsx } from "react/jsx-runtime";
|
|
7
|
-
import { useMemo, useRef } from "react";
|
|
8
|
-
import { useFormContext, useWatch } from "react-hook-form";
|
|
9
6
|
//#region src/editor/EditorField.tsx
|
|
7
|
+
/** A form field that edits its value as code, in the language its `options` name (shell by default). */
|
|
10
8
|
function EditorField(props) {
|
|
11
9
|
const { field, label, disabled, onChange } = props;
|
|
12
|
-
const
|
|
13
|
-
const [value, change] = useFieldValue(fieldName);
|
|
14
|
-
const touchedRef = useRef(false);
|
|
15
|
-
const handleChange = (val) => {
|
|
16
|
-
touchedRef.current = true;
|
|
17
|
-
onChange?.(val);
|
|
18
|
-
change(val);
|
|
19
|
-
};
|
|
20
|
-
const { control } = useFormContext();
|
|
21
|
-
const resetKey = useWatch({
|
|
22
|
-
control,
|
|
23
|
-
name: "editorKeyPostfix"
|
|
24
|
-
});
|
|
25
|
-
const editorKeyPostfix = typeof resetKey === "string" ? resetKey : "";
|
|
26
|
-
const postfixKey = useMemo(() => {
|
|
27
|
-
const randomKey = Math.random().toString(36).substring(7);
|
|
28
|
-
return editorKeyPostfix || randomKey;
|
|
29
|
-
}, [editorKeyPostfix]);
|
|
10
|
+
const [value, change] = useFieldValue(field.name ?? "");
|
|
30
11
|
return /* @__PURE__ */ jsx(Field, {
|
|
31
12
|
...fieldFrame(props),
|
|
32
13
|
children: /* @__PURE__ */ jsx(Editor, {
|
|
33
14
|
ariaLabel: label,
|
|
34
15
|
height: "200px",
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
16
|
+
value: value ?? "",
|
|
17
|
+
disabled,
|
|
18
|
+
onChange: (text) => {
|
|
19
|
+
onChange?.(text);
|
|
20
|
+
change(text);
|
|
21
|
+
},
|
|
40
22
|
language: field.options?.language || "shell"
|
|
41
|
-
}
|
|
23
|
+
})
|
|
42
24
|
});
|
|
43
25
|
}
|
|
44
26
|
//#endregion
|
|
45
|
-
export { EditorField
|
|
27
|
+
export { EditorField };
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
export interface FormCodePanelProps {
|
|
2
|
+
/** The form's input definitions, which say which values are sensitive or hidden. */
|
|
2
3
|
formJSON: Record<string, unknown>;
|
|
4
|
+
/** The form's values, shown as JSON. */
|
|
3
5
|
data: Record<string, unknown>;
|
|
6
|
+
/** Called with the values each time the JSON parses as an object. */
|
|
4
7
|
mutate: (values: Record<string, unknown>) => void;
|
|
5
8
|
height?: string;
|
|
6
9
|
disabled?: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
10
|
+
}
|
|
11
|
+
/** A form's values as editable JSON, with sensitive and hidden fields left out unless asked for. */
|
|
12
|
+
export declare function FormCodePanel({ formJSON, data, mutate, height, disabled, }: FormCodePanelProps): import("react").JSX.Element;
|
|
@@ -5,7 +5,7 @@ import { useStrings, useWorkflowEngine } from "../components/Provider.js";
|
|
|
5
5
|
import { useCopy } from "../components/useCopy.js";
|
|
6
6
|
import { Switch } from "../components/Switch.js";
|
|
7
7
|
import { flattenGroups, impureSetValueFromPath } from "../form/lib.js";
|
|
8
|
-
import Editor from "./Editor.js";
|
|
8
|
+
import { Editor } from "./Editor.js";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
import { useRef, useState } from "react";
|
|
11
11
|
//#region src/editor/FormCodePanel.tsx
|
|
@@ -68,6 +68,7 @@ var populateFiltered = (filteredFields, data) => {
|
|
|
68
68
|
});
|
|
69
69
|
return data;
|
|
70
70
|
};
|
|
71
|
+
/** A form's values as editable JSON, with sensitive and hidden fields left out unless asked for. */
|
|
71
72
|
function FormCodePanel({ formJSON, data, mutate, height = "600px", disabled = false }) {
|
|
72
73
|
const engine = useWorkflowEngine();
|
|
73
74
|
const { common: t } = useStrings();
|
|
@@ -85,12 +86,14 @@ function FormCodePanel({ formJSON, data, mutate, height = "600px", disabled = fa
|
|
|
85
86
|
const filteredFieldsRef = useRef(filteredFields);
|
|
86
87
|
filteredFieldsRef.current = filteredFields;
|
|
87
88
|
const json = JSON.stringify(displayObj, null, 2);
|
|
89
|
+
const typedRef = useRef(null);
|
|
90
|
+
const shown = typedRef.current?.json === json ? typedRef.current.text : json;
|
|
88
91
|
const handleCopy = () => void copy(json, { quiet: true });
|
|
89
92
|
return /* @__PURE__ */ jsxs("div", {
|
|
90
93
|
style: { height },
|
|
91
94
|
className: "flex w-full flex-col gap-2",
|
|
92
95
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
93
|
-
className: cx("flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border", jsonHasErrors ? "border-
|
|
96
|
+
className: cx("flex min-h-0 flex-1 flex-col overflow-hidden rounded-md border", jsonHasErrors ? "border-(--theme-error)" : "border-(--theme-border)"),
|
|
94
97
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
95
98
|
className: "bg-(--theme-muted-panel-bg) text-(--theme-muted-text-color) flex shrink-0 items-center gap-3 border-b border-(--theme-border) px-3 py-2",
|
|
96
99
|
children: [hasHiddenFields && /* @__PURE__ */ jsx(Tooltip, {
|
|
@@ -111,13 +114,13 @@ function FormCodePanel({ formJSON, data, mutate, height = "600px", disabled = fa
|
|
|
111
114
|
onClick: handleCopy,
|
|
112
115
|
"aria-label": copied ? t.copied : t.copy,
|
|
113
116
|
className: "ml-auto flex shrink-0 items-center gap-1.5 rounded-md border border-(--theme-border) px-2.5 py-1.5 text-sm text-(--theme-app) transition-colors duration-150 hover:bg-(--theme-hover) focus:outline-none focus-visible:ring-2 focus-visible:ring-(--theme-link)",
|
|
114
|
-
children: [copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-
|
|
117
|
+
children: [copied ? /* @__PURE__ */ jsx(CheckIcon, { className: "text-(--theme-success)" }) : /* @__PURE__ */ jsx(CopyIcon, { className: "text-(--theme-muted-text-color)" }), copied ? t.copied : t.copy]
|
|
115
118
|
})]
|
|
116
119
|
}), /* @__PURE__ */ jsx("div", {
|
|
117
120
|
className: "min-h-0 flex-1",
|
|
118
121
|
children: /* @__PURE__ */ jsx(Editor, {
|
|
119
122
|
height: "100%",
|
|
120
|
-
value:
|
|
123
|
+
value: shown,
|
|
121
124
|
onValidate: isValidJson,
|
|
122
125
|
className: "!rounded-none !border-0",
|
|
123
126
|
minimap: { enabled: false },
|
|
@@ -140,7 +143,11 @@ function FormCodePanel({ formJSON, data, mutate, height = "600px", disabled = fa
|
|
|
140
143
|
try {
|
|
141
144
|
const parsed = JSON.parse(e);
|
|
142
145
|
if (!isObject(parsed)) return;
|
|
143
|
-
|
|
146
|
+
typedRef.current = {
|
|
147
|
+
text: e,
|
|
148
|
+
json: JSON.stringify(parsed, null, 2)
|
|
149
|
+
};
|
|
150
|
+
mutate(showHiddenRef.current ? parsed : populateFiltered(filteredFieldsRef.current, structuredClone(parsed)));
|
|
144
151
|
} catch {}
|
|
145
152
|
},
|
|
146
153
|
language: "json",
|
|
@@ -148,10 +155,10 @@ function FormCodePanel({ formJSON, data, mutate, height = "600px", disabled = fa
|
|
|
148
155
|
})
|
|
149
156
|
})]
|
|
150
157
|
}), jsonHasErrors && /* @__PURE__ */ jsx("p", {
|
|
151
|
-
className: "shrink-0 text-sm text-
|
|
158
|
+
className: "shrink-0 text-sm text-(--theme-error-text)",
|
|
152
159
|
children: t.jsonHasErrors
|
|
153
160
|
})]
|
|
154
161
|
});
|
|
155
162
|
}
|
|
156
163
|
//#endregion
|
|
157
|
-
export { FormCodePanel
|
|
164
|
+
export { FormCodePanel };
|
package/dist/editor/Monaco.d.ts
CHANGED
|
@@ -1,19 +1,35 @@
|
|
|
1
|
-
import * as monaco from 'monaco-editor';
|
|
1
|
+
import * as monaco from 'monaco-editor/editor/editor.api';
|
|
2
2
|
import { type NestedWorkflowText } from './nestedText.js';
|
|
3
|
-
|
|
3
|
+
import './monacoFeatures.js';
|
|
4
|
+
/** A problem Monaco or the YAML service found in the text, as `onValidate` reports it. */
|
|
5
|
+
export type ValidationMarker = monaco.editor.IMarker;
|
|
4
6
|
/** A problem to mark on one line of the editor. */
|
|
5
7
|
export interface EditorMarker {
|
|
6
8
|
line: number;
|
|
7
9
|
message: string;
|
|
8
10
|
}
|
|
9
|
-
export interface
|
|
11
|
+
export interface EditorProps extends monaco.editor.IStandaloneEditorConstructionOptions {
|
|
10
12
|
className?: string;
|
|
13
|
+
/** Shows the text greyed out and read-only, as a disabled field does. */
|
|
11
14
|
disabled?: boolean | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Shows the text to read rather than edit: it stays selectable, copyable and reachable by
|
|
17
|
+
* keyboard, announces itself read-only, and shows no cursor, current line or quick fixes. The
|
|
18
|
+
* view ends at the last line, and the wheel scrolls the page once the text has none left.
|
|
19
|
+
*/
|
|
20
|
+
readOnly?: boolean;
|
|
21
|
+
/** The text as the person edits it, with carriage returns removed. */
|
|
12
22
|
onChange?: (value: string) => void;
|
|
13
|
-
|
|
23
|
+
/** Every marker on the text, each time they change: the schema's, the lint's and the host's. */
|
|
24
|
+
onValidate?: (markers: ValidationMarker[]) => void;
|
|
14
25
|
width?: string | number;
|
|
15
26
|
height?: string | number;
|
|
16
|
-
|
|
27
|
+
/**
|
|
28
|
+
* The model's URI. A YAML schema registered with `configureEditorYaml` applies where its
|
|
29
|
+
* `fileMatch` matches this path, and `revealLines` finds the editor by it. Each editor gets one
|
|
30
|
+
* of its own when left out. It is read once: give the editor a `key` to edit another path.
|
|
31
|
+
*/
|
|
32
|
+
path?: string;
|
|
17
33
|
/** Apply outside `value` changes as undoable edits instead of resetting the undo history. */
|
|
18
34
|
preserveUndo?: boolean;
|
|
19
35
|
/** Checks a whole workflow for what the schema can't, such as needs read but never listed. */
|
|
@@ -23,4 +39,4 @@ export interface IEditorProps extends monaco.editor.IStandaloneEditorConstructio
|
|
|
23
39
|
/** Set when the text is one job or step, for completions that touch the rest of the workflow. */
|
|
24
40
|
nested?: NestedWorkflowText;
|
|
25
41
|
}
|
|
26
|
-
export default function MonacoEditor({ className, disabled, onChange, onValidate, width, height, path, preserveUndo, lint, markers, nested, ...options }:
|
|
42
|
+
export default function MonacoEditor({ className, disabled, onChange, onValidate, width, height, path: pathProp, preserveUndo, lint, markers, nested, value, language, ...options }: EditorProps): import("react").JSX.Element;
|
package/dist/editor/Monaco.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cx } from "../cx.js";
|
|
2
|
+
import { useStrings } from "../components/Provider.js";
|
|
2
3
|
import { useCssIsDark } from "../components/useCssIsDark.js";
|
|
3
4
|
import { HOST_MARKER_OWNER, LINT_OWNER } from "./lintOwner.js";
|
|
4
5
|
import { lintContext, useLintEditing, useLintSources } from "./lintContext.js";
|
|
@@ -7,10 +8,11 @@ import { registerRevealer } from "./reveal.js";
|
|
|
7
8
|
import { defineEditorThemes, followThemeTokens, getThemeName } from "./themes.js";
|
|
8
9
|
import { setupMonacoWorkers } from "./workers.js";
|
|
9
10
|
import { holdListeners, modelFor } from "./editorModel.js";
|
|
11
|
+
import "./monacoFeatures.js";
|
|
10
12
|
import { ensureYamlLanguage } from "./yamlLanguage.js";
|
|
11
13
|
import { jsx } from "react/jsx-runtime";
|
|
12
|
-
import { useEffect, useLayoutEffect, useRef } from "react";
|
|
13
|
-
import * as monaco from "monaco-editor";
|
|
14
|
+
import { useEffect, useId, useLayoutEffect, useRef } from "react";
|
|
15
|
+
import * as monaco from "monaco-editor/editor/editor.api";
|
|
14
16
|
//#region src/editor/Monaco.tsx
|
|
15
17
|
setupMonacoWorkers();
|
|
16
18
|
var SCHEMA_UNREADABLE = "768";
|
|
@@ -38,25 +40,177 @@ function editorText(value) {
|
|
|
38
40
|
return value.replace(/\r/g, "");
|
|
39
41
|
}
|
|
40
42
|
var noop = () => {};
|
|
41
|
-
|
|
43
|
+
var DISABLED_BACKGROUNDS = [
|
|
44
|
+
"--vscode-editor-background",
|
|
45
|
+
"--vscode-editorGutter-background",
|
|
46
|
+
"--vscode-editorStickyScroll-background",
|
|
47
|
+
"--vscode-minimap-background",
|
|
48
|
+
"--vscode-editorOverviewRuler-background"
|
|
49
|
+
];
|
|
50
|
+
function minimalEdit(model, from, to) {
|
|
51
|
+
let start = 0;
|
|
52
|
+
const shortest = Math.min(from.length, to.length);
|
|
53
|
+
while (start < shortest && from[start] === to[start]) start++;
|
|
54
|
+
let end = 0;
|
|
55
|
+
while (end < shortest - start && from[from.length - 1 - end] === to[to.length - 1 - end]) end++;
|
|
56
|
+
const a = model.getPositionAt(start);
|
|
57
|
+
const b = model.getPositionAt(from.length - end);
|
|
58
|
+
return {
|
|
59
|
+
range: new monaco.Range(a.lineNumber, a.column, b.lineNumber, b.column),
|
|
60
|
+
text: to.slice(start, to.length - end)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop, width = "100%", height = "100%", path: pathProp, preserveUndo = false, lint = false, markers, nested, value, language, ...options }) {
|
|
64
|
+
const { common: t } = useStrings();
|
|
65
|
+
const ownPath = `file:///editor/${useId().replace(/[^\w-]/g, "")}`;
|
|
66
|
+
const path = useRef(pathProp ?? ownPath).current;
|
|
42
67
|
const isDark = useCssIsDark();
|
|
68
|
+
const isDarkRef = useRef(isDark);
|
|
69
|
+
isDarkRef.current = isDark;
|
|
43
70
|
const readOnly = Boolean(disabled || options.readOnly);
|
|
71
|
+
const containerRef = useRef(null);
|
|
44
72
|
const monacoRef = useRef(null);
|
|
45
73
|
const isSyncingValueRef = useRef(false);
|
|
46
74
|
const lintSources = useLintSources();
|
|
47
75
|
const lintSourcesRef = useRef(lintSources);
|
|
48
76
|
lintSourcesRef.current = lintSources;
|
|
49
77
|
const runLintRef = useRef(null);
|
|
50
|
-
const unregisterRevealRef = useRef(null);
|
|
51
|
-
const listenersRef = useRef([]);
|
|
52
78
|
const nestedRef = useRef(nested);
|
|
53
79
|
nestedRef.current = nested;
|
|
54
80
|
const isNested = nested !== void 0;
|
|
81
|
+
const onChangeRef = useRef(onChange);
|
|
82
|
+
onChangeRef.current = onChange;
|
|
83
|
+
const onValidateRef = useRef(onValidate);
|
|
84
|
+
onValidateRef.current = onValidate;
|
|
85
|
+
const markersRef = useRef(markers);
|
|
86
|
+
markersRef.current = markers;
|
|
87
|
+
const editorOptions = {
|
|
88
|
+
ariaLabel: t.codeEditor,
|
|
89
|
+
readOnlyMessage: { value: t.readOnlyText },
|
|
90
|
+
domReadOnly: readOnly,
|
|
91
|
+
hideCursorInOverviewRuler: readOnly,
|
|
92
|
+
lightbulb: { enabled: readOnly ? monaco.editor.ShowLightbulbIconMode.Off : monaco.editor.ShowLightbulbIconMode.OnCode },
|
|
93
|
+
scrollBeyondLastLine: !readOnly,
|
|
94
|
+
...options,
|
|
95
|
+
scrollbar: {
|
|
96
|
+
alwaysConsumeMouseWheel: !readOnly,
|
|
97
|
+
...options.scrollbar
|
|
98
|
+
},
|
|
99
|
+
readOnly,
|
|
100
|
+
renderLineHighlight: disabled ? "none" : options.renderLineHighlight ?? (readOnly ? "none" : "line")
|
|
101
|
+
};
|
|
102
|
+
const optionsKey = JSON.stringify(editorOptions);
|
|
103
|
+
const optionsRef = useRef(editorOptions);
|
|
104
|
+
optionsRef.current = editorOptions;
|
|
105
|
+
const initialRef = useRef({
|
|
106
|
+
value,
|
|
107
|
+
language
|
|
108
|
+
});
|
|
55
109
|
const lintEditing = useLintEditing(lint);
|
|
56
110
|
const lintEditingRef = useRef(lintEditing);
|
|
57
111
|
lintEditingRef.current = lintEditing;
|
|
58
112
|
const lintRef = useRef(lint);
|
|
59
113
|
lintRef.current = lint;
|
|
114
|
+
useLayoutEffect(() => {
|
|
115
|
+
const container = containerRef.current;
|
|
116
|
+
if (!container) return;
|
|
117
|
+
defineEditorThemes(monaco.editor);
|
|
118
|
+
monaco.editor.setTheme(getThemeName(isDarkRef.current));
|
|
119
|
+
const { value: initial, language: initialLanguage } = initialRef.current;
|
|
120
|
+
const model = modelFor(monaco.Uri.parse(path), initial ?? "", initialLanguage);
|
|
121
|
+
const editor = monaco.editor.create(container, {
|
|
122
|
+
automaticLayout: true,
|
|
123
|
+
model,
|
|
124
|
+
...optionsRef.current,
|
|
125
|
+
fixedOverflowWidgets: true,
|
|
126
|
+
suggest: {
|
|
127
|
+
preview: true,
|
|
128
|
+
showWords: false,
|
|
129
|
+
showInlineDetails: true
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
setMarkers(model, HOST_MARKER_OWNER, (markersRef.current ?? []).map((marker) => lintMarker(model, marker)));
|
|
133
|
+
setMarkers(model, LINT_OWNER, []);
|
|
134
|
+
const runLint = () => {
|
|
135
|
+
const editing = lintEditingRef.current;
|
|
136
|
+
if (!lintRef.current || !editing || model.isDisposed()) return;
|
|
137
|
+
const schema = monaco.editor.getModelMarkers({ resource: model.uri }).filter((marker) => marker.owner !== "workflowlint" && marker.owner !== "workflowmarkers" && String(marker.code ?? "") !== SCHEMA_UNREADABLE);
|
|
138
|
+
const source = model.getValue();
|
|
139
|
+
setMarkers(model, LINT_OWNER, schema.length > 0 ? [] : editing.lintWorkflow(source, lintContext(editing, source, lintSourcesRef.current, runLint)).map((problem) => lintMarker(model, problem)));
|
|
140
|
+
};
|
|
141
|
+
runLintRef.current = runLint;
|
|
142
|
+
let lintTimer;
|
|
143
|
+
const validate = () => {
|
|
144
|
+
runLint();
|
|
145
|
+
onValidateRef.current(monaco.editor.getModelMarkers({ resource: model.uri }));
|
|
146
|
+
};
|
|
147
|
+
const modelListeners = [
|
|
148
|
+
model.onDidChangeContent(() => {
|
|
149
|
+
if (lintRef.current) {
|
|
150
|
+
window.clearTimeout(lintTimer);
|
|
151
|
+
lintTimer = window.setTimeout(runLint, 300);
|
|
152
|
+
}
|
|
153
|
+
if (isSyncingValueRef.current) return;
|
|
154
|
+
onChangeRef.current(editorText(editor.getValue()));
|
|
155
|
+
}),
|
|
156
|
+
monaco.editor.onDidChangeMarkers((resources) => {
|
|
157
|
+
const uri = model.uri.toString();
|
|
158
|
+
if (resources.some((resource) => resource.toString() === uri)) validate();
|
|
159
|
+
}),
|
|
160
|
+
{ dispose: () => window.clearTimeout(lintTimer) }
|
|
161
|
+
];
|
|
162
|
+
holdListeners(model, modelListeners);
|
|
163
|
+
validate();
|
|
164
|
+
const unregisterReveal = registerRevealer(path, (start, end) => {
|
|
165
|
+
const last = Math.min(Math.max(start, end), model.getLineCount());
|
|
166
|
+
editor.revealLinesInCenterIfOutsideViewport(start, last);
|
|
167
|
+
editor.setPosition({
|
|
168
|
+
lineNumber: start,
|
|
169
|
+
column: model.getLineFirstNonWhitespaceColumn(start) || 1
|
|
170
|
+
});
|
|
171
|
+
const flash = editor.createDecorationsCollection([{
|
|
172
|
+
range: new monaco.Range(start, 1, last, 1),
|
|
173
|
+
options: {
|
|
174
|
+
isWholeLine: true,
|
|
175
|
+
className: "bg-(--theme-accent)/20"
|
|
176
|
+
}
|
|
177
|
+
}]);
|
|
178
|
+
window.setTimeout(() => flash.clear(), 1500);
|
|
179
|
+
});
|
|
180
|
+
const unfollow = followThemeTokens(monaco.editor, () => getThemeName(isDarkRef.current));
|
|
181
|
+
ensureYamlLanguage();
|
|
182
|
+
monacoRef.current = editor;
|
|
183
|
+
return () => {
|
|
184
|
+
unfollow();
|
|
185
|
+
unregisterReveal();
|
|
186
|
+
for (const listener of modelListeners) listener.dispose();
|
|
187
|
+
editor.dispose();
|
|
188
|
+
monacoRef.current = null;
|
|
189
|
+
runLintRef.current = null;
|
|
190
|
+
if (!model.isDisposed() && model.getLanguageId() !== "yaml") model.dispose();
|
|
191
|
+
};
|
|
192
|
+
}, [path]);
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
if (monacoRef.current) {
|
|
195
|
+
defineEditorThemes(monaco.editor);
|
|
196
|
+
monaco.editor.setTheme(getThemeName(isDark));
|
|
197
|
+
}
|
|
198
|
+
}, [isDark]);
|
|
199
|
+
useEffect(() => {
|
|
200
|
+
const node = monacoRef.current?.getDomNode();
|
|
201
|
+
for (const name of DISABLED_BACKGROUNDS) if (disabled) node?.style.setProperty(name, "var(--theme-input-disabled-bg)");
|
|
202
|
+
else node?.style.removeProperty(name);
|
|
203
|
+
}, [disabled]);
|
|
204
|
+
useEffect(() => {
|
|
205
|
+
monacoRef.current?.getDomNode()?.querySelector("textarea.inputarea, .native-edit-context")?.setAttribute("aria-readonly", String(readOnly));
|
|
206
|
+
}, [readOnly, path]);
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
monacoRef.current?.updateOptions(optionsRef.current);
|
|
209
|
+
}, [optionsKey]);
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
const model = monacoRef.current?.getModel();
|
|
212
|
+
if (model && language && model.getLanguageId() !== language) monaco.editor.setModelLanguage(model, language);
|
|
213
|
+
}, [language]);
|
|
60
214
|
useEffect(() => {
|
|
61
215
|
const model = monacoRef.current?.getModel();
|
|
62
216
|
if (!lint && model) setMarkers(model, LINT_OWNER, []);
|
|
@@ -70,126 +224,36 @@ function MonacoEditor({ className, disabled, onChange = noop, onValidate = noop,
|
|
|
70
224
|
if (!isNested) return;
|
|
71
225
|
return publishNestedText(monaco.Uri.parse(path).toString(), nestedRef);
|
|
72
226
|
}, [path, isNested]);
|
|
73
|
-
const themeName = useRef(getThemeName(isDark, disabled));
|
|
74
|
-
themeName.current = getThemeName(isDark, disabled);
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
if (!monacoRef.current) return;
|
|
77
|
-
defineEditorThemes(monaco.editor);
|
|
78
|
-
monaco.editor.setTheme(getThemeName(isDark, disabled));
|
|
79
|
-
monacoRef.current.updateOptions({ readOnly });
|
|
80
|
-
}, [
|
|
81
|
-
disabled,
|
|
82
|
-
isDark,
|
|
83
|
-
readOnly
|
|
84
|
-
]);
|
|
85
|
-
useEffect(() => followThemeTokens(monaco.editor, () => themeName.current), []);
|
|
86
227
|
useLayoutEffect(() => {
|
|
87
|
-
const
|
|
88
|
-
|
|
228
|
+
const editor = monacoRef.current;
|
|
229
|
+
const model = editor?.getModel();
|
|
230
|
+
if (!editor || !model || value === void 0) return;
|
|
231
|
+
const current = model.getValue();
|
|
232
|
+
if (editorText(current) === editorText(value)) return;
|
|
89
233
|
isSyncingValueRef.current = true;
|
|
90
234
|
try {
|
|
91
235
|
if (preserveUndo) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
editor
|
|
99
|
-
}
|
|
236
|
+
editor.pushUndoStop();
|
|
237
|
+
model.pushEditOperations([], [minimalEdit(model, current, value)], () => null);
|
|
238
|
+
editor.pushUndoStop();
|
|
239
|
+
} else {
|
|
240
|
+
const view = editor.saveViewState();
|
|
241
|
+
model.setValue(value);
|
|
242
|
+
if (view) editor.restoreViewState(view);
|
|
243
|
+
}
|
|
100
244
|
} finally {
|
|
101
245
|
isSyncingValueRef.current = false;
|
|
102
246
|
}
|
|
103
|
-
}, [
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
return () => {
|
|
106
|
-
unregisterRevealRef.current?.();
|
|
107
|
-
for (const listener of listenersRef.current) listener.dispose();
|
|
108
|
-
monacoRef.current?.dispose();
|
|
109
|
-
monacoRef.current = null;
|
|
110
|
-
};
|
|
111
|
-
}, []);
|
|
112
|
-
/** Strips CR (\r) — Windows line endings break bash scripts. */
|
|
113
|
-
const onChangeWrapper = (value) => {
|
|
114
|
-
value = editorText(value);
|
|
115
|
-
onChange(value);
|
|
116
|
-
};
|
|
247
|
+
}, [value, preserveUndo]);
|
|
117
248
|
return /* @__PURE__ */ jsx("div", {
|
|
249
|
+
ref: containerRef,
|
|
118
250
|
style: {
|
|
119
251
|
width,
|
|
120
252
|
height
|
|
121
253
|
},
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
defineEditorThemes(monaco.editor);
|
|
126
|
-
monaco.editor.setTheme(getThemeName(isDark, disabled));
|
|
127
|
-
const model = modelFor(monaco.Uri.parse(path), options.value ?? "", options.language);
|
|
128
|
-
const editor = monaco.editor.create(ref, {
|
|
129
|
-
automaticLayout: true,
|
|
130
|
-
model,
|
|
131
|
-
...options,
|
|
132
|
-
readOnly,
|
|
133
|
-
fixedOverflowWidgets: true,
|
|
134
|
-
suggest: {
|
|
135
|
-
preview: true,
|
|
136
|
-
showWords: false,
|
|
137
|
-
showInlineDetails: true
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
setMarkers(model, HOST_MARKER_OWNER, (markers ?? []).map((marker) => lintMarker(model, marker)));
|
|
141
|
-
setMarkers(model, LINT_OWNER, []);
|
|
142
|
-
const runLint = () => {
|
|
143
|
-
const editing = lintEditingRef.current;
|
|
144
|
-
if (!lintRef.current || !editing || model.isDisposed()) return;
|
|
145
|
-
const schema = monaco.editor.getModelMarkers({ resource: model.uri }).filter((marker) => marker.owner !== "workflowlint" && marker.owner !== "workflowmarkers" && String(marker.code ?? "") !== SCHEMA_UNREADABLE);
|
|
146
|
-
const source = model.getValue();
|
|
147
|
-
setMarkers(model, LINT_OWNER, schema.length > 0 ? [] : editing.lintWorkflow(source, lintContext(editing, source, lintSourcesRef.current, runLint)).map((problem) => lintMarker(model, problem)));
|
|
148
|
-
};
|
|
149
|
-
runLintRef.current = runLint;
|
|
150
|
-
let lintTimer;
|
|
151
|
-
const validate = () => {
|
|
152
|
-
runLint();
|
|
153
|
-
onValidate(monaco.editor.getModelMarkers({ resource: model.uri }));
|
|
154
|
-
};
|
|
155
|
-
const modelListeners = [
|
|
156
|
-
model.onDidChangeContent(() => {
|
|
157
|
-
if (lintRef.current) {
|
|
158
|
-
window.clearTimeout(lintTimer);
|
|
159
|
-
lintTimer = window.setTimeout(runLint, 300);
|
|
160
|
-
}
|
|
161
|
-
if (isSyncingValueRef.current) return;
|
|
162
|
-
onChangeWrapper(editor.getValue());
|
|
163
|
-
}),
|
|
164
|
-
monaco.editor.onDidChangeMarkers((resources) => {
|
|
165
|
-
const uri = model.uri.toString();
|
|
166
|
-
if (resources.some((resource) => resource.toString() === uri)) validate();
|
|
167
|
-
}),
|
|
168
|
-
{ dispose: () => window.clearTimeout(lintTimer) }
|
|
169
|
-
];
|
|
170
|
-
holdListeners(model, modelListeners);
|
|
171
|
-
listenersRef.current = modelListeners;
|
|
172
|
-
validate();
|
|
173
|
-
unregisterRevealRef.current = registerRevealer(path, (start, end) => {
|
|
174
|
-
const last = Math.min(Math.max(start, end), model.getLineCount());
|
|
175
|
-
editor.revealLinesInCenterIfOutsideViewport(start, last);
|
|
176
|
-
editor.setPosition({
|
|
177
|
-
lineNumber: start,
|
|
178
|
-
column: model.getLineFirstNonWhitespaceColumn(start) || 1
|
|
179
|
-
});
|
|
180
|
-
const flash = editor.createDecorationsCollection([{
|
|
181
|
-
range: new monaco.Range(start, 1, last, 1),
|
|
182
|
-
options: {
|
|
183
|
-
isWholeLine: true,
|
|
184
|
-
className: "bg-(--theme-accent)/20"
|
|
185
|
-
}
|
|
186
|
-
}]);
|
|
187
|
-
window.setTimeout(() => flash.clear(), 1500);
|
|
188
|
-
});
|
|
189
|
-
ensureYamlLanguage();
|
|
190
|
-
monacoRef.current = editor;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
254
|
+
"data-disabled": disabled ? "" : void 0,
|
|
255
|
+
"data-read-only": readOnly ? "" : void 0,
|
|
256
|
+
className: cx("relative rounded border border-(--theme-border)", "focus-within:border-(--theme-accent) focus-within:ring-1 focus-within:ring-(--theme-accent)", "data-read-only:[&_.cursors-layer]:hidden data-disabled:[&_.view-lines]:opacity-60", className)
|
|
193
257
|
});
|
|
194
258
|
}
|
|
195
259
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as monaco from 'monaco-editor';
|
|
1
|
+
import * as monaco from 'monaco-editor/editor/editor.api';
|
|
2
2
|
/** The model a new editor on `uri` edits, holding `value`. */
|
|
3
3
|
export declare function modelFor(uri: monaco.Uri, value: string, language: string | undefined): monaco.editor.ITextModel;
|
|
4
4
|
/** An editor's listeners on its model, dropped when the next editor takes the model over. */
|