@grafana/scenes 7.3.4 → 7.3.5

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 (29) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/esm/index.js +2 -1
  3. package/dist/esm/index.js.map +1 -1
  4. package/dist/esm/variables/adhoc/AdHocFilterRenderer.js +1 -1
  5. package/dist/esm/variables/adhoc/AdHocFilterRenderer.js.map +1 -1
  6. package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js +1 -3
  7. package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js.map +1 -1
  8. package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js +23 -0
  9. package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js.map +1 -1
  10. package/dist/esm/variables/adhoc/controller/AdHocFiltersVariableController.js +4 -0
  11. package/dist/esm/variables/adhoc/controller/AdHocFiltersVariableController.js.map +1 -1
  12. package/dist/esm/variables/components/VariableValueInput.js +2 -1
  13. package/dist/esm/variables/components/VariableValueInput.js.map +1 -1
  14. package/dist/esm/variables/components/VariableValueSelect.js +3 -0
  15. package/dist/esm/variables/components/VariableValueSelect.js.map +1 -1
  16. package/dist/esm/variables/components/VariableValueSelectors.js +4 -3
  17. package/dist/esm/variables/components/VariableValueSelectors.js.map +1 -1
  18. package/dist/esm/variables/groupby/GroupByVariable.js +2 -1
  19. package/dist/esm/variables/groupby/GroupByVariable.js.map +1 -1
  20. package/dist/esm/variables/utils.js +7 -1
  21. package/dist/esm/variables/utils.js.map +1 -1
  22. package/dist/esm/variables/variants/IntervalVariable.js +2 -0
  23. package/dist/esm/variables/variants/IntervalVariable.js.map +1 -1
  24. package/dist/esm/variables/variants/SwitchVariable.js +2 -1
  25. package/dist/esm/variables/variants/SwitchVariable.js.map +1 -1
  26. package/dist/index.d.ts +8 -2
  27. package/dist/index.js +44 -9
  28. package/dist/index.js.map +1 -1
  29. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/variables/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport { VariableValue } from './types';\nimport {\n AdHocVariableFilter,\n DataQueryError,\n GetTagResponse,\n GrafanaTheme2,\n MetricFindValue,\n SelectableValue,\n} from '@grafana/data';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneDataQuery, SceneObject, SceneObjectState } from '../core/types';\nimport { SceneQueryRunner } from '../querying/SceneQueryRunner';\nimport { DataSourceRef } from '@grafana/schema';\nimport { css } from '@emotion/css';\n\nexport function isVariableValueEqual(a: VariableValue | null | undefined, b: VariableValue | null | undefined) {\n if (a === b) {\n return true;\n }\n\n return isEqual(a, b);\n}\n\nexport function safeStringifyValue(value: unknown) {\n // Avoid circular references ignoring those references\n const getCircularReplacer = () => {\n const seen = new WeakSet();\n return (_: string, value: object | null) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n };\n\n try {\n return JSON.stringify(value, getCircularReplacer());\n } catch (error) {\n console.error(error);\n }\n\n return '';\n}\n\nexport function renderPrometheusLabelFilters(filters: AdHocVariableFilter[]) {\n return filters.map((filter) => renderFilter(filter)).join(',');\n}\n\nfunction renderFilter(filter: AdHocVariableFilter) {\n let value = '';\n let operator = filter.operator;\n\n // map \"one of\" operator to regex\n if (operator === '=|') {\n operator = '=~';\n // TODO remove when we're on the latest version of @grafana/data\n // @ts-expect-error\n value = filter.values?.map(escapeLabelValueInRegexSelector).join('|');\n } else if (operator === '!=|') {\n operator = '!~';\n // TODO remove when we're on the latest version of @grafana/data\n // @ts-expect-error\n value = filter.values?.map(escapeLabelValueInRegexSelector).join('|');\n } else if (operator === '=~' || operator === '!~') {\n value = escapeLabelValueInRegexSelector(filter.value);\n } else {\n value = escapeLabelValueInExactSelector(filter.value);\n }\n\n return `${filter.key}${operator}\"${value}\"`;\n}\n\n// based on the openmetrics-documentation, the 3 symbols we have to handle are:\n// - \\n ... the newline character\n// - \\ ... the backslash character\n// - \" ... the double-quote character\nexport function escapeLabelValueInExactSelector(labelValue: string): string {\n return labelValue.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"');\n}\n\nexport function escapeLabelValueInRegexSelector(labelValue: string): string {\n return escapeLabelValueInExactSelector(escapeLokiRegexp(labelValue));\n}\n\nexport function isRegexSelector(selector?: string) {\n if (selector && (selector.includes('=~') || selector.includes('!~'))) {\n return true;\n }\n return false;\n}\n\n// Loki regular-expressions use the RE2 syntax (https://github.com/google/re2/wiki/Syntax),\n// so every character that matches something in that list has to be escaped.\n// the list of meta characters is: *+?()|\\.[]{}^$\n// we make a javascript regular expression that matches those characters:\nconst RE2_METACHARACTERS = /[*+?()|\\\\.\\[\\]{}^$]/g;\nfunction escapeLokiRegexp(value: string): string {\n return value.replace(RE2_METACHARACTERS, '\\\\$&');\n}\n\n/**\n * Get all queries in the scene that have the same datasource as provided source object\n */\nexport function getQueriesForVariables(\n sourceObject: SceneObject<SceneObjectState & { datasource: DataSourceRef | null }>\n) {\n const runners = sceneGraph.findAllObjects(\n sourceObject.getRoot(),\n (o) => o instanceof SceneQueryRunner\n ) as SceneQueryRunner[];\n\n const interpolatedDsUuid = sceneGraph.interpolate(sourceObject, sourceObject.state.datasource?.uid);\n\n const applicableRunners = filterOutInactiveRunnerDuplicates(runners).filter((r) => {\n // First check if the runner's datasource matches\n if (r.state.datasource?.uid) {\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, r.state.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n }\n\n // If the runner has no datasource set, check if any of its queries have a matching datasource\n // This handles the case where panel-level datasource is not set but individual queries have datasources\n // (e.g., in v2 schema dashboards where non-mixed panels don't have panel.datasource)\n return r.state.queries.some((q) => {\n if (!q.datasource?.uid) {\n return false;\n }\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, q.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n });\n });\n\n if (applicableRunners.length === 0) {\n return [];\n }\n\n const result: SceneDataQuery[] = [];\n applicableRunners.forEach((r) => {\n result.push(\n ...r.state.queries.filter((q) => {\n if (!q.datasource || !q.datasource.uid) {\n return true;\n }\n\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, q.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n })\n );\n });\n\n return result;\n}\n\n// Filters out inactive runner duplicates, keeping only the ones that are currently active.\n// This is needed for scnearios whan a query runner is cloned and the original is not removed but de-activated.\n// Can happen i.e. when editing a panel in Grafana Core dashboards.\nfunction filterOutInactiveRunnerDuplicates(runners: SceneQueryRunner[]) {\n // Group items by key\n const groupedItems: { [key: string]: SceneQueryRunner[] } = {};\n\n for (const item of runners) {\n if (item.state.key) {\n if (!(item.state.key in groupedItems)) {\n groupedItems[item.state.key] = [];\n }\n groupedItems[item.state.key].push(item);\n }\n }\n\n // Filter out inactive items and concatenate active items\n return Object.values(groupedItems).flatMap((group) => {\n const activeItems = group.filter((item) => item.isActive);\n // Keep inactive items if there's only one item with the key\n if (activeItems.length === 0 && group.length === 1) {\n return group;\n }\n return activeItems;\n });\n}\n\nexport function escapeUrlPipeDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the pipe due to using it as a filter separator\n return (value = /\\|/g[Symbol.replace](value, '__gfp__'));\n}\n\nexport function escapeUrlCommaDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the comma due to using it as a value/label separator\n return /,/g[Symbol.replace](value, '__gfc__');\n}\n\nexport function escapeUrlHashDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the hash due to using it as a value/label separator\n return /#/g[Symbol.replace](value, '__gfh__');\n}\n\nexport function escapeOriginFilterUrlDelimiters(value: string | undefined): string {\n return escapeUrlHashDelimiters(escapeUrlPipeDelimiters(value));\n}\n\nexport function escapeURLDelimiters(value: string | undefined): string {\n return escapeUrlCommaDelimiters(escapeUrlPipeDelimiters(value));\n}\n\nexport function unescapeUrlDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n value = /__gfp__/g[Symbol.replace](value, '|');\n value = /__gfc__/g[Symbol.replace](value, ',');\n value = /__gfh__/g[Symbol.replace](value, '#');\n\n return value;\n}\n\nexport function toUrlCommaDelimitedString(key: string, label?: string): string {\n // Omit for identical key/label or when label is not set at all\n if (!label || key === label) {\n return escapeUrlCommaDelimiters(key);\n }\n\n return [key, label].map(escapeUrlCommaDelimiters).join(',');\n}\n\nexport function dataFromResponse(response: GetTagResponse | MetricFindValue[]) {\n return Array.isArray(response) ? response : response.data;\n}\n\nexport function responseHasError(\n response: GetTagResponse | MetricFindValue[]\n): response is GetTagResponse & { error: DataQueryError } {\n return !Array.isArray(response) && Boolean(response.error);\n}\n\n// Collect a flat list of SelectableValues with a `group` property into a hierarchical list with groups\nexport function handleOptionGroups(values: SelectableValue[]): Array<SelectableValue<string>> {\n const result: Array<SelectableValue<string>> = [];\n const groupedResults = new Map<string, Array<SelectableValue<string>>>();\n\n for (const value of values) {\n const groupLabel = value.group;\n if (groupLabel) {\n let group = groupedResults.get(groupLabel);\n\n if (!group) {\n group = [];\n groupedResults.set(groupLabel, group);\n result.push({ label: groupLabel, options: group });\n }\n\n group.push(value);\n } else {\n result.push(value);\n }\n }\n\n return result;\n}\n\nexport function getNonApplicablePillStyles(theme: GrafanaTheme2) {\n return {\n disabledPill: css({\n background: theme.colors.action.selected,\n color: theme.colors.text.disabled,\n border: 0,\n '&:hover': {\n background: theme.colors.action.selected,\n },\n }),\n strikethrough: css({\n textDecoration: 'line-through',\n }),\n };\n}\n"],"names":["value","_a"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/variables/utils.ts"],"sourcesContent":["import { isEqual } from 'lodash';\nimport { VariableValue } from './types';\nimport {\n AdHocVariableFilter,\n DataQueryError,\n GetTagResponse,\n GrafanaTheme2,\n MetricFindValue,\n SelectableValue,\n} from '@grafana/data';\nimport { sceneGraph } from '../core/sceneGraph';\nimport { SceneDataQuery, SceneObject, SceneObjectState } from '../core/types';\nimport { SceneQueryRunner } from '../querying/SceneQueryRunner';\nimport { DataSourceRef, VariableType } from '@grafana/schema';\nimport { css } from '@emotion/css';\n\nexport function isVariableValueEqual(a: VariableValue | null | undefined, b: VariableValue | null | undefined) {\n if (a === b) {\n return true;\n }\n\n return isEqual(a, b);\n}\n\nexport function safeStringifyValue(value: unknown) {\n // Avoid circular references ignoring those references\n const getCircularReplacer = () => {\n const seen = new WeakSet();\n return (_: string, value: object | null) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return;\n }\n seen.add(value);\n }\n return value;\n };\n };\n\n try {\n return JSON.stringify(value, getCircularReplacer());\n } catch (error) {\n console.error(error);\n }\n\n return '';\n}\n\nexport function renderPrometheusLabelFilters(filters: AdHocVariableFilter[]) {\n return filters.map((filter) => renderFilter(filter)).join(',');\n}\n\nfunction renderFilter(filter: AdHocVariableFilter) {\n let value = '';\n let operator = filter.operator;\n\n // map \"one of\" operator to regex\n if (operator === '=|') {\n operator = '=~';\n // TODO remove when we're on the latest version of @grafana/data\n // @ts-expect-error\n value = filter.values?.map(escapeLabelValueInRegexSelector).join('|');\n } else if (operator === '!=|') {\n operator = '!~';\n // TODO remove when we're on the latest version of @grafana/data\n // @ts-expect-error\n value = filter.values?.map(escapeLabelValueInRegexSelector).join('|');\n } else if (operator === '=~' || operator === '!~') {\n value = escapeLabelValueInRegexSelector(filter.value);\n } else {\n value = escapeLabelValueInExactSelector(filter.value);\n }\n\n return `${filter.key}${operator}\"${value}\"`;\n}\n\n// based on the openmetrics-documentation, the 3 symbols we have to handle are:\n// - \\n ... the newline character\n// - \\ ... the backslash character\n// - \" ... the double-quote character\nexport function escapeLabelValueInExactSelector(labelValue: string): string {\n return labelValue.replace(/\\\\/g, '\\\\\\\\').replace(/\\n/g, '\\\\n').replace(/\"/g, '\\\\\"');\n}\n\nexport function escapeLabelValueInRegexSelector(labelValue: string): string {\n return escapeLabelValueInExactSelector(escapeLokiRegexp(labelValue));\n}\n\nexport function isRegexSelector(selector?: string) {\n if (selector && (selector.includes('=~') || selector.includes('!~'))) {\n return true;\n }\n return false;\n}\n\n// Loki regular-expressions use the RE2 syntax (https://github.com/google/re2/wiki/Syntax),\n// so every character that matches something in that list has to be escaped.\n// the list of meta characters is: *+?()|\\.[]{}^$\n// we make a javascript regular expression that matches those characters:\nconst RE2_METACHARACTERS = /[*+?()|\\\\.\\[\\]{}^$]/g;\nfunction escapeLokiRegexp(value: string): string {\n return value.replace(RE2_METACHARACTERS, '\\\\$&');\n}\n\n/**\n * Get all queries in the scene that have the same datasource as provided source object\n */\nexport function getQueriesForVariables(\n sourceObject: SceneObject<SceneObjectState & { datasource: DataSourceRef | null }>\n) {\n const runners = sceneGraph.findAllObjects(\n sourceObject.getRoot(),\n (o) => o instanceof SceneQueryRunner\n ) as SceneQueryRunner[];\n\n const interpolatedDsUuid = sceneGraph.interpolate(sourceObject, sourceObject.state.datasource?.uid);\n\n const applicableRunners = filterOutInactiveRunnerDuplicates(runners).filter((r) => {\n // First check if the runner's datasource matches\n if (r.state.datasource?.uid) {\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, r.state.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n }\n\n // If the runner has no datasource set, check if any of its queries have a matching datasource\n // This handles the case where panel-level datasource is not set but individual queries have datasources\n // (e.g., in v2 schema dashboards where non-mixed panels don't have panel.datasource)\n return r.state.queries.some((q) => {\n if (!q.datasource?.uid) {\n return false;\n }\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, q.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n });\n });\n\n if (applicableRunners.length === 0) {\n return [];\n }\n\n const result: SceneDataQuery[] = [];\n applicableRunners.forEach((r) => {\n result.push(\n ...r.state.queries.filter((q) => {\n if (!q.datasource || !q.datasource.uid) {\n return true;\n }\n\n const interpolatedQueryDsUuid = sceneGraph.interpolate(sourceObject, q.datasource.uid);\n return interpolatedQueryDsUuid === interpolatedDsUuid;\n })\n );\n });\n\n return result;\n}\n\n// Filters out inactive runner duplicates, keeping only the ones that are currently active.\n// This is needed for scnearios whan a query runner is cloned and the original is not removed but de-activated.\n// Can happen i.e. when editing a panel in Grafana Core dashboards.\nfunction filterOutInactiveRunnerDuplicates(runners: SceneQueryRunner[]) {\n // Group items by key\n const groupedItems: { [key: string]: SceneQueryRunner[] } = {};\n\n for (const item of runners) {\n if (item.state.key) {\n if (!(item.state.key in groupedItems)) {\n groupedItems[item.state.key] = [];\n }\n groupedItems[item.state.key].push(item);\n }\n }\n\n // Filter out inactive items and concatenate active items\n return Object.values(groupedItems).flatMap((group) => {\n const activeItems = group.filter((item) => item.isActive);\n // Keep inactive items if there's only one item with the key\n if (activeItems.length === 0 && group.length === 1) {\n return group;\n }\n return activeItems;\n });\n}\n\nexport function escapeUrlPipeDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the pipe due to using it as a filter separator\n return (value = /\\|/g[Symbol.replace](value, '__gfp__'));\n}\n\nexport function escapeUrlCommaDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the comma due to using it as a value/label separator\n return /,/g[Symbol.replace](value, '__gfc__');\n}\n\nexport function escapeUrlHashDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n // Replace the hash due to using it as a value/label separator\n return /#/g[Symbol.replace](value, '__gfh__');\n}\n\nexport function escapeOriginFilterUrlDelimiters(value: string | undefined): string {\n return escapeUrlHashDelimiters(escapeUrlPipeDelimiters(value));\n}\n\nexport function escapeURLDelimiters(value: string | undefined): string {\n return escapeUrlCommaDelimiters(escapeUrlPipeDelimiters(value));\n}\n\nexport function unescapeUrlDelimiters(value: string | undefined): string {\n if (value === null || value === undefined) {\n return '';\n }\n\n value = /__gfp__/g[Symbol.replace](value, '|');\n value = /__gfc__/g[Symbol.replace](value, ',');\n value = /__gfh__/g[Symbol.replace](value, '#');\n\n return value;\n}\n\nexport function toUrlCommaDelimitedString(key: string, label?: string): string {\n // Omit for identical key/label or when label is not set at all\n if (!label || key === label) {\n return escapeUrlCommaDelimiters(key);\n }\n\n return [key, label].map(escapeUrlCommaDelimiters).join(',');\n}\n\nexport function dataFromResponse(response: GetTagResponse | MetricFindValue[]) {\n return Array.isArray(response) ? response : response.data;\n}\n\nexport function responseHasError(\n response: GetTagResponse | MetricFindValue[]\n): response is GetTagResponse & { error: DataQueryError } {\n return !Array.isArray(response) && Boolean(response.error);\n}\n\n// Collect a flat list of SelectableValues with a `group` property into a hierarchical list with groups\nexport function handleOptionGroups(values: SelectableValue[]): Array<SelectableValue<string>> {\n const result: Array<SelectableValue<string>> = [];\n const groupedResults = new Map<string, Array<SelectableValue<string>>>();\n\n for (const value of values) {\n const groupLabel = value.group;\n if (groupLabel) {\n let group = groupedResults.get(groupLabel);\n\n if (!group) {\n group = [];\n groupedResults.set(groupLabel, group);\n result.push({ label: groupLabel, options: group });\n }\n\n group.push(value);\n } else {\n result.push(value);\n }\n }\n\n return result;\n}\n\nexport const getVariableControlId = (variableType: VariableType, key?: string) => {\n // TODO: remove this once switch is in the schema\n // @ts-expect-error - switch is a valid variable type, but not in the schema yet\n if (variableType === 'switch') {\n return `var-switch-${key}`;\n }\n return `var-${key}`;\n};\n\nexport function getNonApplicablePillStyles(theme: GrafanaTheme2) {\n return {\n disabledPill: css({\n background: theme.colors.action.selected,\n color: theme.colors.text.disabled,\n border: 0,\n '&:hover': {\n background: theme.colors.action.selected,\n },\n }),\n strikethrough: css({\n textDecoration: 'line-through',\n }),\n };\n}\n"],"names":["value","_a"],"mappings":"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"}
@@ -9,6 +9,7 @@ import { SceneObjectBase } from '../../core/SceneObjectBase.js';
9
9
  import { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig.js';
10
10
  import { AUTO_VARIABLE_TEXT, AUTO_VARIABLE_VALUE } from '../constants.js';
11
11
  import { SceneVariableValueChangedEvent } from '../types.js';
12
+ import { getVariableControlId } from '../utils.js';
12
13
 
13
14
  class IntervalVariable extends SceneObjectBase {
14
15
  constructor(initialState) {
@@ -92,6 +93,7 @@ IntervalVariable.Component = ({ model }) => {
92
93
  Select,
93
94
  {
94
95
  id: key,
96
+ inputId: getVariableControlId(model.state.type, key),
95
97
  placeholder: t("grafana-scenes.variables.interval-variable.placeholder-select-value", "Select value"),
96
98
  width: "auto",
97
99
  value,
@@ -1 +1 @@
1
- {"version":3,"file":"IntervalVariable.js","sources":["../../../../src/variables/variants/IntervalVariable.tsx"],"sourcesContent":["import { t } from '@grafana/i18n';\nimport { rangeUtil, SelectableValue } from '@grafana/data';\nimport { VariableRefresh } from '@grafana/schema';\nimport { Select } from '@grafana/ui';\nimport React from 'react';\nimport { Observable, of } from 'rxjs';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectUrlValues } from '../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig';\nimport { AUTO_VARIABLE_TEXT, AUTO_VARIABLE_VALUE } from '../constants';\nimport {\n SceneVariable,\n SceneVariableState,\n SceneVariableValueChangedEvent,\n ValidateAndUpdateResult,\n VariableValue,\n} from '../types';\n\nexport interface IntervalVariableState extends SceneVariableState {\n intervals: string[];\n value: string;\n autoEnabled: boolean;\n autoMinInterval: string;\n autoStepCount: number;\n refresh: VariableRefresh;\n}\n\nexport class IntervalVariable\n extends SceneObjectBase<IntervalVariableState>\n implements SceneVariable<IntervalVariableState>\n{\n public constructor(initialState: Partial<IntervalVariableState>) {\n super({\n type: 'interval',\n value: '',\n intervals: ['1m', '10m', '30m', '1h', '6h', '12h', '1d', '7d', '14d', '30d'],\n name: '',\n autoStepCount: 30,\n autoMinInterval: '10s',\n autoEnabled: false,\n refresh: VariableRefresh.onTimeRangeChanged,\n ...initialState,\n });\n\n this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: () => [this.getKey()] });\n }\n\n private getKey(): string {\n return `var-${this.state.name}`;\n }\n\n public getUrlState() {\n return { [this.getKey()]: this.state.value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const update: Partial<IntervalVariableState> = {};\n const val = values[this.getKey()];\n if (typeof val === 'string') {\n // support old auto interval url value\n if (val.startsWith('$__auto_interval_')) {\n update.value = AUTO_VARIABLE_VALUE;\n } else {\n update.value = val;\n }\n }\n this.setState(update);\n }\n\n public getOptionsForSelect(): Array<SelectableValue<string>> {\n const { value: currentValue, intervals, autoEnabled } = this.state;\n\n let options = intervals.map((interval) => ({ value: interval, label: interval }));\n\n if (autoEnabled) {\n options = [{ value: AUTO_VARIABLE_VALUE, label: AUTO_VARIABLE_TEXT }, ...options];\n }\n\n // If the current value is not in the list of intervals, add it to the list\n if (currentValue && !options.some((option) => option.value === currentValue)) {\n options.push({ value: currentValue, label: currentValue });\n }\n\n return options;\n }\n\n public getValue(): VariableValue {\n const { value, autoStepCount, autoMinInterval } = this.state;\n if (value === AUTO_VARIABLE_VALUE) {\n return this.getAutoRefreshInteval(autoStepCount, autoMinInterval);\n }\n\n return value;\n }\n\n private getAutoRefreshInteval(autoStepCount: number, minRefreshInterval: string) {\n const timeRange = sceneGraph.getTimeRange(this).state.value;\n const intervalObject = rangeUtil.calculateInterval(timeRange, autoStepCount, minRefreshInterval);\n return intervalObject.interval;\n }\n\n public _onChange = (value: SelectableValue<string>) => {\n this.setState({ value: value.value! });\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n };\n\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n const { value, intervals } = this.state;\n let shouldPublish = false;\n\n if (value === AUTO_VARIABLE_VALUE) {\n shouldPublish = true;\n } else if (!value && intervals.length > 0) {\n const firstOption = intervals[0];\n this.setState({ value: firstOption });\n shouldPublish = true;\n }\n\n if (shouldPublish) {\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n }\n\n return of({});\n }\n\n public static Component = ({ model }: SceneComponentProps<IntervalVariable>) => {\n const { key, value } = model.useState();\n return (\n <Select\n id={key}\n placeholder={t('grafana-scenes.variables.interval-variable.placeholder-select-value', 'Select value')}\n width=\"auto\"\n value={value}\n tabSelectsValue={false}\n options={model.getOptionsForSelect()}\n onChange={model._onChange}\n />\n );\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IntervalVariable.js","sources":["../../../../src/variables/variants/IntervalVariable.tsx"],"sourcesContent":["import { t } from '@grafana/i18n';\nimport { rangeUtil, SelectableValue } from '@grafana/data';\nimport { VariableRefresh } from '@grafana/schema';\nimport { Select } from '@grafana/ui';\nimport React from 'react';\nimport { Observable, of } from 'rxjs';\nimport { sceneGraph } from '../../core/sceneGraph';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectUrlValues } from '../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig';\nimport { AUTO_VARIABLE_TEXT, AUTO_VARIABLE_VALUE } from '../constants';\nimport {\n SceneVariable,\n SceneVariableState,\n SceneVariableValueChangedEvent,\n ValidateAndUpdateResult,\n VariableValue,\n} from '../types';\nimport { getVariableControlId } from '../utils';\n\nexport interface IntervalVariableState extends SceneVariableState {\n intervals: string[];\n value: string;\n autoEnabled: boolean;\n autoMinInterval: string;\n autoStepCount: number;\n refresh: VariableRefresh;\n}\n\nexport class IntervalVariable\n extends SceneObjectBase<IntervalVariableState>\n implements SceneVariable<IntervalVariableState>\n{\n public constructor(initialState: Partial<IntervalVariableState>) {\n super({\n type: 'interval',\n value: '',\n intervals: ['1m', '10m', '30m', '1h', '6h', '12h', '1d', '7d', '14d', '30d'],\n name: '',\n autoStepCount: 30,\n autoMinInterval: '10s',\n autoEnabled: false,\n refresh: VariableRefresh.onTimeRangeChanged,\n ...initialState,\n });\n\n this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: () => [this.getKey()] });\n }\n\n private getKey(): string {\n return `var-${this.state.name}`;\n }\n\n public getUrlState() {\n return { [this.getKey()]: this.state.value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n const update: Partial<IntervalVariableState> = {};\n const val = values[this.getKey()];\n if (typeof val === 'string') {\n // support old auto interval url value\n if (val.startsWith('$__auto_interval_')) {\n update.value = AUTO_VARIABLE_VALUE;\n } else {\n update.value = val;\n }\n }\n this.setState(update);\n }\n\n public getOptionsForSelect(): Array<SelectableValue<string>> {\n const { value: currentValue, intervals, autoEnabled } = this.state;\n\n let options = intervals.map((interval) => ({ value: interval, label: interval }));\n\n if (autoEnabled) {\n options = [{ value: AUTO_VARIABLE_VALUE, label: AUTO_VARIABLE_TEXT }, ...options];\n }\n\n // If the current value is not in the list of intervals, add it to the list\n if (currentValue && !options.some((option) => option.value === currentValue)) {\n options.push({ value: currentValue, label: currentValue });\n }\n\n return options;\n }\n\n public getValue(): VariableValue {\n const { value, autoStepCount, autoMinInterval } = this.state;\n if (value === AUTO_VARIABLE_VALUE) {\n return this.getAutoRefreshInteval(autoStepCount, autoMinInterval);\n }\n\n return value;\n }\n\n private getAutoRefreshInteval(autoStepCount: number, minRefreshInterval: string) {\n const timeRange = sceneGraph.getTimeRange(this).state.value;\n const intervalObject = rangeUtil.calculateInterval(timeRange, autoStepCount, minRefreshInterval);\n return intervalObject.interval;\n }\n\n public _onChange = (value: SelectableValue<string>) => {\n this.setState({ value: value.value! });\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n };\n\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n const { value, intervals } = this.state;\n let shouldPublish = false;\n\n if (value === AUTO_VARIABLE_VALUE) {\n shouldPublish = true;\n } else if (!value && intervals.length > 0) {\n const firstOption = intervals[0];\n this.setState({ value: firstOption });\n shouldPublish = true;\n }\n\n if (shouldPublish) {\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n }\n\n return of({});\n }\n\n public static Component = ({ model }: SceneComponentProps<IntervalVariable>) => {\n const { key, value } = model.useState();\n return (\n <Select\n id={key}\n inputId={getVariableControlId(model.state.type, key)}\n placeholder={t('grafana-scenes.variables.interval-variable.placeholder-select-value', 'Select value')}\n width=\"auto\"\n value={value}\n tabSelectsValue={false}\n options={model.getOptionsForSelect()}\n onChange={model._onChange}\n />\n );\n };\n}\n"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import { css } from '@emotion/css';
5
5
  import { SceneObjectBase } from '../../core/SceneObjectBase.js';
6
6
  import { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig.js';
7
7
  import { SceneVariableValueChangedEvent } from '../types.js';
8
+ import { getVariableControlId } from '../utils.js';
8
9
 
9
10
  class SwitchVariable extends SceneObjectBase {
10
11
  constructor(initialState) {
@@ -83,7 +84,7 @@ function SwitchVariableRenderer({ model }) {
83
84
  return /* @__PURE__ */ React.createElement("div", { className: styles.container }, /* @__PURE__ */ React.createElement(
84
85
  Switch,
85
86
  {
86
- id: `var-switch-${state.key}`,
87
+ id: getVariableControlId(model.state.type, state.key),
87
88
  value: state.value === state.enabledValue,
88
89
  onChange: (event) => {
89
90
  model.setValue(event.currentTarget.checked ? state.enabledValue : state.disabledValue);
@@ -1 +1 @@
1
- {"version":3,"file":"SwitchVariable.js","sources":["../../../../src/variables/variants/SwitchVariable.tsx"],"sourcesContent":["import React from 'react';\nimport { Observable, of } from 'rxjs';\nimport { Switch, useStyles2 } from '@grafana/ui';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { css } from '@emotion/css';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectUrlValues } from '../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig';\nimport {\n SceneVariable,\n SceneVariableState,\n SceneVariableValueChangedEvent,\n ValidateAndUpdateResult,\n VariableValue,\n} from '../types';\n\nexport interface SwitchVariableState extends SceneVariableState {\n value: string;\n enabledValue: string;\n disabledValue: string;\n}\n\nexport class SwitchVariable extends SceneObjectBase<SwitchVariableState> implements SceneVariable<SwitchVariableState> {\n public static Component = SwitchVariableRenderer;\n private _prevValue: VariableValue = '';\n\n public constructor(initialState: Partial<SwitchVariableState>) {\n super({\n // TODO: remove this once switch is in the schema @leventebalogh\n // @ts-expect-error - switch is a valid variable type, but not in the schema yet\n type: 'switch',\n value: 'false',\n enabledValue: 'true',\n disabledValue: 'false',\n name: '',\n ...initialState,\n });\n\n this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: () => this.getKeys() });\n }\n\n /**\n * This function is called on when SceneVariableSet is activated or when a dependency changes.\n */\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n const newValue = this.getValue();\n\n if (this._prevValue !== newValue) {\n this._prevValue = newValue;\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n }\n\n return of({});\n }\n\n public setValue(newValue: string): void {\n // Ignore if there's no change\n if (this.getValue() === newValue) {\n return;\n }\n\n if ([this.state.enabledValue, this.state.disabledValue].includes(newValue)) {\n this.setState({ value: newValue });\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n } else {\n console.error(\n `Invalid value for switch variable: \"${newValue}\". Valid values are: \"${this.state.enabledValue}\" and \"${this.state.disabledValue}\".`\n );\n }\n }\n\n public getValue(): VariableValue {\n return this.state.value;\n }\n\n public isEnabled(): boolean {\n return this.state.value === this.state.enabledValue;\n }\n\n public isDisabled(): boolean {\n return this.state.value === this.state.disabledValue;\n }\n\n private getKey(): string {\n return `var-${this.state.name}`;\n }\n\n public getKeys(): string[] {\n if (this.state.skipUrlSync) {\n return [];\n }\n\n return [this.getKey()];\n }\n\n public getUrlState(): SceneObjectUrlValues {\n if (this.state.skipUrlSync) {\n return {};\n }\n\n return { [this.getKey()]: this.state.value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues): void {\n const val = values[this.getKey()];\n\n if (typeof val === 'string') {\n this.setValue(val);\n }\n }\n}\n\nfunction SwitchVariableRenderer({ model }: SceneComponentProps<SwitchVariable>) {\n const state = model.useState();\n const styles = useStyles2(getStyles);\n\n return (\n <div className={styles.container}>\n <Switch\n id={`var-switch-${state.key}`}\n value={state.value === state.enabledValue}\n onChange={(event) => {\n model.setValue(event!.currentTarget.checked ? state.enabledValue : state.disabledValue);\n }}\n />\n </div>\n );\n}\n\nfunction getStyles(theme: GrafanaTheme2) {\n return {\n container: css({\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(0, 1),\n height: theme.spacing(theme.components.height.md),\n borderRadius: theme.shape.radius.default,\n border: `1px solid ${theme.components.input.borderColor}`,\n background: theme.colors.background.primary,\n }),\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SwitchVariable.js","sources":["../../../../src/variables/variants/SwitchVariable.tsx"],"sourcesContent":["import React from 'react';\nimport { Observable, of } from 'rxjs';\nimport { Switch, useStyles2 } from '@grafana/ui';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { css } from '@emotion/css';\nimport { SceneObjectBase } from '../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectUrlValues } from '../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../services/SceneObjectUrlSyncConfig';\nimport {\n SceneVariable,\n SceneVariableState,\n SceneVariableValueChangedEvent,\n ValidateAndUpdateResult,\n VariableValue,\n} from '../types';\nimport { getVariableControlId } from '../utils';\n\nexport interface SwitchVariableState extends SceneVariableState {\n value: string;\n enabledValue: string;\n disabledValue: string;\n}\n\nexport class SwitchVariable extends SceneObjectBase<SwitchVariableState> implements SceneVariable<SwitchVariableState> {\n public static Component = SwitchVariableRenderer;\n private _prevValue: VariableValue = '';\n\n public constructor(initialState: Partial<SwitchVariableState>) {\n super({\n // TODO: remove this once switch is in the schema @leventebalogh\n // @ts-expect-error - switch is a valid variable type, but not in the schema yet\n type: 'switch',\n value: 'false',\n enabledValue: 'true',\n disabledValue: 'false',\n name: '',\n ...initialState,\n });\n\n this._urlSync = new SceneObjectUrlSyncConfig(this, { keys: () => this.getKeys() });\n }\n\n /**\n * This function is called on when SceneVariableSet is activated or when a dependency changes.\n */\n public validateAndUpdate(): Observable<ValidateAndUpdateResult> {\n const newValue = this.getValue();\n\n if (this._prevValue !== newValue) {\n this._prevValue = newValue;\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n }\n\n return of({});\n }\n\n public setValue(newValue: string): void {\n // Ignore if there's no change\n if (this.getValue() === newValue) {\n return;\n }\n\n if ([this.state.enabledValue, this.state.disabledValue].includes(newValue)) {\n this.setState({ value: newValue });\n this.publishEvent(new SceneVariableValueChangedEvent(this), true);\n } else {\n console.error(\n `Invalid value for switch variable: \"${newValue}\". Valid values are: \"${this.state.enabledValue}\" and \"${this.state.disabledValue}\".`\n );\n }\n }\n\n public getValue(): VariableValue {\n return this.state.value;\n }\n\n public isEnabled(): boolean {\n return this.state.value === this.state.enabledValue;\n }\n\n public isDisabled(): boolean {\n return this.state.value === this.state.disabledValue;\n }\n\n private getKey(): string {\n return `var-${this.state.name}`;\n }\n\n public getKeys(): string[] {\n if (this.state.skipUrlSync) {\n return [];\n }\n\n return [this.getKey()];\n }\n\n public getUrlState(): SceneObjectUrlValues {\n if (this.state.skipUrlSync) {\n return {};\n }\n\n return { [this.getKey()]: this.state.value };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues): void {\n const val = values[this.getKey()];\n\n if (typeof val === 'string') {\n this.setValue(val);\n }\n }\n}\n\nfunction SwitchVariableRenderer({ model }: SceneComponentProps<SwitchVariable>) {\n const state = model.useState();\n const styles = useStyles2(getStyles);\n\n return (\n <div className={styles.container}>\n <Switch\n id={getVariableControlId(model.state.type, state.key)}\n value={state.value === state.enabledValue}\n onChange={(event) => {\n model.setValue(event!.currentTarget.checked ? state.enabledValue : state.disabledValue);\n }}\n />\n </div>\n );\n}\n\nfunction getStyles(theme: GrafanaTheme2) {\n return {\n container: css({\n display: 'flex',\n alignItems: 'center',\n padding: theme.spacing(0, 1),\n height: theme.spacing(theme.components.height.md),\n borderRadius: theme.shape.radius.default,\n border: `1px solid ${theme.components.input.borderColor}`,\n background: theme.colors.background.primary,\n }),\n };\n}\n"],"names":[],"mappings":";;;;;;;;;AAuBO,MAAM,uBAAuB,eAAmF,CAAA;AAAA,EAI9G,YAAY,YAA4C,EAAA;AAC7D,IAAM,KAAA,CAAA;AAAA;AAAA;AAAA,MAGJ,IAAM,EAAA,QAAA;AAAA,MACN,KAAO,EAAA,OAAA;AAAA,MACP,YAAc,EAAA,MAAA;AAAA,MACd,aAAe,EAAA,OAAA;AAAA,MACf,IAAM,EAAA,EAAA;AAAA,MACN,GAAG;AAAA,KACJ,CAAA;AAZH,IAAA,IAAA,CAAQ,UAA4B,GAAA,EAAA;AAclC,IAAK,IAAA,CAAA,QAAA,GAAW,IAAI,wBAAA,CAAyB,IAAM,EAAA,EAAE,MAAM,MAAM,IAAA,CAAK,OAAQ,EAAA,EAAG,CAAA;AAAA;AACnF;AAAA;AAAA;AAAA,EAKO,iBAAyD,GAAA;AAC9D,IAAM,MAAA,QAAA,GAAW,KAAK,QAAS,EAAA;AAE/B,IAAI,IAAA,IAAA,CAAK,eAAe,QAAU,EAAA;AAChC,MAAA,IAAA,CAAK,UAAa,GAAA,QAAA;AAClB,MAAA,IAAA,CAAK,YAAa,CAAA,IAAI,8BAA+B,CAAA,IAAI,GAAG,IAAI,CAAA;AAAA;AAGlE,IAAO,OAAA,EAAA,CAAG,EAAE,CAAA;AAAA;AACd,EAEO,SAAS,QAAwB,EAAA;AAEtC,IAAI,IAAA,IAAA,CAAK,QAAS,EAAA,KAAM,QAAU,EAAA;AAChC,MAAA;AAAA;AAGF,IAAI,IAAA,CAAC,IAAK,CAAA,KAAA,CAAM,YAAc,EAAA,IAAA,CAAK,MAAM,aAAa,CAAA,CAAE,QAAS,CAAA,QAAQ,CAAG,EAAA;AAC1E,MAAA,IAAA,CAAK,QAAS,CAAA,EAAE,KAAO,EAAA,QAAA,EAAU,CAAA;AACjC,MAAA,IAAA,CAAK,YAAa,CAAA,IAAI,8BAA+B,CAAA,IAAI,GAAG,IAAI,CAAA;AAAA,KAC3D,MAAA;AACL,MAAQ,OAAA,CAAA,KAAA;AAAA,QACN,CAAA,oCAAA,EAAuC,QAAQ,CAAyB,sBAAA,EAAA,IAAA,CAAK,MAAM,YAAY,CAAA,OAAA,EAAU,IAAK,CAAA,KAAA,CAAM,aAAa,CAAA,EAAA;AAAA,OACnI;AAAA;AACF;AACF,EAEO,QAA0B,GAAA;AAC/B,IAAA,OAAO,KAAK,KAAM,CAAA,KAAA;AAAA;AACpB,EAEO,SAAqB,GAAA;AAC1B,IAAA,OAAO,IAAK,CAAA,KAAA,CAAM,KAAU,KAAA,IAAA,CAAK,KAAM,CAAA,YAAA;AAAA;AACzC,EAEO,UAAsB,GAAA;AAC3B,IAAA,OAAO,IAAK,CAAA,KAAA,CAAM,KAAU,KAAA,IAAA,CAAK,KAAM,CAAA,aAAA;AAAA;AACzC,EAEQ,MAAiB,GAAA;AACvB,IAAO,OAAA,CAAA,IAAA,EAAO,IAAK,CAAA,KAAA,CAAM,IAAI,CAAA,CAAA;AAAA;AAC/B,EAEO,OAAoB,GAAA;AACzB,IAAI,IAAA,IAAA,CAAK,MAAM,WAAa,EAAA;AAC1B,MAAA,OAAO,EAAC;AAAA;AAGV,IAAO,OAAA,CAAC,IAAK,CAAA,MAAA,EAAQ,CAAA;AAAA;AACvB,EAEO,WAAoC,GAAA;AACzC,IAAI,IAAA,IAAA,CAAK,MAAM,WAAa,EAAA;AAC1B,MAAA,OAAO,EAAC;AAAA;AAGV,IAAO,OAAA,EAAE,CAAC,IAAK,CAAA,MAAA,EAAQ,GAAG,IAAA,CAAK,MAAM,KAAM,EAAA;AAAA;AAC7C,EAEO,cAAc,MAAoC,EAAA;AACvD,IAAA,MAAM,GAAM,GAAA,MAAA,CAAO,IAAK,CAAA,MAAA,EAAQ,CAAA;AAEhC,IAAI,IAAA,OAAO,QAAQ,QAAU,EAAA;AAC3B,MAAA,IAAA,CAAK,SAAS,GAAG,CAAA;AAAA;AACnB;AAEJ;AAxFa,cAAA,CACG,SAAY,GAAA,sBAAA;AAyF5B,SAAS,sBAAA,CAAuB,EAAE,KAAA,EAA8C,EAAA;AAC9E,EAAM,MAAA,KAAA,GAAQ,MAAM,QAAS,EAAA;AAC7B,EAAM,MAAA,MAAA,GAAS,WAAW,SAAS,CAAA;AAEnC,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,MAAA,CAAO,SACrB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAI,oBAAqB,CAAA,KAAA,CAAM,KAAM,CAAA,IAAA,EAAM,MAAM,GAAG,CAAA;AAAA,MACpD,KAAA,EAAO,KAAM,CAAA,KAAA,KAAU,KAAM,CAAA,YAAA;AAAA,MAC7B,QAAA,EAAU,CAAC,KAAU,KAAA;AACnB,QAAA,KAAA,CAAM,SAAS,KAAO,CAAA,aAAA,CAAc,UAAU,KAAM,CAAA,YAAA,GAAe,MAAM,aAAa,CAAA;AAAA;AACxF;AAAA,GAEJ,CAAA;AAEJ;AAEA,SAAS,UAAU,KAAsB,EAAA;AACvC,EAAO,OAAA;AAAA,IACL,WAAW,GAAI,CAAA;AAAA,MACb,OAAS,EAAA,MAAA;AAAA,MACT,UAAY,EAAA,QAAA;AAAA,MACZ,OAAS,EAAA,KAAA,CAAM,OAAQ,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,MAC3B,QAAQ,KAAM,CAAA,OAAA,CAAQ,KAAM,CAAA,UAAA,CAAW,OAAO,EAAE,CAAA;AAAA,MAChD,YAAA,EAAc,KAAM,CAAA,KAAA,CAAM,MAAO,CAAA,OAAA;AAAA,MACjC,MAAQ,EAAA,CAAA,UAAA,EAAa,KAAM,CAAA,UAAA,CAAW,MAAM,WAAW,CAAA,CAAA;AAAA,MACvD,UAAA,EAAY,KAAM,CAAA,MAAA,CAAO,UAAW,CAAA;AAAA,KACrC;AAAA,GACH;AACF;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import * as _grafana_data from '@grafana/data';
2
- import { BusEventWithPayload, EventBus, BusEvent, BusEventType, BusEventHandler, PanelMenuItem, DataQueryRequest, FieldConfigSource, PanelPlugin, AbsoluteTimeRange, PanelData, InterpolateFunction, PanelModel, TimeRange, DataTransformContext, DataFrame, DataSourceGetTagKeysOptions, DataSourceGetTagValuesOptions, IconName, PageLayoutType, UrlQueryMap, DataQuery as DataQuery$1, DataSourceApi, Registry, RegistryItem, ScopedVars, AdHocVariableFilter, SelectableValue, GetTagResponse, MetricFindValue, DrilldownsApplicability, VariableRegexApplyTo, VariableRefresh as VariableRefresh$1, VariableSort, Scope, EventFilterOptions, AnnotationEvent, AnnotationQuery, DataTransformerConfig, TimeOption, FieldConfig, FieldType, FieldValueMatcherConfig, ScopedVar, RawTimeRange } from '@grafana/data';
3
1
  import * as _grafana_schema from '@grafana/schema';
4
2
  import { VariableType, VariableHide, LoadingState, TimeZone, DataQuery, DataTopic, DataSourceRef, VariableRefresh, DashboardCursorSync, MatcherConfig, TableFieldOptions } from '@grafana/schema';
3
+ import * as _grafana_data from '@grafana/data';
4
+ import { BusEventWithPayload, EventBus, BusEvent, BusEventType, BusEventHandler, PanelMenuItem, DataQueryRequest, FieldConfigSource, PanelPlugin, AbsoluteTimeRange, PanelData, InterpolateFunction, PanelModel, TimeRange, DataTransformContext, DataFrame, DataSourceGetTagKeysOptions, DataSourceGetTagValuesOptions, IconName, PageLayoutType, UrlQueryMap, DataQuery as DataQuery$1, DataSourceApi, Registry, RegistryItem, ScopedVars, AdHocVariableFilter, SelectableValue, GetTagResponse, MetricFindValue, DrilldownsApplicability, VariableRegexApplyTo, VariableRefresh as VariableRefresh$1, VariableSort, Scope, EventFilterOptions, AnnotationEvent, AnnotationQuery, DataTransformerConfig, TimeOption, FieldConfig, FieldType, FieldValueMatcherConfig, ScopedVar, RawTimeRange } from '@grafana/data';
5
5
  import * as React$1 from 'react';
6
6
  import React__default, { ComponentType, CSSProperties, PointerEvent, ForwardRefExoticComponent } from 'react';
7
7
  import * as rxjs from 'rxjs';
@@ -2717,6 +2717,10 @@ interface AdHocFiltersController {
2717
2717
  * @param update - Partial filter properties to update
2718
2718
  */
2719
2719
  updateFilter(filter: AdHocFilterWithLabels, update: Partial<AdHocFilterWithLabels>): void;
2720
+ /**
2721
+ * Get id for the form control. Used for accessibility.
2722
+ */
2723
+ getControlId(): string;
2720
2724
  /**
2721
2725
  * Update filters list
2722
2726
  * @param filters
@@ -2812,6 +2816,7 @@ declare class AdHocFiltersVariableController implements AdHocFiltersController {
2812
2816
  startProfile(name: string): void;
2813
2817
  startInteraction(name: string): void;
2814
2818
  stopInteraction(): void;
2819
+ getControlId(): string;
2815
2820
  }
2816
2821
 
2817
2822
  interface Props$2 {
@@ -3826,6 +3831,7 @@ declare const sceneUtils: {
3826
3831
  escapeLabelValueInRegexSelector: typeof escapeLabelValueInRegexSelector;
3827
3832
  escapeLabelValueInExactSelector: typeof escapeLabelValueInExactSelector;
3828
3833
  escapeURLDelimiters: typeof escapeURLDelimiters;
3834
+ getVariableControlId: (variableType: _grafana_schema.VariableType, key?: string) => string;
3829
3835
  isAdHocVariable: typeof isAdHocVariable;
3830
3836
  isConstantVariable: typeof isConstantVariable;
3831
3837
  isCustomVariable: typeof isCustomVariable;
package/dist/index.js CHANGED
@@ -5564,6 +5564,7 @@ function VariableValueSelect({ model, state }) {
5564
5564
  ui.Select,
5565
5565
  {
5566
5566
  id: key,
5567
+ inputId: getVariableControlId(model.state.type, key),
5567
5568
  isValidNewOption: (inputValue2) => inputValue2.trim().length > 0,
5568
5569
  placeholder: i18n.t("grafana-scenes.variables.variable-value-select.placeholder-select-value", "Select value"),
5569
5570
  width: "auto",
@@ -5630,6 +5631,7 @@ function VariableValueSelectMulti({
5630
5631
  ui.MultiSelect,
5631
5632
  {
5632
5633
  id: key,
5634
+ inputId: getVariableControlId(model.state.type, key),
5633
5635
  placeholder,
5634
5636
  width: "auto",
5635
5637
  inputValue,
@@ -5903,7 +5905,7 @@ function AdHocFilterRenderer({ filter, model }) {
5903
5905
  model._removeFilter(filter);
5904
5906
  }
5905
5907
  },
5906
- openMenuOnFocus: true
5908
+ openMenuOnFocus: false
5907
5909
  }
5908
5910
  );
5909
5911
  const operatorSelect = /* @__PURE__ */ React__default.default.createElement(
@@ -7156,6 +7158,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
7156
7158
  {
7157
7159
  ...getReferenceProps({
7158
7160
  ref: refs.setReference,
7161
+ id: controller.getControlId(),
7159
7162
  onChange,
7160
7163
  value: inputValue,
7161
7164
  // dynamic placeholder to display operator and/or value in filter edit mode
@@ -7186,9 +7189,6 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
7186
7189
  event.stopPropagation();
7187
7190
  onInputClick == null ? void 0 : onInputClick();
7188
7191
  setOpen(true);
7189
- },
7190
- onFocus: () => {
7191
- setOpen(true);
7192
7192
  }
7193
7193
  }
7194
7194
  ), optionsLoading ? /* @__PURE__ */ React__default.default.createElement(ui.Spinner, { className: styles.loadingIndicator, inline: true }) : null, /* @__PURE__ */ React__default.default.createElement(react.FloatingPortal, null, open && /* @__PURE__ */ React__default.default.createElement(react.FloatingFocusManager, { context, initialFocus: -1, visuallyHiddenDismiss: true, modal: true }, /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
@@ -8305,6 +8305,7 @@ const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRen
8305
8305
  const adhocHiddenCount = shouldCollapse ? Math.max(0, adhocFilters.length - maxVisibleAdhocFilters) : 0;
8306
8306
  const groupByFiltersToRender = shouldCollapse ? groupByFilters.slice(0, MAX_VISIBLE_GROUP_BY) : groupByFilters;
8307
8307
  const groupByHiddenCount = shouldCollapse ? Math.max(0, groupByFilters.length - MAX_VISIBLE_GROUP_BY) : 0;
8308
+ const variableControlId = controller.getControlId();
8308
8309
  React.useEffect(() => {
8309
8310
  if (collapsible && totalFiltersCount === 0 && collapsed) {
8310
8311
  setCollapsed(false);
@@ -8322,6 +8323,17 @@ const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRen
8322
8323
  })
8323
8324
  },
8324
8325
  !readOnly && valueRecommendations && /* @__PURE__ */ React__default.default.createElement(valueRecommendations.Component, { model: valueRecommendations }),
8326
+ adhocFiltersToRender.length > 0 && // if there are filters already selected, this makes sure
8327
+ // that the input is announced before focussing on the pills
8328
+ /* @__PURE__ */ React__default.default.createElement(
8329
+ "span",
8330
+ {
8331
+ tabIndex: 0,
8332
+ "aria-labelledby": variableControlId,
8333
+ className: styles.screenReaderOnlyLabel,
8334
+ "data-testid": "AdHocFilter-label-announcer"
8335
+ }
8336
+ ),
8325
8337
  adhocFiltersToRender.map((filter, index) => /* @__PURE__ */ React__default.default.createElement(
8326
8338
  AdHocFilterPill,
8327
8339
  {
@@ -8529,6 +8541,17 @@ const getStyles$b = (theme) => ({
8529
8541
  "&:hover": {
8530
8542
  color: theme.colors.text.primary
8531
8543
  }
8544
+ }),
8545
+ screenReaderOnlyLabel: css.css({
8546
+ position: "absolute",
8547
+ width: "1px",
8548
+ height: "1px",
8549
+ padding: 0,
8550
+ margin: "-1px",
8551
+ overflow: "hidden",
8552
+ clip: "rect(0, 0, 0, 0)",
8553
+ whiteSpace: "nowrap",
8554
+ border: 0
8532
8555
  })
8533
8556
  });
8534
8557
 
@@ -8740,6 +8763,9 @@ class AdHocFiltersVariableController {
8740
8763
  const interactionTracker = getInteractionTracker(this.model);
8741
8764
  interactionTracker == null ? void 0 : interactionTracker.stopInteraction();
8742
8765
  }
8766
+ getControlId() {
8767
+ return getVariableControlId(this.model.state.type, this.model.state.key);
8768
+ }
8743
8769
  }
8744
8770
 
8745
8771
  const ORIGIN_FILTERS_KEY = "originFilters";
@@ -10365,6 +10391,7 @@ function GroupByVariableRenderer({ model }) {
10365
10391
  "grafana-scenes.variables.group-by-variable-renderer.aria-label-group-by-selector",
10366
10392
  "Group by selector"
10367
10393
  ),
10394
+ inputId: getVariableControlId(model.state.type, key),
10368
10395
  "data-testid": `GroupBySelect-${key}`,
10369
10396
  id: key,
10370
10397
  placeholder: i18n.t(
@@ -11219,6 +11246,12 @@ function handleOptionGroups(values) {
11219
11246
  }
11220
11247
  return result;
11221
11248
  }
11249
+ const getVariableControlId = (variableType, key) => {
11250
+ if (variableType === "switch") {
11251
+ return `var-switch-${key}`;
11252
+ }
11253
+ return `var-${key}`;
11254
+ };
11222
11255
  function getNonApplicablePillStyles(theme) {
11223
11256
  return {
11224
11257
  disabledPill: css.css({
@@ -12656,12 +12689,12 @@ function VariableValueSelectWrapper({ variable, layout, showAlways, hideLabel })
12656
12689
  return /* @__PURE__ */ React__default.default.createElement("div", { className: containerStyle, "data-testid": e2eSelectors.selectors.pages.Dashboard.SubMenu.submenuItem }, /* @__PURE__ */ React__default.default.createElement(VariableLabel, { variable, hideLabel }), /* @__PURE__ */ React__default.default.createElement(variable.Component, { model: variable }));
12657
12690
  }
12658
12691
  function VariableLabel({ variable, layout, hideLabel }) {
12659
- var _a;
12692
+ var _a, _b;
12660
12693
  const { state } = variable;
12661
12694
  if (variable.state.hide === data.VariableHide.hideLabel || hideLabel) {
12662
12695
  return null;
12663
12696
  }
12664
- const elementId = `var-${state.key}`;
12697
+ const elementId = getVariableControlId(variable.state.type, (_a = variable.state.key) != null ? _a : "");
12665
12698
  const labelOrName = state.label || state.name;
12666
12699
  return /* @__PURE__ */ React__default.default.createElement(
12667
12700
  ControlsLabel,
@@ -12675,7 +12708,7 @@ function VariableLabel({ variable, layout, hideLabel }) {
12675
12708
  label: labelOrName,
12676
12709
  error: state.error,
12677
12710
  layout,
12678
- description: (_a = state.description) != null ? _a : void 0
12711
+ description: (_b = state.description) != null ? _b : void 0
12679
12712
  }
12680
12713
  );
12681
12714
  }
@@ -13144,7 +13177,7 @@ function SwitchVariableRenderer({ model }) {
13144
13177
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, /* @__PURE__ */ React__default.default.createElement(
13145
13178
  ui.Switch,
13146
13179
  {
13147
- id: `var-switch-${state.key}`,
13180
+ id: getVariableControlId(model.state.type, state.key),
13148
13181
  value: state.value === state.enabledValue,
13149
13182
  onChange: (event) => {
13150
13183
  model.setValue(event.currentTarget.checked ? state.enabledValue : state.disabledValue);
@@ -13911,7 +13944,7 @@ function VariableValueInput({ model }) {
13911
13944
  return /* @__PURE__ */ React__default.default.createElement(
13912
13945
  ui.AutoSizeInput,
13913
13946
  {
13914
- id: key,
13947
+ id: getVariableControlId(model.state.type, key),
13915
13948
  placeholder: i18n.t("grafana-scenes.variables.variable-value-input.placeholder-enter-value", "Enter value"),
13916
13949
  minWidth: 15,
13917
13950
  maxWidth: 30,
@@ -14050,6 +14083,7 @@ IntervalVariable.Component = ({ model }) => {
14050
14083
  ui.Select,
14051
14084
  {
14052
14085
  id: key,
14086
+ inputId: getVariableControlId(model.state.type, key),
14053
14087
  placeholder: i18n.t("grafana-scenes.variables.interval-variable.placeholder-select-value", "Select value"),
14054
14088
  width: "auto",
14055
14089
  value,
@@ -17896,6 +17930,7 @@ const sceneUtils = {
17896
17930
  escapeLabelValueInRegexSelector,
17897
17931
  escapeLabelValueInExactSelector,
17898
17932
  escapeURLDelimiters,
17933
+ getVariableControlId,
17899
17934
  // Variable guards
17900
17935
  isAdHocVariable,
17901
17936
  isConstantVariable,