@gooddata/sdk-ui-catalog 11.47.0-alpha.3 → 11.47.0-alpha.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"MetricYamlEditor.d.ts","sourceRoot":"","sources":["../../src/metric/MetricYamlEditor.tsx"],"names":[],"mappings":"AAcA,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,KAAK,2CA2BnF"}
1
+ {"version":3,"file":"MetricYamlEditor.d.ts","sourceRoot":"","sources":["../../src/metric/MetricYamlEditor.tsx"],"names":[],"mappings":"AAYA,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,KAAK,2CAWnF"}
@@ -1,20 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
- import { useCallback, useMemo, useState } from "react";
4
- import { yaml } from "@codemirror/lang-yaml";
5
- import { lintGutter } from "@codemirror/lint";
6
- import { lineNumbers } from "@codemirror/view";
7
- import { useIntl } from "react-intl";
8
- import { SyntaxHighlightingInput } from "@gooddata/sdk-ui-kit";
9
- import { metricSchemaCompletions } from "./metricCompletions.js";
10
- import { createMetricYamlLinter } from "./metricYamlLinter.js";
3
+ import { defineMessages, useIntl } from "react-intl";
4
+ import { YamlEditor } from "@gooddata/sdk-ui-kit";
5
+ import { metricCompletions } from "./metricCompletions.js";
6
+ const messages = defineMessages({
7
+ syntaxError: { id: "analyticsCatalog.metric.validation.syntax" },
8
+ });
11
9
  export function MetricYamlEditor({ initialValue, onChange, disabled = false }) {
12
10
  const intl = useIntl();
13
- const [value, setValue] = useState(initialValue);
14
- const extensions = useMemo(() => [yaml(), lineNumbers(), createMetricYamlLinter(intl), lintGutter()], [intl]);
15
- const handleChange = useCallback((nextValue) => {
16
- setValue(nextValue);
17
- onChange?.(nextValue);
18
- }, [onChange]);
19
- return (_jsx(SyntaxHighlightingInput, { className: "gd-ascode-dialog-editor-input", value: value, onChange: handleChange, extensions: extensions, onCompletion: metricSchemaCompletions, disabled: disabled }));
11
+ return (_jsx(YamlEditor, { initialValue: initialValue, onChange: onChange, disabled: disabled, completionSource: metricCompletions, syntaxErrorMessage: intl.formatMessage(messages.syntaxError) }));
20
12
  }
@@ -1,7 +1,8 @@
1
1
  import type { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
2
2
  /**
3
- * CodeMirror completion source that suggests allowed YAML property names
4
- * based on the metric zod schema and cursor position in the Lezer tree.
3
+ * Completion source for the metric YAML schema. The metric schema is a flat mapping, so completion
4
+ * only offers the top-level property names, and only at column zero an indented line sits inside a
5
+ * sequence value (e.g. under `tags:`), where those keys must not be offered.
5
6
  */
6
- export declare function metricSchemaCompletions(context: CompletionContext): CompletionResult | null;
7
+ export declare function metricCompletions(context: CompletionContext): CompletionResult | null;
7
8
  //# sourceMappingURL=metricCompletions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"metricCompletions.d.ts","sourceRoot":"","sources":["../../src/metric/metricCompletions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAcpF;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,IAAI,CA2B3F"}
1
+ {"version":3,"file":"metricCompletions.d.ts","sourceRoot":"","sources":["../../src/metric/metricCompletions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAMpF;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,IAAI,CAWrF"}
@@ -1,59 +1,18 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { syntaxTree } from "@codemirror/language";
3
2
  import { METRIC_SCHEMA_KEYS } from "./metricSchema.js";
4
- /** Pre-built completion options from the schema key map. */
5
- const completionOptions = Object.fromEntries(Object.entries(METRIC_SCHEMA_KEYS).map(([parent, keys]) => [
6
- parent,
7
- keys.map((label) => ({ label, type: "property" })),
8
- ]));
3
+ const rootOptions = (METRIC_SCHEMA_KEYS[""] ?? []).map((label) => ({ label, type: "property" }));
9
4
  /**
10
- * CodeMirror completion source that suggests allowed YAML property names
11
- * based on the metric zod schema and cursor position in the Lezer tree.
5
+ * Completion source for the metric YAML schema. The metric schema is a flat mapping, so completion
6
+ * only offers the top-level property names, and only at column zero an indented line sits inside a
7
+ * sequence value (e.g. under `tags:`), where those keys must not be offered.
12
8
  */
13
- export function metricSchemaCompletions(context) {
9
+ export function metricCompletions(context) {
14
10
  const line = context.state.doc.lineAt(context.pos);
15
11
  const before = line.text.slice(0, context.pos - line.from);
16
- // Only trigger when typing a key name at the start of a line
17
- const match = before.match(/^(\s*)(\w*)$/);
12
+ // Trigger only for a key typed at column zero; any leading whitespace means the cursor is nested.
13
+ const match = before.match(/^([\w-]*)$/);
18
14
  if (!match) {
19
15
  return null;
20
16
  }
21
- // The metric schema is flat: property keys exist only at the top-level mapping, at zero
22
- // indentation. An indented cursor is inside a value such as the `tags` sequence, where the
23
- // top-level key suggestions must not be offered.
24
- if (match[1].length > 0) {
25
- return null;
26
- }
27
- const word = match[2];
28
- const from = context.pos - word.length;
29
- const parentKey = getParentKey(context.state, context.pos);
30
- const options = completionOptions[parentKey];
31
- if (!options) {
32
- return null;
33
- }
34
- return { from, options };
35
- }
36
- /**
37
- * Walk up the Lezer YAML tree from cursor to find which key's BlockMapping
38
- * we're inside. Returns "" for the top-level mapping.
39
- */
40
- function getParentKey(state, pos) {
41
- const tree = syntaxTree(state);
42
- let node = tree.resolveInner(pos, -1).parent;
43
- // Find the BlockMapping we're inside
44
- while (node) {
45
- if (node.name === "BlockMapping") {
46
- // If this BlockMapping is the value of a Pair, return the Pair's key
47
- const pair = node.parent;
48
- if (pair?.name === "Pair") {
49
- const keyNode = pair.getChild("Key");
50
- if (keyNode) {
51
- return state.sliceDoc(keyNode.from, keyNode.to).trim();
52
- }
53
- }
54
- return "";
55
- }
56
- node = node.parent;
57
- }
58
- return "";
17
+ return { from: context.pos - match[1].length, options: rootOptions, validFor: /^[\w-]*$/ };
59
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ParameterYamlEditor.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterYamlEditor.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAMzD,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,KAAK,2CAyBpG"}
1
+ {"version":3,"file":"ParameterYamlEditor.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterYamlEditor.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AASzD,KAAK,KAAK,GAAG;IACT,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,QAAgB,EAAE,EAAE,KAAK,2CAepG"}
@@ -1,21 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // (C) 2026 GoodData Corporation
3
- import { useCallback, useMemo, useState } from "react";
4
- import { yaml } from "@codemirror/lang-yaml";
5
- import { lintGutter } from "@codemirror/lint";
6
- import { lineNumbers } from "@codemirror/view";
7
- import { useIntl } from "react-intl";
8
- import { SyntaxHighlightingInput } from "@gooddata/sdk-ui-kit";
3
+ import { useMemo } from "react";
4
+ import { defineMessages, useIntl } from "react-intl";
5
+ import { YamlEditor } from "@gooddata/sdk-ui-kit";
9
6
  import { createParameterCompletions } from "./parameterCompletions.js";
10
- import { createYamlLinter } from "./yamlLinter.js";
7
+ const messages = defineMessages({
8
+ syntaxError: { id: "analyticsCatalog.parameter.validation.syntax" },
9
+ });
11
10
  export function ParameterYamlEditor({ initialValue, enabledTypes, onChange, disabled = false }) {
12
11
  const intl = useIntl();
13
- const [value, setValue] = useState(initialValue);
14
- const extensions = useMemo(() => [yaml(), lineNumbers(), createYamlLinter(intl), lintGutter()], [intl]);
15
- const completions = useMemo(() => createParameterCompletions(enabledTypes), [enabledTypes]);
16
- const handleChange = useCallback((nextValue) => {
17
- setValue(nextValue);
18
- onChange?.(nextValue);
19
- }, [onChange]);
20
- return (_jsx(SyntaxHighlightingInput, { className: "gd-ascode-dialog-editor-input", value: value, onChange: handleChange, extensions: extensions, onCompletion: completions, disabled: disabled }));
12
+ // The completion source narrows keys and `type:` values to the enabled parameter types, so it is
13
+ // rebuilt whenever that set changes.
14
+ const completionSource = useMemo(() => createParameterCompletions(enabledTypes), [enabledTypes]);
15
+ return (_jsx(YamlEditor, { initialValue: initialValue, onChange: onChange, disabled: disabled, completionSource: completionSource, syntaxErrorMessage: intl.formatMessage(messages.syntaxError) }));
21
16
  }
@@ -48,9 +48,12 @@ function toOptions(keyMap) {
48
48
  ]));
49
49
  }
50
50
  /**
51
- * The key whose block mapping a new entry at column `indent` would join: the
52
- * nearest less-indented `key:` line above. Returns "" for the top-level
53
- * mapping and null when the enclosing line is not a mapping key.
51
+ * The key whose block mapping a new entry at column `indent` would join: the nearest less-indented
52
+ * `key:` line above. Returns `""` only for the top-level mapping (`indent === 0`), and `null` when the
53
+ * enclosing line is not a mapping key or an indented line has no less-indented ancestor above it (an
54
+ * orphaned line, which is not top-level). Derived purely from indentation, not from a parsed syntax
55
+ * tree, so it also resolves the parent on a blank indented line; the flip side is that it does not
56
+ * understand block scalars (`|`, `>`), whose literal content is scanned as if it were mapping keys.
54
57
  */
55
58
  function getParentKey(doc, lineNumber, indent) {
56
59
  if (indent === 0) {
@@ -59,19 +62,25 @@ function getParentKey(doc, lineNumber, indent) {
59
62
  for (let number = lineNumber - 1; number >= 1; number--) {
60
63
  const text = doc.line(number).text;
61
64
  const content = text.trimStart();
65
+ // Skip blank lines, comments, and lines indented at least as deep as the new entry.
62
66
  if (content === "" || content.startsWith("#") || text.length - content.length >= indent) {
63
67
  continue;
64
68
  }
65
69
  return content.match(/^([\w-]+):/)?.[1] ?? null;
66
70
  }
67
- return "";
71
+ // Indented with no less-indented ancestor: an orphaned line, not top-level.
72
+ return null;
68
73
  }
69
- /** Value of the first indented `type:` key, i.e. `definition.type` (the top-level `type` is unindented). */
74
+ /**
75
+ * Value of `definition.type`: the first indented `type:` line whose enclosing mapping is `definition`.
76
+ * Resolving the parent via {@link getParentKey} keeps a `type:` nested elsewhere — under `constraints`
77
+ * or inside a block-scalar `description` — from being mistaken for the declared parameter type.
78
+ */
70
79
  function getDeclaredType(doc) {
71
80
  for (let number = 1; number <= doc.lines; number++) {
72
- const match = doc.line(number).text.match(/^\s+type:\s*(\w+)/);
73
- if (match) {
74
- return match[1];
81
+ const match = doc.line(number).text.match(/^(\s+)type:\s*(\w+)/);
82
+ if (match && getParentKey(doc, number, match[1].length) === "definition") {
83
+ return match[2];
75
84
  }
76
85
  }
77
86
  return undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-catalog",
3
- "version": "11.47.0-alpha.3",
3
+ "version": "11.47.0-alpha.4",
4
4
  "description": "GoodData SDK - Analytics Catalog",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -32,11 +32,7 @@
32
32
  "dependencies": {
33
33
  "@babel/core": "7.28.4",
34
34
  "@codemirror/autocomplete": "6.20.0",
35
- "@codemirror/lang-yaml": "6.1.3",
36
- "@codemirror/language": "6.12.1",
37
- "@codemirror/lint": "6.9.2",
38
35
  "@codemirror/state": "6.5.3",
39
- "@codemirror/view": "6.39.10",
40
36
  "@joint/core": "^4.2.4",
41
37
  "@joint/layout-directed-graph": "^4.2.3",
42
38
  "classnames": "2.5.1",
@@ -45,15 +41,15 @@
45
41
  "tslib": "2.8.1",
46
42
  "yaml": "2.8.3",
47
43
  "zod": "4.3.6",
48
- "@gooddata/sdk-backend-spi": "11.47.0-alpha.3",
49
- "@gooddata/sdk-ui": "11.47.0-alpha.3",
50
- "@gooddata/sdk-ui-ext": "11.47.0-alpha.3",
51
- "@gooddata/sdk-model": "11.47.0-alpha.3",
52
- "@gooddata/sdk-code-schemas": "11.47.0-alpha.3",
53
- "@gooddata/sdk-ui-kit": "11.47.0-alpha.3",
54
- "@gooddata/sdk-ui-semantic-search": "11.47.0-alpha.3",
55
- "@gooddata/sdk-ui-theme-provider": "11.47.0-alpha.3",
56
- "@gooddata/util": "11.47.0-alpha.3"
44
+ "@gooddata/sdk-backend-spi": "11.47.0-alpha.4",
45
+ "@gooddata/sdk-code-schemas": "11.47.0-alpha.4",
46
+ "@gooddata/sdk-ui": "11.47.0-alpha.4",
47
+ "@gooddata/sdk-model": "11.47.0-alpha.4",
48
+ "@gooddata/sdk-ui-ext": "11.47.0-alpha.4",
49
+ "@gooddata/sdk-ui-kit": "11.47.0-alpha.4",
50
+ "@gooddata/sdk-ui-semantic-search": "11.47.0-alpha.4",
51
+ "@gooddata/sdk-ui-theme-provider": "11.47.0-alpha.4",
52
+ "@gooddata/util": "11.47.0-alpha.4"
57
53
  },
58
54
  "devDependencies": {
59
55
  "@microsoft/api-documenter": "^7.17.0",
@@ -93,11 +89,11 @@
93
89
  "typescript": "5.9.3",
94
90
  "vitest": "4.1.8",
95
91
  "vitest-dom": "0.1.1",
96
- "@gooddata/eslint-config": "11.47.0-alpha.3",
97
- "@gooddata/i18n-toolkit": "11.47.0-alpha.3",
98
- "@gooddata/oxlint-config": "11.47.0-alpha.3",
99
- "@gooddata/sdk-backend-mockingbird": "11.47.0-alpha.3",
100
- "@gooddata/stylelint-config": "11.47.0-alpha.3"
92
+ "@gooddata/eslint-config": "11.47.0-alpha.4",
93
+ "@gooddata/i18n-toolkit": "11.47.0-alpha.4",
94
+ "@gooddata/oxlint-config": "11.47.0-alpha.4",
95
+ "@gooddata/sdk-backend-mockingbird": "11.47.0-alpha.4",
96
+ "@gooddata/stylelint-config": "11.47.0-alpha.4"
101
97
  },
102
98
  "peerDependencies": {
103
99
  "react": "^18.0.0 || ^19.0.0",
@@ -1,7 +0,0 @@
1
- import { type IntlShape } from "react-intl";
2
- /**
3
- * Creates a CodeMirror linter extension that reports YAML syntax errors
4
- * using the metric-specific syntax error message.
5
- */
6
- export declare function createMetricYamlLinter(intl: IntlShape): import("@codemirror/state").Extension;
7
- //# sourceMappingURL=metricYamlLinter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metricYamlLinter.d.ts","sourceRoot":"","sources":["../../src/metric/metricYamlLinter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,YAAY,CAAC;AAQ5D;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS,yCAErD"}
@@ -1,13 +0,0 @@
1
- // (C) 2026 GoodData Corporation
2
- import { defineMessages } from "react-intl";
3
- import { createYamlSyntaxLinter } from "../utils/yamlSyntaxLinter.js";
4
- const messages = defineMessages({
5
- syntaxError: { id: "analyticsCatalog.metric.validation.syntax" },
6
- });
7
- /**
8
- * Creates a CodeMirror linter extension that reports YAML syntax errors
9
- * using the metric-specific syntax error message.
10
- */
11
- export function createMetricYamlLinter(intl) {
12
- return createYamlSyntaxLinter(intl.formatMessage(messages.syntaxError));
13
- }
@@ -1,7 +0,0 @@
1
- import { type IntlShape } from "react-intl";
2
- /**
3
- * Creates a CodeMirror linter extension that reports YAML syntax errors
4
- * using the parameter-specific syntax error message.
5
- */
6
- export declare function createYamlLinter(intl: IntlShape): import("@codemirror/state").Extension;
7
- //# sourceMappingURL=yamlLinter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yamlLinter.d.ts","sourceRoot":"","sources":["../../src/parameter/yamlLinter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,YAAY,CAAC;AAQ5D;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,yCAE/C"}
@@ -1,13 +0,0 @@
1
- // (C) 2026 GoodData Corporation
2
- import { defineMessages } from "react-intl";
3
- import { createYamlSyntaxLinter } from "../utils/yamlSyntaxLinter.js";
4
- const messages = defineMessages({
5
- syntaxError: { id: "analyticsCatalog.parameter.validation.syntax" },
6
- });
7
- /**
8
- * Creates a CodeMirror linter extension that reports YAML syntax errors
9
- * using the parameter-specific syntax error message.
10
- */
11
- export function createYamlLinter(intl) {
12
- return createYamlSyntaxLinter(intl.formatMessage(messages.syntaxError));
13
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Creates a CodeMirror linter extension that reports YAML syntax errors
3
- * by walking the parse tree for error nodes.
4
- *
5
- * This reuses the tree already built by `@codemirror/lang-yaml` for
6
- * highlighting — no extra parsing or dependencies required.
7
- *
8
- * @param message - localized message shown on each syntax error diagnostic
9
- */
10
- export declare function createYamlSyntaxLinter(message: string): import("@codemirror/state").Extension;
11
- //# sourceMappingURL=yamlSyntaxLinter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"yamlSyntaxLinter.d.ts","sourceRoot":"","sources":["../../src/utils/yamlSyntaxLinter.ts"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,yCAoBrD"}
@@ -1,31 +0,0 @@
1
- // (C) 2026 GoodData Corporation
2
- import { syntaxTree } from "@codemirror/language";
3
- import { linter } from "@codemirror/lint";
4
- /**
5
- * Creates a CodeMirror linter extension that reports YAML syntax errors
6
- * by walking the parse tree for error nodes.
7
- *
8
- * This reuses the tree already built by `@codemirror/lang-yaml` for
9
- * highlighting — no extra parsing or dependencies required.
10
- *
11
- * @param message - localized message shown on each syntax error diagnostic
12
- */
13
- export function createYamlSyntaxLinter(message) {
14
- return linter((view) => {
15
- const diagnostics = [];
16
- const tree = syntaxTree(view.state);
17
- tree.iterate({
18
- enter(node) {
19
- if (node.type.isError) {
20
- diagnostics.push({
21
- from: node.from,
22
- to: Math.max(node.to, node.from + 1),
23
- severity: "error",
24
- message,
25
- });
26
- }
27
- },
28
- });
29
- return diagnostics;
30
- });
31
- }