@gooddata/sdk-ui-catalog 11.46.0-alpha.2 → 11.46.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.
Files changed (96) hide show
  1. package/esm/AnalyticsCatalogDetail.d.ts.map +1 -1
  2. package/esm/AnalyticsCatalogDetail.js +2 -1
  3. package/esm/catalog/Catalog.d.ts.map +1 -1
  4. package/esm/catalog/Catalog.js +5 -2
  5. package/esm/catalogDetail/CatalogDetailActionBar.d.ts +6 -4
  6. package/esm/catalogDetail/CatalogDetailActionBar.d.ts.map +1 -1
  7. package/esm/catalogDetail/CatalogDetailActionBar.js +5 -6
  8. package/esm/catalogDetail/CatalogDetailActions.d.ts +2 -1
  9. package/esm/catalogDetail/CatalogDetailActions.d.ts.map +1 -1
  10. package/esm/catalogDetail/CatalogDetailActions.js +6 -2
  11. package/esm/catalogDetail/CatalogDetailContent.d.ts.map +1 -1
  12. package/esm/catalogDetail/CatalogDetailContent.js +3 -1
  13. package/esm/catalogItem/query.d.ts +7 -2
  14. package/esm/catalogItem/query.d.ts.map +1 -1
  15. package/esm/catalogItem/query.js +16 -1
  16. package/esm/header/CreateObjectButton.d.ts +2 -1
  17. package/esm/header/CreateObjectButton.d.ts.map +1 -1
  18. package/esm/header/CreateObjectButton.js +42 -38
  19. package/esm/localization/bundles/en-US.localization-bundle.d.ts +112 -0
  20. package/esm/localization/bundles/en-US.localization-bundle.d.ts.map +1 -1
  21. package/esm/localization/bundles/en-US.localization-bundle.js +112 -0
  22. package/esm/main/Main.d.ts.map +1 -1
  23. package/esm/main/Main.js +2 -3
  24. package/esm/metric/MetricCreateDialog.d.ts +11 -0
  25. package/esm/metric/MetricCreateDialog.d.ts.map +1 -0
  26. package/esm/metric/MetricCreateDialog.js +55 -0
  27. package/esm/metric/MetricDeleteDialog.d.ts +9 -0
  28. package/esm/metric/MetricDeleteDialog.d.ts.map +1 -0
  29. package/esm/metric/MetricDeleteDialog.js +68 -0
  30. package/esm/metric/MetricDetailActions.d.ts +23 -0
  31. package/esm/metric/MetricDetailActions.d.ts.map +1 -0
  32. package/esm/metric/MetricDetailActions.js +101 -0
  33. package/esm/metric/MetricDialog.d.ts +14 -0
  34. package/esm/metric/MetricDialog.d.ts.map +1 -0
  35. package/esm/metric/MetricDialog.js +100 -0
  36. package/esm/metric/MetricEditDialog.d.ts +11 -0
  37. package/esm/metric/MetricEditDialog.d.ts.map +1 -0
  38. package/esm/metric/MetricEditDialog.js +51 -0
  39. package/esm/metric/MetricMutationContext.d.ts +16 -0
  40. package/esm/metric/MetricMutationContext.d.ts.map +1 -0
  41. package/esm/metric/MetricMutationContext.js +32 -0
  42. package/esm/metric/MetricYamlEditor.d.ts +8 -0
  43. package/esm/metric/MetricYamlEditor.d.ts.map +1 -0
  44. package/esm/metric/MetricYamlEditor.js +20 -0
  45. package/esm/metric/gate.d.ts +9 -0
  46. package/esm/metric/gate.d.ts.map +1 -0
  47. package/esm/metric/gate.js +16 -0
  48. package/esm/metric/metricCompletions.d.ts +7 -0
  49. package/esm/metric/metricCompletions.d.ts.map +1 -0
  50. package/esm/metric/metricCompletions.js +59 -0
  51. package/esm/metric/metricConverter.d.ts +49 -0
  52. package/esm/metric/metricConverter.d.ts.map +1 -0
  53. package/esm/metric/metricConverter.js +101 -0
  54. package/esm/metric/metricCopy.d.ts +4 -0
  55. package/esm/metric/metricCopy.d.ts.map +1 -0
  56. package/esm/metric/metricCopy.js +60 -0
  57. package/esm/metric/metricMutationPort.d.ts +18 -0
  58. package/esm/metric/metricMutationPort.d.ts.map +1 -0
  59. package/esm/metric/metricMutationPort.js +39 -0
  60. package/esm/metric/metricSchema.d.ts +29 -0
  61. package/esm/metric/metricSchema.d.ts.map +1 -0
  62. package/esm/metric/metricSchema.js +30 -0
  63. package/esm/metric/metricSerialization.d.ts +10 -0
  64. package/esm/metric/metricSerialization.d.ts.map +1 -0
  65. package/esm/metric/metricSerialization.js +33 -0
  66. package/esm/metric/metricValidation.d.ts +15 -0
  67. package/esm/metric/metricValidation.d.ts.map +1 -0
  68. package/esm/metric/metricValidation.js +47 -0
  69. package/esm/metric/metricYamlLinter.d.ts +7 -0
  70. package/esm/metric/metricYamlLinter.d.ts.map +1 -0
  71. package/esm/metric/metricYamlLinter.js +13 -0
  72. package/esm/metric/tests/metricMutationPort.test.utils.d.ts +7 -0
  73. package/esm/metric/tests/metricMutationPort.test.utils.d.ts.map +1 -0
  74. package/esm/metric/tests/metricMutationPort.test.utils.js +43 -0
  75. package/esm/parameter/ParameterDialog.d.ts.map +1 -1
  76. package/esm/parameter/ParameterDialog.js +7 -7
  77. package/esm/parameter/ParameterYamlEditor.js +1 -1
  78. package/esm/parameter/yamlLinter.d.ts +1 -4
  79. package/esm/parameter/yamlLinter.d.ts.map +1 -1
  80. package/esm/parameter/yamlLinter.js +3 -24
  81. package/esm/utils/backendError.d.ts +11 -0
  82. package/esm/utils/backendError.d.ts.map +1 -0
  83. package/esm/utils/backendError.js +21 -0
  84. package/esm/utils/yamlSyntaxLinter.d.ts +11 -0
  85. package/esm/utils/yamlSyntaxLinter.d.ts.map +1 -0
  86. package/esm/utils/yamlSyntaxLinter.js +31 -0
  87. package/package.json +15 -14
  88. package/styles/css/{parameter.css → codeDialog.css} +26 -18
  89. package/styles/css/codeDialog.css.map +1 -0
  90. package/styles/css/detail.css +25 -17
  91. package/styles/css/detail.css.map +1 -1
  92. package/styles/css/main.css +25 -17
  93. package/styles/css/main.css.map +1 -1
  94. package/styles/scss/{parameter.scss → codeDialog.scss} +17 -8
  95. package/styles/scss/detail.scss +1 -1
  96. package/styles/css/parameter.css.map +0 -1
@@ -0,0 +1,47 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { parse as parseYaml } from "yaml";
3
+ import { metricYamlToDefinition } from "./metricConverter.js";
4
+ import { metricSchema } from "./metricSchema.js";
5
+ export function validateMetricYaml(value, options = {}) {
6
+ if (value.trim() === "") {
7
+ return invalid("empty");
8
+ }
9
+ let parsed;
10
+ try {
11
+ parsed = parseYaml(value, { strict: true });
12
+ }
13
+ catch {
14
+ return invalid("syntax");
15
+ }
16
+ const result = metricSchema.safeParse(parsed);
17
+ if (!result.success) {
18
+ return classifySchemaError(result.error, parsed);
19
+ }
20
+ if (options.fixedIdentifier !== undefined && result.data.id !== options.fixedIdentifier) {
21
+ return invalid("idImmutable");
22
+ }
23
+ return {
24
+ isValid: true,
25
+ measure: metricYamlToDefinition(result.data),
26
+ };
27
+ }
28
+ function classifySchemaError(error, parsed) {
29
+ const maqlProvided = typeof parsed === "object" && parsed !== null && parsed.maql !== undefined;
30
+ for (const issue of error.issues) {
31
+ const path = issue.path.map(String).join(".");
32
+ if (path === "maql") {
33
+ // A present-but-wrong-typed maql is a structural error, not a missing field.
34
+ return invalid(maqlProvided ? "invalidStructure" : "missingMaql");
35
+ }
36
+ if (path === "tags" || path.startsWith("tags.")) {
37
+ return invalid("invalidTags");
38
+ }
39
+ }
40
+ return invalid("invalidStructure");
41
+ }
42
+ function invalid(code) {
43
+ return {
44
+ isValid: false,
45
+ errorCode: code,
46
+ };
47
+ }
@@ -0,0 +1,7 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,13 @@
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
+ }
@@ -0,0 +1,7 @@
1
+ import type { IMetricMutationPort } from "../metricMutationPort.js";
2
+ /**
3
+ * Test utility. Returns a metric mutation port with vi.fn() stubs.
4
+ * @internal
5
+ */
6
+ export declare function createTestMetricMutationPort(overrides?: Partial<IMetricMutationPort>): IMetricMutationPort;
7
+ //# sourceMappingURL=metricMutationPort.test.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metricMutationPort.test.utils.d.ts","sourceRoot":"","sources":["../../../src/metric/tests/metricMutationPort.test.utils.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAiBpE;;;GAGG;AACH,wBAAgB,4BAA4B,CACxC,SAAS,GAAE,OAAO,CAAC,mBAAmB,CAAM,GAC7C,mBAAmB,CAsBrB"}
@@ -0,0 +1,43 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { vi } from "vitest";
3
+ const defaultSavedItem = {
4
+ identifier: "test-metric",
5
+ type: "measure",
6
+ title: "Test Metric",
7
+ description: "",
8
+ tags: [],
9
+ createdBy: "test",
10
+ updatedBy: "test",
11
+ createdAt: null,
12
+ updatedAt: null,
13
+ isLocked: false,
14
+ isEditable: true,
15
+ format: "#,##0.00",
16
+ };
17
+ /**
18
+ * Test utility. Returns a metric mutation port with vi.fn() stubs.
19
+ * @internal
20
+ */
21
+ export function createTestMetricMutationPort(overrides = {}) {
22
+ return {
23
+ create: vi.fn().mockResolvedValue(defaultSavedItem),
24
+ update: vi.fn().mockResolvedValue(defaultSavedItem),
25
+ delete: vi.fn().mockResolvedValue(undefined),
26
+ load: vi.fn().mockResolvedValue({
27
+ id: "test-metric",
28
+ uri: "test-metric",
29
+ ref: { identifier: "test-metric", type: "measure" },
30
+ type: "measure",
31
+ title: "Test Metric",
32
+ description: "",
33
+ tags: [],
34
+ production: true,
35
+ deprecated: false,
36
+ unlisted: false,
37
+ expression: "SELECT 1",
38
+ format: "#,##0.00",
39
+ }),
40
+ getReferencingObjects: vi.fn().mockResolvedValue({ insights: [], measures: [] }),
41
+ ...overrides,
42
+ };
43
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ParameterDialog.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAK9E,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,6BAA6B,CAAC;AAyB5F,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,mBAAmB,CAAC;IAC1B,gBAAgB,CAAC,EAAE,cAAc,CAAC;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,2CAsJ3C"}
1
+ {"version":3,"file":"ParameterDialog.d.ts","sourceRoot":"","sources":["../../src/parameter/ParameterDialog.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AAM9E,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,6BAA6B,CAAC;AAyB5F,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,KAAK,KAAK,GAAG;IACT,IAAI,EAAE,mBAAmB,CAAC;IAC1B,gBAAgB,CAAC,EAAE,cAAc,CAAC;IAClC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,kCAAkC,KAAK,IAAI,CAAC;CACzE,CAAC;AAEF,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,2CAyJ3C"}
@@ -4,6 +4,7 @@ import { useCallback, useRef, useState } from "react";
4
4
  import { FormattedMessage, defineMessages, useIntl } from "react-intl";
5
5
  import { ConfirmDialog, UiButton, UiIcon, UiLink, UiTooltip } from "@gooddata/sdk-ui-kit";
6
6
  import { useIsWhiteLabeled } from "../permission/PermissionsContext.js";
7
+ import { extractBackendErrorDetail } from "../utils/backendError.js";
7
8
  import { serializeParameterToYaml } from "./parameterSerialization.js";
8
9
  import { validateParameterYaml } from "./parameterValidation.js";
9
10
  import { ParameterYamlEditor } from "./ParameterYamlEditor.js";
@@ -69,8 +70,7 @@ export function ParameterDialog(props) {
69
70
  await onSubmit(result.parameter);
70
71
  }
71
72
  catch (error) {
72
- const message = error instanceof Error && error.message ? error.message : undefined;
73
- setSubmitError(message ?? intl.formatMessage(messages.dialogSubmitError));
73
+ setSubmitError(extractBackendErrorDetail(error) ?? intl.formatMessage(messages.dialogSubmitError));
74
74
  }
75
75
  finally {
76
76
  setIsSubmitting(false);
@@ -88,12 +88,12 @@ export function ParameterDialog(props) {
88
88
  }
89
89
  onDuplicate(result.parameter);
90
90
  }, [intl, onDuplicate, validate]);
91
- const footerLeftRenderer = useCallback(() => (_jsxs("div", { className: "gd-parameter-dialog-footer-left", children: [isWhiteLabeled ? null : (_jsxs(UiLink, { variant: "secondary", href: PARAMETER_DOCS_URL, target: "_blank", rel: "noopener noreferrer", children: [
91
+ const footerLeftRenderer = useCallback(() => (_jsxs("div", { className: "gd-ascode-dialog-footer-left", children: [isWhiteLabeled ? null : (_jsxs(UiLink, { variant: "secondary", href: PARAMETER_DOCS_URL, target: "_blank", rel: "noopener noreferrer", children: [
92
92
  _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), _jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.help" })
93
93
  ] })), isEdit && onDuplicate ? (_jsx(UiButton, { label: intl.formatMessage(messages.dialogDuplicate), variant: "tertiary", isDisabled: isSubmitting, onClick: handleDuplicate })) : null] })), [handleDuplicate, intl, isEdit, isSubmitting, isWhiteLabeled, onDuplicate]);
94
- return (_jsx(ConfirmDialog, { className: "gd-parameter-dialog", containerClassName: "gd-parameter-dialog-overlay", headline: headlineMessage, cancelButtonText: cancelMessage, submitButtonText: submitMessage, isPositive: true, isSubmitDisabled: isSubmitting || (isEdit && !isDirty), isCancelDisabled: isSubmitting, shouldCloseOnEscape: !isSubmitting, onCancel: handleClose, onClose: handleClose, onSubmit: handleSubmit, displayCloseButton: !isSubmitting, footerLeftRenderer: footerLeftRenderer, children: _jsxs("div", { className: "gd-parameter-dialog-content", children: [
95
- _jsxs("div", { className: "gd-parameter-dialog-section-header", children: [
94
+ return (_jsx(ConfirmDialog, { className: "gd-ascode-dialog", containerClassName: "gd-ascode-dialog-overlay", headline: headlineMessage, cancelButtonText: cancelMessage, submitButtonText: submitMessage, isPositive: true, isSubmitDisabled: isSubmitting || (isEdit && !isDirty), isCancelDisabled: isSubmitting, shouldCloseOnEscape: !isSubmitting, onCancel: handleClose, onClose: handleClose, onSubmit: handleSubmit, displayCloseButton: !isSubmitting, footerLeftRenderer: footerLeftRenderer, children: _jsxs("div", { className: "gd-ascode-dialog-content", children: [
95
+ _jsxs("div", { className: "gd-ascode-dialog-section-header", children: [
96
96
  _jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.sectionHeader" }), _jsx(UiTooltip, { arrowPlacement: "top", optimalPlacement: true, triggerBy: ["hover", "click", "focus"], anchor: _jsx(UiIcon, { type: "question", size: 14, color: "complementary-6" }), content: _jsx(FormattedMessage, { id: "analyticsCatalog.parameter.dialog.sectionHeader.tooltip" }) })
97
- ] }), _jsx("div", { className: "gd-parameter-dialog-editor", children: _jsx(ParameterYamlEditor, { initialValue: initialYaml, onChange: handleChange, disabled: isSubmitting }) }), validationError || submitError ? (_jsxs("div", { className: "gd-parameter-dialog-error", children: [
98
- _jsx("span", { className: "gd-parameter-dialog-error-label", children: "Error:" }), " ", validationError ?? submitError] })) : null] }) }));
97
+ ] }), _jsx("div", { className: "gd-ascode-dialog-editor", children: _jsx(ParameterYamlEditor, { initialValue: initialYaml, onChange: handleChange, disabled: isSubmitting }) }), validationError || submitError ? (_jsxs("div", { className: "gd-ascode-dialog-error", children: [
98
+ _jsx("span", { className: "gd-ascode-dialog-error-label", children: _jsx(FormattedMessage, { id: "analyticsCatalog.dialog.error.label" }) }), " ", validationError ?? submitError] })) : null] }) }));
99
99
  }
@@ -16,5 +16,5 @@ export function ParameterYamlEditor({ initialValue, onChange, disabled = false }
16
16
  setValue(nextValue);
17
17
  onChange?.(nextValue);
18
18
  }, [onChange]);
19
- return (_jsx(SyntaxHighlightingInput, { className: "gd-parameter-dialog-editor-input", value: value, onChange: handleChange, extensions: extensions, onCompletion: parameterSchemaCompletions, disabled: disabled }));
19
+ return (_jsx(SyntaxHighlightingInput, { className: "gd-ascode-dialog-editor-input", value: value, onChange: handleChange, extensions: extensions, onCompletion: parameterSchemaCompletions, disabled: disabled }));
20
20
  }
@@ -1,10 +1,7 @@
1
1
  import { type IntlShape } from "react-intl";
2
2
  /**
3
3
  * Creates a CodeMirror linter extension that reports YAML syntax errors
4
- * by walking the parse tree for error nodes.
5
- *
6
- * This reuses the tree already built by `@codemirror/lang-yaml` for
7
- * highlighting — no extra parsing or dependencies required.
4
+ * using the parameter-specific syntax error message.
8
5
  */
9
6
  export declare function createYamlLinter(intl: IntlShape): import("@codemirror/state").Extension;
10
7
  //# sourceMappingURL=yamlLinter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"yamlLinter.d.ts","sourceRoot":"","sources":["../../src/parameter/yamlLinter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAkB,MAAM,YAAY,CAAC;AAM5D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,yCAsB/C"}
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,34 +1,13 @@
1
1
  // (C) 2026 GoodData Corporation
2
- import { syntaxTree } from "@codemirror/language";
3
- import { linter } from "@codemirror/lint";
4
2
  import { defineMessages } from "react-intl";
3
+ import { createYamlSyntaxLinter } from "../utils/yamlSyntaxLinter.js";
5
4
  const messages = defineMessages({
6
5
  syntaxError: { id: "analyticsCatalog.parameter.validation.syntax" },
7
6
  });
8
7
  /**
9
8
  * Creates a CodeMirror linter extension that reports YAML syntax errors
10
- * by walking the parse tree for error nodes.
11
- *
12
- * This reuses the tree already built by `@codemirror/lang-yaml` for
13
- * highlighting — no extra parsing or dependencies required.
9
+ * using the parameter-specific syntax error message.
14
10
  */
15
11
  export function createYamlLinter(intl) {
16
- const message = intl.formatMessage(messages.syntaxError);
17
- return linter((view) => {
18
- const diagnostics = [];
19
- const tree = syntaxTree(view.state);
20
- tree.iterate({
21
- enter(node) {
22
- if (node.type.isError) {
23
- diagnostics.push({
24
- from: node.from,
25
- to: Math.max(node.to, node.from + 1),
26
- severity: "error",
27
- message,
28
- });
29
- }
30
- },
31
- });
32
- return diagnostics;
33
- });
12
+ return createYamlSyntaxLinter(intl.formatMessage(messages.syntaxError));
34
13
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Extracts the human-readable reason from a backend error, if present.
3
+ *
4
+ * For a generic `UnexpectedResponseError` the meaningful reason lives in Tiger's RFC 7807
5
+ * `responseBody.detail`, while `error.message` carries only the transport-level "Request failed
6
+ * with status code NNN" — so that message is intentionally ignored. Other typed backend errors
7
+ * (e.g. `LimitReached` → "Upgrade your plan to create more objects.") carry a curated, user-facing
8
+ * message, which is preserved. Callers fall back to a localized generic message otherwise.
9
+ */
10
+ export declare function extractBackendErrorDetail(error: unknown): string | undefined;
11
+ //# sourceMappingURL=backendError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backendError.d.ts","sourceRoot":"","sources":["../../src/utils/backendError.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAS5E"}
@@ -0,0 +1,21 @@
1
+ // (C) 2026 GoodData Corporation
2
+ import { isAnalyticalBackendError, isUnexpectedResponseError } from "@gooddata/sdk-backend-spi";
3
+ /**
4
+ * Extracts the human-readable reason from a backend error, if present.
5
+ *
6
+ * For a generic `UnexpectedResponseError` the meaningful reason lives in Tiger's RFC 7807
7
+ * `responseBody.detail`, while `error.message` carries only the transport-level "Request failed
8
+ * with status code NNN" — so that message is intentionally ignored. Other typed backend errors
9
+ * (e.g. `LimitReached` → "Upgrade your plan to create more objects.") carry a curated, user-facing
10
+ * message, which is preserved. Callers fall back to a localized generic message otherwise.
11
+ */
12
+ export function extractBackendErrorDetail(error) {
13
+ if (isUnexpectedResponseError(error)) {
14
+ const detail = error.responseBody?.detail;
15
+ return typeof detail === "string" && detail.trim() !== "" ? detail : undefined;
16
+ }
17
+ if (isAnalyticalBackendError(error) && error.message.trim() !== "") {
18
+ return error.message;
19
+ }
20
+ return undefined;
21
+ }
@@ -0,0 +1,11 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,31 @@
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddata/sdk-ui-catalog",
3
- "version": "11.46.0-alpha.2",
3
+ "version": "11.46.0-alpha.4",
4
4
  "description": "GoodData SDK - Analytics Catalog",
5
5
  "license": "MIT",
6
6
  "author": "GoodData Corporation",
@@ -45,14 +45,15 @@
45
45
  "tslib": "2.8.1",
46
46
  "yaml": "2.8.3",
47
47
  "zod": "4.3.6",
48
- "@gooddata/sdk-backend-spi": "11.46.0-alpha.2",
49
- "@gooddata/sdk-model": "11.46.0-alpha.2",
50
- "@gooddata/sdk-ui": "11.46.0-alpha.2",
51
- "@gooddata/sdk-ui-kit": "11.46.0-alpha.2",
52
- "@gooddata/sdk-ui-ext": "11.46.0-alpha.2",
53
- "@gooddata/sdk-ui-semantic-search": "11.46.0-alpha.2",
54
- "@gooddata/sdk-ui-theme-provider": "11.46.0-alpha.2",
55
- "@gooddata/util": "11.46.0-alpha.2"
48
+ "@gooddata/sdk-backend-spi": "11.46.0-alpha.4",
49
+ "@gooddata/sdk-code-schemas": "11.46.0-alpha.4",
50
+ "@gooddata/sdk-ui": "11.46.0-alpha.4",
51
+ "@gooddata/sdk-model": "11.46.0-alpha.4",
52
+ "@gooddata/sdk-ui-ext": "11.46.0-alpha.4",
53
+ "@gooddata/sdk-ui-kit": "11.46.0-alpha.4",
54
+ "@gooddata/sdk-ui-semantic-search": "11.46.0-alpha.4",
55
+ "@gooddata/sdk-ui-theme-provider": "11.46.0-alpha.4",
56
+ "@gooddata/util": "11.46.0-alpha.4"
56
57
  },
57
58
  "devDependencies": {
58
59
  "@microsoft/api-documenter": "^7.17.0",
@@ -92,11 +93,11 @@
92
93
  "typescript": "5.9.3",
93
94
  "vitest": "4.1.8",
94
95
  "vitest-dom": "0.1.1",
95
- "@gooddata/eslint-config": "11.46.0-alpha.2",
96
- "@gooddata/i18n-toolkit": "11.46.0-alpha.2",
97
- "@gooddata/sdk-backend-mockingbird": "11.46.0-alpha.2",
98
- "@gooddata/oxlint-config": "11.46.0-alpha.2",
99
- "@gooddata/stylelint-config": "11.46.0-alpha.2"
96
+ "@gooddata/oxlint-config": "11.46.0-alpha.4",
97
+ "@gooddata/i18n-toolkit": "11.46.0-alpha.4",
98
+ "@gooddata/eslint-config": "11.46.0-alpha.4",
99
+ "@gooddata/sdk-backend-mockingbird": "11.46.0-alpha.4",
100
+ "@gooddata/stylelint-config": "11.46.0-alpha.4"
100
101
  },
101
102
  "peerDependencies": {
102
103
  "react": "^18.0.0 || ^19.0.0",
@@ -1,23 +1,23 @@
1
- .gd-parameter-dialog {
1
+ .gd-ascode-dialog {
2
2
  width: 640px;
3
3
  height: 560px;
4
4
  flex-direction: column;
5
5
  display: flex;
6
6
  overflow: hidden;
7
7
  }
8
- .gd-parameter-dialog.overlay.gd-dialog:not(.gd-dropdown) {
8
+ .gd-ascode-dialog.overlay.gd-dialog:not(.gd-dropdown) {
9
9
  max-width: calc(100vw - 40px);
10
10
  padding: 0;
11
11
  }
12
- .gd-parameter-dialog .gd-dialog-header-wrapper {
12
+ .gd-ascode-dialog .gd-dialog-header-wrapper {
13
13
  padding: 20px 20px 0;
14
14
  }
15
- .gd-parameter-dialog .gd-dialog-content {
15
+ .gd-ascode-dialog .gd-dialog-content {
16
16
  flex: auto;
17
17
  padding: 0;
18
18
  overflow: hidden;
19
19
  }
20
- .gd-parameter-dialog .gd-dialog-footer {
20
+ .gd-ascode-dialog .gd-dialog-footer {
21
21
  display: flex;
22
22
  align-items: center;
23
23
  margin-top: 0;
@@ -25,15 +25,23 @@
25
25
  border-top: 1px solid var(--gd-palette-complementary-3);
26
26
  }
27
27
 
28
- .gd-parameter-dialog-content {
28
+ .gd-ascode-dialog-content {
29
29
  display: grid;
30
30
  grid-template-rows: auto 1fr;
31
31
  height: 100%;
32
- background-color: #fcfcfd;
32
+ background-color: var(--gd-palette-complementary-0-from-theme, #fcfcfd);
33
33
  border-top: 1px solid var(--gd-palette-complementary-3);
34
34
  }
35
35
 
36
- .gd-parameter-dialog-section-header {
36
+ .gd-ascode-dialog-loading {
37
+ grid-row: 1/-1;
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ height: 100%;
42
+ }
43
+
44
+ .gd-ascode-dialog-section-header {
37
45
  display: flex;
38
46
  align-items: center;
39
47
  gap: 5px;
@@ -45,38 +53,38 @@
45
53
  color: var(--gd-palette-complementary-6);
46
54
  }
47
55
 
48
- .gd-parameter-dialog-editor {
56
+ .gd-ascode-dialog-editor {
49
57
  height: 100%;
50
58
  overflow: hidden;
51
59
  padding: 10px 20px 20px;
52
60
  }
53
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input {
61
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input {
54
62
  height: 100%;
55
63
  font-family: "Andale Mono", monospace;
56
64
  font-size: 14px;
57
65
  line-height: 22px;
58
66
  }
59
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-editor {
67
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-editor {
60
68
  height: 100%;
61
69
  border-color: transparent;
62
70
  background-color: transparent;
63
71
  box-shadow: none;
64
72
  transition: none;
65
73
  }
66
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-editor.cm-focused {
74
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-editor.cm-focused {
67
75
  border-color: var(--gd-palette-primary-base, #14b2e2);
68
76
  }
69
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-content {
77
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-content {
70
78
  font-family: "Andale Mono", monospace;
71
79
  }
72
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-gutters {
80
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-gutters {
73
81
  background-color: transparent;
74
82
  border-right: none;
75
83
  color: var(--gd-palette-complementary-6);
76
84
  padding-right: 10px;
77
85
  }
78
86
 
79
- .gd-parameter-dialog-error {
87
+ .gd-ascode-dialog-error {
80
88
  background-color: var(--gd-palette-error-lightest, #fff2f1);
81
89
  color: var(--gd-palette-error-base, #e54d42);
82
90
  font-size: 14px;
@@ -85,11 +93,11 @@
85
93
  margin: 0 20px 10px;
86
94
  border-radius: 3px;
87
95
  }
88
- .gd-parameter-dialog-error .gd-parameter-dialog-error-label {
96
+ .gd-ascode-dialog-error .gd-ascode-dialog-error-label {
89
97
  font-weight: 700;
90
98
  }
91
99
 
92
- .gd-parameter-dialog-footer-left {
100
+ .gd-ascode-dialog-footer-left {
93
101
  display: flex;
94
102
  align-items: center;
95
103
  justify-content: space-between;
@@ -98,4 +106,4 @@
98
106
  margin-right: 10px;
99
107
  }
100
108
 
101
- /*# sourceMappingURL=parameter.css.map */
109
+ /*# sourceMappingURL=codeDialog.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["../scss/codeDialog.scss","../../node_modules/@gooddata/sdk-ui-kit/styles/scss/variables.scss"],"names":[],"mappings":"AAIA;EACI;EACA;EACA;EACA;EACA;;AAGA;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI,cCpCU;;ADwClB;EACI;;AAGJ;EACI;EACA;EACA;EACA;;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA","file":"codeDialog.css"}
@@ -14,26 +14,26 @@
14
14
  --catalog-object-type-icon-color: #f18600;
15
15
  }
16
16
 
17
- .gd-parameter-dialog {
17
+ .gd-ascode-dialog {
18
18
  width: 640px;
19
19
  height: 560px;
20
20
  flex-direction: column;
21
21
  display: flex;
22
22
  overflow: hidden;
23
23
  }
24
- .gd-parameter-dialog.overlay.gd-dialog:not(.gd-dropdown) {
24
+ .gd-ascode-dialog.overlay.gd-dialog:not(.gd-dropdown) {
25
25
  max-width: calc(100vw - 40px);
26
26
  padding: 0;
27
27
  }
28
- .gd-parameter-dialog .gd-dialog-header-wrapper {
28
+ .gd-ascode-dialog .gd-dialog-header-wrapper {
29
29
  padding: 20px 20px 0;
30
30
  }
31
- .gd-parameter-dialog .gd-dialog-content {
31
+ .gd-ascode-dialog .gd-dialog-content {
32
32
  flex: auto;
33
33
  padding: 0;
34
34
  overflow: hidden;
35
35
  }
36
- .gd-parameter-dialog .gd-dialog-footer {
36
+ .gd-ascode-dialog .gd-dialog-footer {
37
37
  display: flex;
38
38
  align-items: center;
39
39
  margin-top: 0;
@@ -41,15 +41,23 @@
41
41
  border-top: 1px solid var(--gd-palette-complementary-3);
42
42
  }
43
43
 
44
- .gd-parameter-dialog-content {
44
+ .gd-ascode-dialog-content {
45
45
  display: grid;
46
46
  grid-template-rows: auto 1fr;
47
47
  height: 100%;
48
- background-color: #fcfcfd;
48
+ background-color: var(--gd-palette-complementary-0-from-theme, #fcfcfd);
49
49
  border-top: 1px solid var(--gd-palette-complementary-3);
50
50
  }
51
51
 
52
- .gd-parameter-dialog-section-header {
52
+ .gd-ascode-dialog-loading {
53
+ grid-row: 1/-1;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ height: 100%;
58
+ }
59
+
60
+ .gd-ascode-dialog-section-header {
53
61
  display: flex;
54
62
  align-items: center;
55
63
  gap: 5px;
@@ -61,38 +69,38 @@
61
69
  color: var(--gd-palette-complementary-6);
62
70
  }
63
71
 
64
- .gd-parameter-dialog-editor {
72
+ .gd-ascode-dialog-editor {
65
73
  height: 100%;
66
74
  overflow: hidden;
67
75
  padding: 10px 20px 20px;
68
76
  }
69
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input {
77
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input {
70
78
  height: 100%;
71
79
  font-family: "Andale Mono", monospace;
72
80
  font-size: 14px;
73
81
  line-height: 22px;
74
82
  }
75
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-editor {
83
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-editor {
76
84
  height: 100%;
77
85
  border-color: transparent;
78
86
  background-color: transparent;
79
87
  box-shadow: none;
80
88
  transition: none;
81
89
  }
82
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-editor.cm-focused {
90
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-editor.cm-focused {
83
91
  border-color: var(--gd-palette-primary-base, #14b2e2);
84
92
  }
85
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-content {
93
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-content {
86
94
  font-family: "Andale Mono", monospace;
87
95
  }
88
- .gd-parameter-dialog-editor .gd-input-syntax-highlighting-input .cm-gutters {
96
+ .gd-ascode-dialog-editor .gd-input-syntax-highlighting-input .cm-gutters {
89
97
  background-color: transparent;
90
98
  border-right: none;
91
99
  color: var(--gd-palette-complementary-6);
92
100
  padding-right: 10px;
93
101
  }
94
102
 
95
- .gd-parameter-dialog-error {
103
+ .gd-ascode-dialog-error {
96
104
  background-color: var(--gd-palette-error-lightest, #fff2f1);
97
105
  color: var(--gd-palette-error-base, #e54d42);
98
106
  font-size: 14px;
@@ -101,11 +109,11 @@
101
109
  margin: 0 20px 10px;
102
110
  border-radius: 3px;
103
111
  }
104
- .gd-parameter-dialog-error .gd-parameter-dialog-error-label {
112
+ .gd-ascode-dialog-error .gd-ascode-dialog-error-label {
105
113
  font-weight: 700;
106
114
  }
107
115
 
108
- .gd-parameter-dialog-footer-left {
116
+ .gd-ascode-dialog-footer-left {
109
117
  display: flex;
110
118
  align-items: center;
111
119
  justify-content: space-between;
@@ -1 +1 @@
1
- {"version":3,"sourceRoot":"","sources":["../scss/objectType.scss","../scss/parameter.scss","../../node_modules/@gooddata/sdk-ui-kit/styles/scss/variables.scss","../scss/detail.scss"],"names":[],"mappings":"AAKI;EAEI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;AAGJ;EACI;;;ACrBR;EACI;EACA;EACA;EACA;EACA;;AAGA;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI,cC3BU;;AD+BlB;EACI;;AAGJ;EACI;EACA;EACA;EACA;;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;;;AEjGJ;EACI,aDwFc;ECvFd,WAJgB;EAKhB,OAVI;EAWJ;;AAEA;EANJ;IAOQ;;;AAGJ;EAEI;EACA;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;;AAGA;EACI;EACA;EACA;;AAIJ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA,ODzCA;EC0CA,WAtEE;EAuEF,aAtES;EAuET;EACA;;AAEA;EACI;;AAOJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI,OD3EG;;AC8EP;EACI;EACA,OD7EJ;EC8EI;EACA;;AAGJ;EAEI;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI,ODnGJ;ECoGI,aAzHQ;EA0HR,WA3HC;EA4HD;EACA;EACA;;AAGJ;EACI,ODxGJ;ECyGI,WAjIA;EAkIA;EACA;EACA;EACA;EACA;;AAGJ;EACI,ODzHG;;AC4HP;EACI;EACA,OD3HJ;;AC+HJ;EACI;;AAEA;EACI;;AAKZ;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;;AAKR;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAMR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAEA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA,ODhQQ;ECiQR;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;;AAGJ;EACI;EACA;;AAKJ;EACI;EACA;;AAGJ;EACI,ODjSW;;ACoSf;EACI;EACA,ODnSI;;ACuSZ;EACI,ODpSQ;ECqSR;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,ODvTW;ECwTX;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;;AAEJ;EACI;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIR;EACI,MD7XS;;AC+Xb;AAAA;EAEI,MDhYQ;;ACkYZ;AAAA;EAEI,MDlYO;;ACoYX;EACI;;AAEJ;EACI;;AAGJ;EACI,QD3XW;;;ACiYnB;EACI;EACA;EACA;EACA;EACA;EACA;EACA,kBD9YS;EC+YT;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGI;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,kBD/bK;ECgcL;EACA;EACA,ODrbI;;ACubJ;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI","file":"detail.css"}
1
+ {"version":3,"sourceRoot":"","sources":["../scss/objectType.scss","../scss/codeDialog.scss","../../node_modules/@gooddata/sdk-ui-kit/styles/scss/variables.scss","../scss/detail.scss"],"names":[],"mappings":"AAKI;EAEI;;AAGJ;EACI;;AAGJ;EACI;;AAGJ;EAEI;;AAGJ;EACI;;;ACpBR;EACI;EACA;EACA;EACA;EACA;;AAGA;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAIR;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI,cCpCU;;ADwClB;EACI;;AAGJ;EACI;EACA;EACA;EACA;;;AAKZ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;;AAIR;EACI;EACA;EACA;EACA;EACA;EACA;;;AE1GJ;EACI,aDwFc;ECvFd,WAJgB;EAKhB,OAVI;EAWJ;;AAEA;EANJ;IAOQ;;;AAGJ;EAEI;EACA;;AAGJ;EACI;EACA;EACA;;AAEA;EACI;;AAIR;EACI;EACA;EACA;;AAGA;EACI;EACA;EACA;;AAIJ;EACI;EACA;;AAEA;EACI;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA,ODzCA;EC0CA,WAtEE;EAuEF,aAtES;EAuET;EACA;;AAEA;EACI;;AAOJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAGJ;EACI,OD3EG;;AC8EP;EACI;EACA,OD7EJ;EC8EI;EACA;;AAGJ;EAEI;;AAGJ;EACI;EACA;EACA;EACA;;AAIR;EACI;;AAEA;EACI,ODnGJ;ECoGI,aAzHQ;EA0HR,WA3HC;EA4HD;EACA;EACA;;AAGJ;EACI,ODxGJ;ECyGI,WAjIA;EAkIA;EACA;EACA;EACA;EACA;;AAGJ;EACI,ODzHG;;AC4HP;EACI;EACA,OD3HJ;;AC+HJ;EACI;;AAEA;EACI;;AAKZ;EACI;EACA;;AAIR;EACI;EACA;EACA;;AAEA;EACI;;AAKR;EACI;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;;AAEA;AAAA;EAEI;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;;AAMR;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAEA;EACI;;AAKZ;EACI;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA,ODhQQ;ECiQR;EACA;EACA;EACA;;AAEA;EACI;EACA;;AAKJ;EACI;;AAGJ;EACI;EACA;;AAKJ;EACI;EACA;;AAGJ;EACI,ODjSW;;ACoSf;EACI;EACA,ODnSI;;ACuSZ;EACI,ODpSQ;ECqSR;EACA;EACA;EACA;;AAGJ;EACI;EACA;;AAEA;EACI,ODvTW;ECwTX;EACA;EACA;EACA;;AAIR;EACI;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;EACA;EACA;EACA;;AAEJ;EACI;EACA;;AAEJ;EACI;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACI;EACA;EACA;;AAIR;EACI,MD7XS;;AC+Xb;AAAA;EAEI,MDhYQ;;ACkYZ;AAAA;EAEI,MDlYO;;ACoYX;EACI;;AAEJ;EACI;;AAGJ;EACI,QD3XW;;;ACiYnB;EACI;EACA;EACA;EACA;EACA;EACA;EACA,kBD9YS;EC+YT;EACA;;AAEA;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;EACA;EACA;;AAGJ;EACI;EACA;EACA;EACA;;AAGI;EACI;EACA;;AAIR;EACI;;AAGJ;EACI;;AAIR;EACI;EACA;EACA,kBD/bK;ECgcL;EACA;EACA,ODrbI;;ACubJ;EACI;EACA;EACA;;AAGJ;EACI;;AAGJ;EACI;EACA;;AAGJ;EACI","file":"detail.css"}