@gooddata/sdk-ui-kit 11.53.0-alpha.0 → 11.53.0-alpha.2
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/esm/@ui/UiConfigEditor/ConfigEditorToolbar.d.ts +26 -0
- package/esm/@ui/UiConfigEditor/ConfigEditorToolbar.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/ConfigEditorToolbar.js +38 -0
- package/esm/@ui/UiConfigEditor/UiConfigEditor.d.ts +20 -0
- package/esm/@ui/UiConfigEditor/UiConfigEditor.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/UiConfigEditor.js +229 -0
- package/esm/@ui/UiConfigEditor/configEditorGrammars.d.ts +15 -0
- package/esm/@ui/UiConfigEditor/configEditorGrammars.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/configEditorGrammars.js +50 -0
- package/esm/@ui/UiConfigEditor/configEditorHighlighting.d.ts +6 -0
- package/esm/@ui/UiConfigEditor/configEditorHighlighting.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/configEditorHighlighting.js +31 -0
- package/esm/@ui/UiConfigEditor/configEditorLanguage.d.ts +43 -0
- package/esm/@ui/UiConfigEditor/configEditorLanguage.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/configEditorLanguage.js +179 -0
- package/esm/@ui/UiConfigEditor/types.d.ts +135 -0
- package/esm/@ui/UiConfigEditor/types.d.ts.map +1 -0
- package/esm/@ui/UiConfigEditor/types.js +2 -0
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuHeader.d.ts.map +1 -1
- package/esm/@ui/UiMenu/components/defaults/DefaultUiMenuHeader.js +5 -2
- package/esm/@ui/UiPagedVirtualList/UiPagedVirtualList.d.ts.map +1 -1
- package/esm/@ui/UiPagedVirtualList/UiPagedVirtualList.js +3 -0
- package/esm/@ui/UiSubmenuHeader/UiSubmenuHeader.d.ts +2 -2
- package/esm/@ui/UiSubmenuHeader/UiSubmenuHeader.d.ts.map +1 -1
- package/esm/@ui/UiSubmenuHeader/UiSubmenuHeader.js +1 -0
- package/esm/@ui/hooks/useVirtualizerRectObserver.d.ts +12 -0
- package/esm/@ui/hooks/useVirtualizerRectObserver.d.ts.map +1 -0
- package/esm/@ui/hooks/useVirtualizerRectObserver.js +34 -0
- package/esm/Datepicker/Datepicker.d.ts +2 -4
- package/esm/Datepicker/Datepicker.d.ts.map +1 -1
- package/esm/Datepicker/Datepicker.js +4 -6
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.d.ts +13 -0
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.d.ts.map +1 -1
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.js +19 -4
- package/esm/Dropdown/DropdownList.d.ts +7 -1
- package/esm/Dropdown/DropdownList.d.ts.map +1 -1
- package/esm/Dropdown/DropdownList.js +3 -2
- package/esm/FlexDimensions/FlexDimensions.d.ts +2 -20
- package/esm/FlexDimensions/FlexDimensions.d.ts.map +1 -1
- package/esm/FlexDimensions/FlexDimensions.js +33 -54
- package/esm/FlexDimensions/typings.d.ts +8 -0
- package/esm/FlexDimensions/typings.d.ts.map +1 -1
- package/esm/FlexDimensions/typings.js +1 -1
- package/esm/Form/Input.d.ts +2 -33
- package/esm/Form/Input.d.ts.map +1 -1
- package/esm/Form/Input.js +30 -35
- package/esm/Form/InputPure.d.ts +40 -50
- package/esm/Form/InputPure.d.ts.map +1 -1
- package/esm/Form/InputPure.js +111 -121
- package/esm/Form/InputWithNumberFormat.d.ts.map +1 -1
- package/esm/Header/Header.d.ts +1 -1
- package/esm/Header/Header.d.ts.map +1 -1
- package/esm/Header/Header.js +4 -3
- package/esm/Header/WorkspacePickerHomeFooter.d.ts +1 -3
- package/esm/Header/WorkspacePickerHomeFooter.d.ts.map +1 -1
- package/esm/Header/WorkspacePickerHomeFooter.js +6 -6
- package/esm/Header/typings.d.ts +0 -2
- package/esm/Header/typings.d.ts.map +1 -1
- package/esm/List/DateDatasetsListItem.d.ts.map +1 -1
- package/esm/List/DateDatasetsListItem.js +1 -2
- package/esm/List/LegacyList.d.ts.map +1 -1
- package/esm/List/LegacyList.js +2 -20
- package/esm/List/List.d.ts.map +1 -1
- package/esm/List/List.js +2 -20
- package/esm/List/ListItem.d.ts +2 -0
- package/esm/List/ListItem.d.ts.map +1 -1
- package/esm/List/ListItem.js +2 -2
- package/esm/ParameterControl/AllowedValuesParameterControlDropdown.d.ts +22 -0
- package/esm/ParameterControl/AllowedValuesParameterControlDropdown.d.ts.map +1 -0
- package/esm/ParameterControl/AllowedValuesParameterControlDropdown.js +38 -0
- package/esm/ParameterControl/ParameterControl.d.ts +3 -2
- package/esm/ParameterControl/ParameterControl.d.ts.map +1 -1
- package/esm/ParameterControl/ParameterControl.js +9 -5
- package/esm/ShortenedText/ShortenedText.d.ts +10 -14
- package/esm/ShortenedText/ShortenedText.d.ts.map +1 -1
- package/esm/ShortenedText/ShortenedText.js +85 -96
- package/esm/index.d.ts +8 -4
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +3 -2
- package/esm/sdk-ui-kit.d.ts +264 -170
- package/esm/syntaxHighlightingInput/SyntaxHighlightingInput.d.ts +7 -1
- package/esm/syntaxHighlightingInput/SyntaxHighlightingInput.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/SyntaxHighlightingInput.js +2 -1
- package/esm/syntaxHighlightingInput/hooks/useChangeHandler.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/hooks/useChangeHandler.js +9 -2
- package/esm/syntaxHighlightingInput/hooks/useCodemirror.d.ts +4 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirror.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirror.js +2 -2
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorChange.d.ts +12 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorChange.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorChange.js +10 -8
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorEditable.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorEditable.js +11 -4
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorKeymap.d.ts +1 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorKeymap.d.ts.map +1 -1
- package/esm/syntaxHighlightingInput/hooks/useCodemirrorKeymap.js +26 -22
- package/esm/syntaxHighlightingInput/syntaxErrorLinter.d.ts +24 -0
- package/esm/syntaxHighlightingInput/syntaxErrorLinter.d.ts.map +1 -0
- package/esm/syntaxHighlightingInput/syntaxErrorLinter.js +49 -0
- package/package.json +13 -11
- package/src/@ui/UiConfigEditor/UiConfigEditor.scss +169 -0
- package/src/@ui/UiMenu/UiMenu.scss +6 -0
- package/src/@ui/UiSubmenuHeader/UiSubmenuHeader.scss +15 -0
- package/src/@ui/index.scss +1 -0
- package/src/ParameterControl/ParameterControl.scss +10 -0
- package/styles/css/list.css +11 -0
- package/styles/css/list.css.map +1 -1
- package/styles/css/main.css +150 -1
- package/styles/css/main.css.map +1 -1
- package/styles/css/menu.css +11 -0
- package/styles/css/menu.css.map +1 -1
- package/styles/css/stylingEditorDialog.css +5 -0
- package/styles/css/stylingEditorDialog.css.map +1 -1
- package/styles/css/syntaxHighlightingInput.css +1 -1
- package/styles/css/syntaxHighlightingInput.css.map +1 -1
- package/styles/scss/list.scss +17 -0
- package/styles/scss/stylingEditorDialog.scss +8 -0
- package/styles/scss/syntaxHighlightingInput.scss +5 -2
- package/esm/syntaxHighlightingInput/YamlEditor.d.ts +0 -35
- package/esm/syntaxHighlightingInput/YamlEditor.d.ts.map +0 -1
- package/esm/syntaxHighlightingInput/YamlEditor.js +0 -32
- package/esm/syntaxHighlightingInput/yamlSyntaxLinter.d.ts +0 -12
- package/esm/syntaxHighlightingInput/yamlSyntaxLinter.d.ts.map +0 -1
- package/esm/syntaxHighlightingInput/yamlSyntaxLinter.js +0 -32
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type ConfigEditorLanguage } from "./configEditorLanguage.js";
|
|
3
|
+
import { type IUiConfigEditorContextMenuProps, type IUiConfigEditorLabels } from "./types.js";
|
|
4
|
+
interface IConfigEditorToolbarProps {
|
|
5
|
+
languages: ConfigEditorLanguage[];
|
|
6
|
+
displayLanguage: ConfigEditorLanguage;
|
|
7
|
+
/** Called when the user picks a language on this toolbar (as opposed to a remote prop change). */
|
|
8
|
+
onSelectLanguage: (next: ConfigEditorLanguage) => void;
|
|
9
|
+
labels: IUiConfigEditorLabels | undefined;
|
|
10
|
+
/** `undefined` when there is nothing to re-format, which disables the action. */
|
|
11
|
+
canAutoFormat: boolean;
|
|
12
|
+
onAutoFormat: () => void;
|
|
13
|
+
renderContextMenu?: (props: IUiConfigEditorContextMenuProps) => ReactNode;
|
|
14
|
+
readOnly: boolean;
|
|
15
|
+
disabled: boolean;
|
|
16
|
+
/** Scoped to the editor instance so several editors' radio groups do not merge. */
|
|
17
|
+
languageGroupName: string;
|
|
18
|
+
contextMenuButtonId: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The editor's fixed-height toolbar: the language radio group (only when more than one language is
|
|
22
|
+
* offered), the Auto-format action, and the optional context-menu button with its popover.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ConfigEditorToolbar({ languages, displayLanguage, onSelectLanguage, labels, canAutoFormat, onAutoFormat, renderContextMenu, readOnly, disabled, languageGroupName, contextMenuButtonId }: IConfigEditorToolbarProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=ConfigEditorToolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigEditorToolbar.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiConfigEditor/ConfigEditorToolbar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAQjD,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,KAAK,+BAA+B,EAAE,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAI9F,UAAU,yBAAyB;IAC/B,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,eAAe,EAAE,oBAAoB,CAAC;IACtC,kGAAkG;IAClG,gBAAgB,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACvD,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC1C,iFAAiF;IACjF,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,+BAA+B,KAAK,SAAS,CAAC;IAC1E,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,mFAAmF;IACnF,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAChC,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,MAAM,EACN,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,QAAQ,EACR,iBAAiB,EACjB,mBAAmB,EACtB,EAAE,yBAAyB,2CAmF3B"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { bem } from "../@utils/bem.js";
|
|
3
|
+
import { UiButton } from "../UiButton/UiButton.js";
|
|
4
|
+
import { UiDropdown } from "../UiDropdown/UiDropdown.js";
|
|
5
|
+
import { UiIconButton } from "../UiIconButton/UiIconButton.js";
|
|
6
|
+
import { UiRadio } from "../UiRadio/UiRadio.js";
|
|
7
|
+
const { e } = bem("gd-ui-kit-config-editor");
|
|
8
|
+
/**
|
|
9
|
+
* The editor's fixed-height toolbar: the language radio group (only when more than one language is
|
|
10
|
+
* offered), the Auto-format action, and the optional context-menu button with its popover.
|
|
11
|
+
*/
|
|
12
|
+
export function ConfigEditorToolbar({ languages, displayLanguage, onSelectLanguage, labels, canAutoFormat, onAutoFormat, renderContextMenu, readOnly, disabled, languageGroupName, contextMenuButtonId, }) {
|
|
13
|
+
const languageLabel = (language) => labels?.languages?.[language] ?? language.toUpperCase();
|
|
14
|
+
return (_jsxs("div", { className: e("toolbar"), children: [languages.length > 1 ? (_jsx("div", { className: e("languages"), role: "radiogroup", "aria-label": labels?.languageSwitcher ?? "Editor language", children: languages.map((radioLanguage) => (_jsx(UiRadio, {
|
|
15
|
+
// One `name` across all of them, so they behave as one native radio
|
|
16
|
+
// group: arrow keys move between them and only one can be chosen.
|
|
17
|
+
name: languageGroupName, value: radioLanguage, label: languageLabel(radioLanguage), checked: displayLanguage === radioLanguage, disabled: disabled, onChange: () => onSelectLanguage(radioLanguage), dataTestId: `s-config-editor-language-${radioLanguage}` }, radioLanguage))) })) : null, _jsxs("div", { className: e("actions", { withMenu: !!renderContextMenu }), children: [
|
|
18
|
+
_jsx(UiButton, { size: "medium", variant: "linkDimmed", label: labels?.autoFormat ?? "Auto-format",
|
|
19
|
+
// Nothing to re-format when the draft is blank or cannot be parsed, so the
|
|
20
|
+
// action is disabled rather than silently doing nothing.
|
|
21
|
+
isDisabled: disabled || readOnly || !canAutoFormat, onClick: onAutoFormat, dataTestId: "s-config-editor-auto-format" }), renderContextMenu ? (_jsx(UiDropdown, { placement: "bottom-end",
|
|
22
|
+
// The dropdown positions against the button, but the design hangs the
|
|
23
|
+
// menu from the toolbar's bottom edge: the 32px button centered in the
|
|
24
|
+
// 36px toolbar leaves 2px below it, plus the divider's 1px.
|
|
25
|
+
offset: 3, closeOnEscape: true, closeOnOutsideClick: true, autofocusOnOpen: true,
|
|
26
|
+
// The popup role is deliberately left at its default. Setting it to
|
|
27
|
+
// "menu" would put `role="menu"` on the positioning wrapper as well, and
|
|
28
|
+
// a menu nested directly inside another menu is invalid — the content is
|
|
29
|
+
// expected to be a `UiMenu`, which brings that role itself.
|
|
30
|
+
renderButton: ({ ref, toggleDropdown, isOpen, ariaAttributes }) => (_jsx(UiIconButton, { ref: ref, id: contextMenuButtonId, icon: "ellipsis", size: "medium", variant: "tertiary", isActive: isOpen, isDisabled: disabled, onClick: toggleDropdown, label: labels?.contextMenu ?? "More actions", accessibilityConfig: { ariaLabel: labels?.contextMenu ?? "More actions" }, ariaAttributes: ariaAttributes, dataTestId: "s-config-editor-context-menu-button" })), renderBody: ({ closeDropdown, ariaAttributes }) => renderContextMenu({
|
|
31
|
+
onClose: closeDropdown,
|
|
32
|
+
ariaAttributes: {
|
|
33
|
+
...ariaAttributes,
|
|
34
|
+
"aria-labelledby": contextMenuButtonId,
|
|
35
|
+
},
|
|
36
|
+
}) })) : null] })
|
|
37
|
+
] }));
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type IUiConfigEditorProps } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* A config editor: a CodeMirror source editor with syntax highlighting, line numbers and a lint
|
|
4
|
+
* gutter, plus a toolbar to re-format the text and — when more than one language is offered — to
|
|
5
|
+
* read and edit the same value as either JSON or YAML.
|
|
6
|
+
*
|
|
7
|
+
* The primary language is always the value in and the value out. Any other offered language is a
|
|
8
|
+
* convenience projection converted on the fly, so a caller never has to know which language the user
|
|
9
|
+
* happens to be looking at. A single-language editor never converts at all: what is typed is what is
|
|
10
|
+
* emitted, byte for byte, so YAML comments and formatting the caller cares about survive.
|
|
11
|
+
*
|
|
12
|
+
* Switching language re-emits the value in canonical form, which is what makes switching to YAML and
|
|
13
|
+
* back re-format the JSON. The canonical form matches the `JSON.stringify(value, null, 4)` that
|
|
14
|
+
* callers conventionally seed the field with, so a switch on an untouched value is a no-op rather
|
|
15
|
+
* than something that marks a form dirty.
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function UiConfigEditor({ value, onChange, primaryLanguage, languages, language, onLanguageChange, completionSource, labels, renderContextMenu, label, placeholder, readOnly, disabled, rows, dataTestId, editorRef }: IUiConfigEditorProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=UiConfigEditor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UiConfigEditor.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiConfigEditor/UiConfigEditor.tsx"],"names":[],"mappings":"AA4BA,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIvD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,eAAwB,EACxB,SAA4B,EAC5B,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,EACN,iBAAiB,EACjB,KAAK,EACL,WAAW,EACX,QAAgB,EAChB,QAAgB,EAChB,IAAS,EACT,UAAU,EACV,SAAS,EACZ,EAAE,oBAAoB,2CAwQtB"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// (C) 2026 GoodData Corporation
|
|
3
|
+
import { useCallback, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, } from "react";
|
|
4
|
+
import { forceLinting, lintGutter } from "@codemirror/lint";
|
|
5
|
+
import { Compartment } from "@codemirror/state";
|
|
6
|
+
import { lineNumbers } from "@codemirror/view";
|
|
7
|
+
import { createSyntaxErrorLinter } from "../../syntaxHighlightingInput/syntaxErrorLinter.js";
|
|
8
|
+
import { SyntaxHighlightingInput } from "../../syntaxHighlightingInput/SyntaxHighlightingInput.js";
|
|
9
|
+
import { yamlPositionAt } from "../../syntaxHighlightingInput/yamlPosition.js";
|
|
10
|
+
import { bem } from "../@utils/bem.js";
|
|
11
|
+
import { useLanguageGrammar } from "./configEditorGrammars.js";
|
|
12
|
+
import { themedHighlighting } from "./configEditorHighlighting.js";
|
|
13
|
+
import { beautify, convertText, isProjectable } from "./configEditorLanguage.js";
|
|
14
|
+
import { ConfigEditorToolbar } from "./ConfigEditorToolbar.js";
|
|
15
|
+
const { b, e } = bem("gd-ui-kit-config-editor");
|
|
16
|
+
/**
|
|
17
|
+
* A config editor: a CodeMirror source editor with syntax highlighting, line numbers and a lint
|
|
18
|
+
* gutter, plus a toolbar to re-format the text and — when more than one language is offered — to
|
|
19
|
+
* read and edit the same value as either JSON or YAML.
|
|
20
|
+
*
|
|
21
|
+
* The primary language is always the value in and the value out. Any other offered language is a
|
|
22
|
+
* convenience projection converted on the fly, so a caller never has to know which language the user
|
|
23
|
+
* happens to be looking at. A single-language editor never converts at all: what is typed is what is
|
|
24
|
+
* emitted, byte for byte, so YAML comments and formatting the caller cares about survive.
|
|
25
|
+
*
|
|
26
|
+
* Switching language re-emits the value in canonical form, which is what makes switching to YAML and
|
|
27
|
+
* back re-format the JSON. The canonical form matches the `JSON.stringify(value, null, 4)` that
|
|
28
|
+
* callers conventionally seed the field with, so a switch on an untouched value is a no-op rather
|
|
29
|
+
* than something that marks a form dirty.
|
|
30
|
+
*
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export function UiConfigEditor({ value, onChange, primaryLanguage = "json", languages = ["json", "yaml"], language, onLanguageChange, completionSource, labels, renderContextMenu, label, placeholder, readOnly = false, disabled = false, rows = 12, dataTestId, editorRef, }) {
|
|
34
|
+
// Scoped to this instance: several editors can sit on one page, and a shared radio `name` would
|
|
35
|
+
// make their language switchers fight over the same group.
|
|
36
|
+
const instanceId = useId();
|
|
37
|
+
const languageGroupName = `config-editor-language-${instanceId}`;
|
|
38
|
+
const contextMenuButtonId = `config-editor-menu-button-${instanceId}`;
|
|
39
|
+
// Only a JSON primary may display another language (see `languages` in types.ts), and only
|
|
40
|
+
// one the caller actually offers — a shared, persisted `language` must not trap a
|
|
41
|
+
// single-language editor in a projection it never presents a way out of. Anything else falls
|
|
42
|
+
// back to the primary rather than letting an unsound display in through the back door.
|
|
43
|
+
const displayLanguage = primaryLanguage === "json" &&
|
|
44
|
+
language !== undefined &&
|
|
45
|
+
languages.length > 1 &&
|
|
46
|
+
languages.includes(language)
|
|
47
|
+
? language
|
|
48
|
+
: primaryLanguage;
|
|
49
|
+
// The switcher needs the full controlled pair: without `language` a selection could never take
|
|
50
|
+
// effect, and the radios would appear to accept it and immediately snap back.
|
|
51
|
+
const isSwitchable = primaryLanguage === "json" && language !== undefined && !!onLanguageChange;
|
|
52
|
+
// The text actually on screen, in the displayed language. `value` stays primary regardless.
|
|
53
|
+
const [draft, setDraft] = useState(() => convertText(value, primaryLanguage, displayLanguage));
|
|
54
|
+
// Bumped to remount the editor when a language switch rewrites the document; a switch that
|
|
55
|
+
// leaves the text byte-identical (an unprojectable draft) keeps the editor instance, so the
|
|
56
|
+
// caret and undo history survive. The compartment swaps the grammar into the live view then.
|
|
57
|
+
const [editorEpoch, setEditorEpoch] = useState(0);
|
|
58
|
+
const draftRef = useRef(draft);
|
|
59
|
+
draftRef.current = draft;
|
|
60
|
+
// The primary-language text last handed to `onChange`, so a controlled parent echoing it back is
|
|
61
|
+
// not mistaken for an outside edit that should overwrite what the user is typing.
|
|
62
|
+
const lastEmittedRef = useRef(value);
|
|
63
|
+
const lastLanguageRef = useRef(displayLanguage);
|
|
64
|
+
// Set when the language change came from this editor's own switcher. The caller may share the
|
|
65
|
+
// language across several mounted editors, and only the one the user actually interacted with
|
|
66
|
+
// may rewrite its value in the new canonical form — the others only re-render their view.
|
|
67
|
+
const languageChangeIsLocalRef = useRef(false);
|
|
68
|
+
const viewRef = useRef(null);
|
|
69
|
+
const onChangeRef = useRef(onChange);
|
|
70
|
+
onChangeRef.current = onChange;
|
|
71
|
+
// Re-derive the draft when the language changes, or when `value` changes from the outside (an
|
|
72
|
+
// example applied, a dialog reset). useLayoutEffect so the new text is in place before paint.
|
|
73
|
+
useLayoutEffect(() => {
|
|
74
|
+
const languageChanged = lastLanguageRef.current !== displayLanguage;
|
|
75
|
+
if (!languageChanged && value === lastEmittedRef.current) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
lastLanguageRef.current = displayLanguage;
|
|
79
|
+
const isLocalLanguageChange = languageChanged && languageChangeIsLocalRef.current;
|
|
80
|
+
languageChangeIsLocalRef.current = false;
|
|
81
|
+
const nextDraft = convertText(value, primaryLanguage, displayLanguage);
|
|
82
|
+
lastEmittedRef.current = value;
|
|
83
|
+
if (languageChanged && (nextDraft !== draftRef.current || completionSource !== undefined)) {
|
|
84
|
+
// A rewritten document remounts the editor: undo has nothing coherent to return to.
|
|
85
|
+
// An identical document keeps the running editor (see `editorEpoch`) — unless a
|
|
86
|
+
// completion source is in play, whose wiring is mount-only and per-language, so
|
|
87
|
+
// keeping the instance would leave the old language's completion behavior active.
|
|
88
|
+
setEditorEpoch((epoch) => epoch + 1);
|
|
89
|
+
}
|
|
90
|
+
setDraft(nextDraft);
|
|
91
|
+
// Report the value in the new language's canonical form — projecting through YAML and back
|
|
92
|
+
// is what re-formats sloppy JSON. Done explicitly: the editor's own value sync is annotated
|
|
93
|
+
// `Transaction.remote`, which the change handler skips.
|
|
94
|
+
//
|
|
95
|
+
// Only for a switch made on this editor, though: a caller may share the language across
|
|
96
|
+
// several mounted editors, and the ones that did not participate in the interaction must
|
|
97
|
+
// not rewrite their values (and dirty their forms) as a side effect.
|
|
98
|
+
//
|
|
99
|
+
// Only when the value really parses: text the user is midway through breaking has no
|
|
100
|
+
// faithful projection, and re-reading it in the other language would change its meaning.
|
|
101
|
+
//
|
|
102
|
+
// And never while the value is not the user's to change: in those modes the toggle is only a
|
|
103
|
+
// way to read the value in another language, so it must not rewrite it.
|
|
104
|
+
if (!isLocalLanguageChange || !isProjectable(value, primaryLanguage) || readOnly || disabled) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const nextValue = convertText(nextDraft, displayLanguage, primaryLanguage);
|
|
108
|
+
if (nextValue !== value) {
|
|
109
|
+
lastEmittedRef.current = nextValue;
|
|
110
|
+
onChangeRef.current(nextValue);
|
|
111
|
+
}
|
|
112
|
+
}, [value, primaryLanguage, displayLanguage, readOnly, disabled, completionSource]);
|
|
113
|
+
const emit = useCallback((nextDraft) => {
|
|
114
|
+
const nextValue = convertText(nextDraft, displayLanguage, primaryLanguage);
|
|
115
|
+
lastEmittedRef.current = nextValue;
|
|
116
|
+
onChange(nextValue);
|
|
117
|
+
}, [displayLanguage, primaryLanguage, onChange]);
|
|
118
|
+
// Only real edits arrive here: the editor's change handler skips the remote-annotated value
|
|
119
|
+
// sync, so this component's own draft pushes never echo back as changes.
|
|
120
|
+
const handleDraftChange = useCallback((nextDraft) => {
|
|
121
|
+
setDraft(nextDraft);
|
|
122
|
+
emit(nextDraft);
|
|
123
|
+
}, [emit]);
|
|
124
|
+
const beautified = useMemo(() => beautify(draft, displayLanguage), [draft, displayLanguage]);
|
|
125
|
+
// Already-formatted text disables the action too: emitting an identical value would only make
|
|
126
|
+
// the caller believe something changed — an As-Code dialog would mark its form dirty.
|
|
127
|
+
const canAutoFormat = beautified !== undefined && beautified !== draft;
|
|
128
|
+
const handleBeautify = useCallback(() => {
|
|
129
|
+
if (beautified === undefined || beautified === draft) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
setDraft(beautified);
|
|
133
|
+
emit(beautified);
|
|
134
|
+
}, [beautified, draft, emit]);
|
|
135
|
+
const handleSelectLanguage = useCallback((next) => {
|
|
136
|
+
// Marks the coming language-prop change as this editor's own interaction, so the
|
|
137
|
+
// canonical re-emit runs here and not in other editors sharing the language.
|
|
138
|
+
languageChangeIsLocalRef.current = true;
|
|
139
|
+
onLanguageChange?.(next);
|
|
140
|
+
}, [onLanguageChange]);
|
|
141
|
+
// The handle is rebuilt when editability changes rather than reading a ref written during
|
|
142
|
+
// render: an abandoned render must not be able to leave a speculative value behind. Callers
|
|
143
|
+
// read `ref.current` at call time, so a new handle identity costs them nothing.
|
|
144
|
+
useImperativeHandle(editorRef, () => ({
|
|
145
|
+
insertAtCursor: (text) => {
|
|
146
|
+
const view = viewRef.current;
|
|
147
|
+
// CodeMirror's non-editable state only blocks user input, not programmatic
|
|
148
|
+
// dispatches, so a read-only or in-flight editor has to be refused here.
|
|
149
|
+
if (!view || readOnly || disabled) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const { from, to } = view.state.selection.main;
|
|
153
|
+
// CodeMirror places the caret and keeps the insertion in view itself; the resulting
|
|
154
|
+
// document change flows back out through the editor's own change handler.
|
|
155
|
+
view.dispatch({
|
|
156
|
+
changes: { from, to, insert: text },
|
|
157
|
+
selection: { anchor: from + text.length },
|
|
158
|
+
scrollIntoView: true,
|
|
159
|
+
});
|
|
160
|
+
view.focus();
|
|
161
|
+
},
|
|
162
|
+
focus: () => viewRef.current?.focus(),
|
|
163
|
+
}), [readOnly, disabled]);
|
|
164
|
+
// Completion availability is fixed when the editor mounts: the wrapper is installed only if
|
|
165
|
+
// a source is present then, and it dereferences the live ref, so removing the source later
|
|
166
|
+
// would make an invoked completion throw while adding one would do nothing.
|
|
167
|
+
const hasCompletionRef = useRef(completionSource !== undefined);
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
const hasCompletion = completionSource !== undefined;
|
|
170
|
+
if (hasCompletionRef.current !== hasCompletion) {
|
|
171
|
+
hasCompletionRef.current = hasCompletion;
|
|
172
|
+
setEditorEpoch((epoch) => epoch + 1);
|
|
173
|
+
}
|
|
174
|
+
}, [completionSource]);
|
|
175
|
+
const grammar = useLanguageGrammar(displayLanguage);
|
|
176
|
+
// The grammar lives in a compartment so a first-time load can be injected into the running
|
|
177
|
+
// view: remounting instead would throw away whatever the user did while the chunk was on the
|
|
178
|
+
// wire — selection, undo history, focus — and their next keystroke would land at offset 0.
|
|
179
|
+
const grammarCompartmentRef = useRef(new Compartment());
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
const view = viewRef.current;
|
|
182
|
+
if (view) {
|
|
183
|
+
// `grammar ?? []` and not a skip: switching to a language whose grammar is still
|
|
184
|
+
// loading must clear the previous one, or the document keeps being parsed, highlighted
|
|
185
|
+
// and linted as the old language until the chunk arrives — indefinitely, if it fails.
|
|
186
|
+
view.dispatch({
|
|
187
|
+
effects: grammarCompartmentRef.current.reconfigure(grammar ?? []),
|
|
188
|
+
});
|
|
189
|
+
// The reconfigure changes neither the document nor the lint configuration, so the
|
|
190
|
+
// linter would not run again on its own — stale diagnostics from the previous grammar
|
|
191
|
+
// (or from the grammar-less tree) would stay in the gutter.
|
|
192
|
+
forceLinting(view);
|
|
193
|
+
}
|
|
194
|
+
}, [grammar]);
|
|
195
|
+
// Extensions are read once when CodeMirror initialises, so the editor is remounted (keyed on
|
|
196
|
+
// language) to swap grammars. Losing the undo history is reasonable there: the document was
|
|
197
|
+
// just rewritten in a different language, so there is nothing coherent left to undo into.
|
|
198
|
+
const syntaxErrorMessage = labels?.syntaxError;
|
|
199
|
+
const extensions = useMemo(() => [
|
|
200
|
+
grammarCompartmentRef.current.of(grammar ?? []),
|
|
201
|
+
themedHighlighting,
|
|
202
|
+
lineNumbers(),
|
|
203
|
+
lintGutter(),
|
|
204
|
+
...(syntaxErrorMessage ? [createSyntaxErrorLinter(syntaxErrorMessage)] : []),
|
|
205
|
+
],
|
|
206
|
+
// Keyed on `grammar` (which changes with the language) rather than the language itself: a
|
|
207
|
+
// running view gets a late-arriving grammar through the effect above, but any later remount
|
|
208
|
+
// (a completion-source toggle, say) is built from this memo — stale, it would mount an
|
|
209
|
+
// editor with no grammar at all.
|
|
210
|
+
[grammar, syntaxErrorMessage]);
|
|
211
|
+
// The completion source speaks in terms of the document's shape — the mapping keys enclosing the
|
|
212
|
+
// position — so the raw CodeMirror context is resolved into that here. YAML only: the position
|
|
213
|
+
// reader walks a YAML parse tree, and no JSON consumer has a completion schema.
|
|
214
|
+
const onCompletion = useMemo(() => completionSource && displayLanguage === "yaml"
|
|
215
|
+
? (context) => completionSource(context, yamlPositionAt(context.state, context.pos))
|
|
216
|
+
: undefined, [completionSource, displayLanguage]);
|
|
217
|
+
return (_jsxs("div", { className: b({ disabled, readOnly }), style: { "--config-editor-rows": rows }, "data-testid": dataTestId, children: [
|
|
218
|
+
_jsx(ConfigEditorToolbar, { languages: isSwitchable ? languages : [], displayLanguage: displayLanguage, onSelectLanguage: handleSelectLanguage, labels: labels, canAutoFormat: canAutoFormat, onAutoFormat: handleBeautify, renderContextMenu: renderContextMenu, readOnly: readOnly, disabled: disabled, languageGroupName: languageGroupName, contextMenuButtonId: contextMenuButtonId }), _jsx("div", { className: e("editor"), children: _jsx(SyntaxHighlightingInput, { value: draft, onChange: handleDraftChange,
|
|
219
|
+
// An external replace means a new document here (an applied example, a dialog
|
|
220
|
+
// reset), so the cursor goes to its end — a stale clamped offset would drop the
|
|
221
|
+
// next inserted variable at the very start of the fresh text.
|
|
222
|
+
externalChangeSelection: "end", onCompletion: onCompletion, label: label ?? "Code editor", placeholder: placeholder,
|
|
223
|
+
// CodeMirror's non-editable state keeps the content focusable and selectable,
|
|
224
|
+
// which is what both the read-only view and an in-flight save want.
|
|
225
|
+
disabled: readOnly || disabled, extensions: extensions, onApi: (view) => {
|
|
226
|
+
viewRef.current = view;
|
|
227
|
+
} }, editorEpoch) })
|
|
228
|
+
] }));
|
|
229
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Extension } from "@codemirror/state";
|
|
2
|
+
import { type ConfigEditorLanguage } from "./configEditorLanguage.js";
|
|
3
|
+
/**
|
|
4
|
+
* Loads the grammar(s) `UiConfigEditor` needs for the given languages ahead of rendering one.
|
|
5
|
+
*
|
|
6
|
+
* Purely an optimization: the editor loads its grammar itself when it first renders, mounting
|
|
7
|
+
* without highlighting for the moment that takes. Callers that know an editor is coming (and
|
|
8
|
+
* tests that assert on a fully initialized editor synchronously) can await this instead.
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export declare function preloadUiConfigEditorGrammars(languages?: ConfigEditorLanguage[]): Promise<void>;
|
|
13
|
+
/** The grammar for `language`, loading it on first use; `undefined` until it has arrived. */
|
|
14
|
+
export declare function useLanguageGrammar(language: ConfigEditorLanguage): Extension | undefined;
|
|
15
|
+
//# sourceMappingURL=configEditorGrammars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configEditorGrammars.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiConfigEditor/configEditorGrammars.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AActE;;;;;;;;GAQG;AACH,wBAAsB,6BAA6B,CAC/C,SAAS,GAAE,oBAAoB,EAAqB,GACrD,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,GAAG,SAAS,CAwBxF"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The grammars are loaded on demand and cached for the page's lifetime: importing them statically
|
|
5
|
+
* would make every consumer carry both, and a single-language editor — the catalog's YAML-only
|
|
6
|
+
* as-code dialogs, say — would ship a JSON grammar it can never display.
|
|
7
|
+
*/
|
|
8
|
+
const grammarLoaders = {
|
|
9
|
+
json: async () => (await import("@codemirror/lang-json")).json(),
|
|
10
|
+
yaml: async () => (await import("@codemirror/lang-yaml")).yaml(),
|
|
11
|
+
};
|
|
12
|
+
const grammarCache = new Map();
|
|
13
|
+
/**
|
|
14
|
+
* Loads the grammar(s) `UiConfigEditor` needs for the given languages ahead of rendering one.
|
|
15
|
+
*
|
|
16
|
+
* Purely an optimization: the editor loads its grammar itself when it first renders, mounting
|
|
17
|
+
* without highlighting for the moment that takes. Callers that know an editor is coming (and
|
|
18
|
+
* tests that assert on a fully initialized editor synchronously) can await this instead.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export async function preloadUiConfigEditorGrammars(languages = ["json", "yaml"]) {
|
|
23
|
+
await Promise.all(languages.map(async (language) => {
|
|
24
|
+
grammarCache.set(language, await grammarLoaders[language]());
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
/** The grammar for `language`, loading it on first use; `undefined` until it has arrived. */
|
|
28
|
+
export function useLanguageGrammar(language) {
|
|
29
|
+
const [, setLoadedCount] = useState(0);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (grammarCache.has(language)) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
let disposed = false;
|
|
35
|
+
void grammarLoaders[language]()
|
|
36
|
+
.then((grammar) => {
|
|
37
|
+
grammarCache.set(language, grammar);
|
|
38
|
+
if (!disposed) {
|
|
39
|
+
setLoadedCount((count) => count + 1);
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
// A failed chunk load leaves the editor plain but working; nothing is cached, so the
|
|
43
|
+
// next request for this language retries the import.
|
|
44
|
+
.catch(() => { });
|
|
45
|
+
return () => {
|
|
46
|
+
disposed = true;
|
|
47
|
+
};
|
|
48
|
+
}, [language]);
|
|
49
|
+
return grammarCache.get(language);
|
|
50
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Prec.highest` so this wins over the shared highlight style that `useCodemirror` installs: with
|
|
3
|
+
* equal precedence the earlier extension takes effect, and that one is added first.
|
|
4
|
+
*/
|
|
5
|
+
export declare const themedHighlighting: import("@codemirror/state").Extension;
|
|
6
|
+
//# sourceMappingURL=configEditorHighlighting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configEditorHighlighting.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiConfigEditor/configEditorHighlighting.ts"],"names":[],"mappings":"AA6BA;;;GAGG;AACH,eAAO,MAAM,kBAAkB,uCAAyD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
3
|
+
import { Prec } from "@codemirror/state";
|
|
4
|
+
import { tags as t } from "@lezer/highlight";
|
|
5
|
+
/**
|
|
6
|
+
* Token colors expressed as theme variables, so the editor stays legible on a dark theme.
|
|
7
|
+
*
|
|
8
|
+
* The shared highlight style in `useCodemirror` hardcodes light-theme hex colors, which leaves dark
|
|
9
|
+
* strings on a dark background once a theme flips the surface (the editor's background is itself
|
|
10
|
+
* theme-driven). Only the complementary scale and the semantic palette are safe to lean on here:
|
|
11
|
+
* both invert with the theme, so foreground stays foreground.
|
|
12
|
+
*/
|
|
13
|
+
const themedHighlightStyle = HighlightStyle.define([
|
|
14
|
+
// Keys read as the primary content of a config file, so they take the foreground colour.
|
|
15
|
+
{
|
|
16
|
+
tag: [t.propertyName, t.definition(t.propertyName), t.variableName],
|
|
17
|
+
color: "var(--gd-palette-complementary-8)",
|
|
18
|
+
},
|
|
19
|
+
{ tag: [t.string, t.special(t.string)], color: "var(--gd-palette-primary-base)" },
|
|
20
|
+
{
|
|
21
|
+
tag: [t.number, t.bool, t.null, t.atom, t.keyword],
|
|
22
|
+
color: "var(--gd-palette-warning-base)",
|
|
23
|
+
},
|
|
24
|
+
{ tag: [t.punctuation, t.separator, t.bracket, t.meta], color: "var(--gd-palette-complementary-6)" },
|
|
25
|
+
{ tag: t.comment, color: "var(--gd-palette-complementary-6)", fontStyle: "italic" },
|
|
26
|
+
]);
|
|
27
|
+
/**
|
|
28
|
+
* `Prec.highest` so this wins over the shared highlight style that `useCodemirror` installs: with
|
|
29
|
+
* equal precedence the earlier extension takes effect, and that one is added first.
|
|
30
|
+
*/
|
|
31
|
+
export const themedHighlighting = Prec.highest(syntaxHighlighting(themedHighlightStyle));
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A language the config editor can display and emit. Every editor instance has a primary language —
|
|
3
|
+
* the one its value is written in — and may offer the other as an on-the-fly projection of it.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export type ConfigEditorLanguage = "json" | "yaml";
|
|
8
|
+
/**
|
|
9
|
+
* Whether `text` is a value in `language` that can be projected into another language and back.
|
|
10
|
+
*
|
|
11
|
+
* Text the user is midway through breaking is not: re-reading it in another language could give it a
|
|
12
|
+
* different meaning (`foo` is broken JSON but a valid YAML string), so switching language must leave
|
|
13
|
+
* it alone rather than quietly turning it into something that parses. Neither is a comment-only YAML
|
|
14
|
+
* document, whose projection would be empty — losing the comments.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
export declare function isProjectable(text: string, language: ConfigEditorLanguage): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Converts text from one of the editor's languages into another.
|
|
21
|
+
*
|
|
22
|
+
* Unconvertible text is passed through verbatim rather than swallowed — unparseable text, and a
|
|
23
|
+
* comment-only YAML document, whose projection would be empty. In the display direction that keeps
|
|
24
|
+
* a language switch from silently discarding what is on screen; in the primary direction it hands
|
|
25
|
+
* the caller the raw text, whose own validation is what reports the problem while the user is
|
|
26
|
+
* mid-edit.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare function convertText(text: string, fromLanguage: ConfigEditorLanguage, toLanguage: ConfigEditorLanguage): string;
|
|
31
|
+
/**
|
|
32
|
+
* Re-formats the displayed text in its own language.
|
|
33
|
+
*
|
|
34
|
+
* YAML is re-formatted structurally — indentation and spacing are normalized while comments, blank
|
|
35
|
+
* lines and scalar styles are kept — so a hand-annotated document is tidied, never stripped.
|
|
36
|
+
*
|
|
37
|
+
* Returns `undefined` when there is nothing to format — blank or unparseable input — so the caller
|
|
38
|
+
* can disable the action instead of offering a no-op.
|
|
39
|
+
*
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export declare function beautify(draft: string, language: ConfigEditorLanguage): string | undefined;
|
|
43
|
+
//# sourceMappingURL=configEditorLanguage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configEditorLanguage.d.ts","sourceRoot":"","sources":["../../../src/@ui/UiConfigEditor/configEditorLanguage.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,CAAC;AAmHnD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CASnF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CACvB,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,oBAAoB,EAClC,UAAU,EAAE,oBAAoB,GACjC,MAAM,CAWR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAgB1F"}
|