{"version":3,"file":"pluginExtensions.mjs","sources":["../../../src/types/pluginExtensions.ts"],"sourcesContent":["import * as React from 'react';\n\nimport { DataQuery, DataSourceJsonData } from '@grafana/schema';\n\nimport { ScopedVars } from './ScopedVars';\nimport { DataSourcePluginMeta, DataSourceSettings } from './datasource';\nimport { IconName } from './icon';\nimport { PanelData } from './panel';\nimport { AbsoluteTimeRange, RawTimeRange, TimeZone } from './time';\n\n// Plugin Extensions types\n// ---------------------------------------\n\nexport enum PluginExtensionTypes {\n  link = 'link',\n  component = 'component',\n  function = 'function',\n}\n\ntype PluginExtensionBase = {\n  id: string;\n  type: PluginExtensionTypes;\n  title: string;\n  description: string;\n  pluginId: string;\n};\nexport type PluginExtensionLink = PluginExtensionBase & {\n  type: PluginExtensionTypes.link;\n  path?: string;\n  onClick?: (event?: React.MouseEvent) => void;\n  icon?: IconName;\n  category?: string;\n  openInNewTab?: boolean;\n};\n\nexport type PluginExtensionComponentMeta = Omit<PluginExtensionComponent, 'component'>;\n\nexport type PluginExtensionComponent<Props = {}> = PluginExtensionBase & {\n  type: PluginExtensionTypes.component;\n  component: React.ComponentType<Props>;\n};\n\nexport type ComponentTypeWithExtensionMeta<Props = {}> = React.ComponentType<Props> & {\n  meta: PluginExtensionComponentMeta;\n};\n\nexport type PluginExtensionFunction<Signature = () => void> = PluginExtensionBase & {\n  type: PluginExtensionTypes.function;\n  fn: Signature;\n};\n\nexport type PluginExtension = PluginExtensionLink | PluginExtensionComponent | PluginExtensionFunction;\n\n// Objects used for registering extensions (in app plugins)\n// --------------------------------------------------------\n\ntype PluginExtensionConfigBase = {\n  /**\n   * The title of the link extension\n   */\n  title: string;\n\n  /**\n   * A short description\n   */\n  description?: string;\n};\n\nexport type PluginExtensionAddedComponentConfig<Props = {}> = PluginExtensionConfigBase & {\n  /**\n   * The target extension points where the component will be added\n   */\n  targets: string | string[];\n\n  /**\n   * The title of the component\n   */\n  title: string;\n\n  /**\n   * A short description of the component\n   */\n  description: string;\n\n  /**\n   * The React component that will added to the target extension points\n   */\n  component: React.ComponentType<Props>;\n};\n\nexport type PluginExtensionAddedFunctionConfig<Signature = unknown> = PluginExtensionConfigBase & {\n  /**\n   * The target extension points where the component will be added\n   */\n  targets: string | string[];\n\n  /**\n   * The function to be executed\n   */\n  fn: Signature;\n};\n\nexport type PluginAddedLinksConfigureFunc<Context extends object> = (context: Readonly<Context> | undefined) =>\n  | Partial<{\n      title: string;\n      description: string;\n      path: string;\n      onClick: (event: React.MouseEvent | undefined, helpers: PluginExtensionEventHelpers<Context>) => void;\n      icon: IconName;\n      category: string;\n      openInNewTab: boolean;\n    }>\n  | undefined;\n\nexport type PluginExtensionAddedLinkConfig<Context extends object = object> = PluginExtensionConfigBase & {\n  /**\n   * The target extension points where the link will be added\n   */\n  targets: string | string[];\n\n  /** A URL path that will be used as the href for the rendered link extension\n   * (It is optional, because in some cases the action will be handled by the `onClick` handler instead of navigating to a new page)\n   */\n  path?: string;\n\n  /** A URL path that will be used as the href for the rendered link extension\n   * (It is optional, because in some cases the action will be handled by the `onClick` handler instead of navigating to a new page)\n   * path?: string;\n   *\n   * A function that will be called when the link is clicked\n   *  (It is called with the original event object)\n   */\n  onClick?: (event: React.MouseEvent | undefined, helpers: PluginExtensionEventHelpers<Context>) => void;\n\n  // (Optional) A function that can be used to configure the extension dynamically based on the extension point's context\n  configure?: PluginAddedLinksConfigureFunc<Context>;\n\n  // (Optional) A icon that can be displayed in the ui for the extension option.\n  icon?: IconName;\n\n  // (Optional) A category to be used when grouping the options in the ui\n  category?: string;\n\n  // (Optional) If true, opens the link in a new tab (renders with target=\"_blank\")\n  // (Important: this is not guaranteed, depends on the extension point if it implements it.)\n  openInNewTab?: boolean;\n};\n\nexport type PluginExtensionExposedComponentConfig<Props = {}> = PluginExtensionConfigBase & {\n  /**\n   * The unique identifier of the component\n   * Shoud be in the format of `<pluginId>/<componentName>/<componentVersion>`. e.g. `myorg-todo-app/todo-list/v1`\n   */\n  id: string;\n\n  /**\n   * The React component that will be exposed to other plugins\n   */\n  component: React.ComponentType<Props>;\n};\n\nexport type PluginExtensionOpenModalOptions = {\n  // The title of the modal\n  title: string;\n  // A React element that will be rendered inside the modal\n  body: React.ElementType<{ onDismiss?: () => void }>;\n  // Width of the modal in pixels or percentage\n  width?: string | number;\n  // Height of the modal in pixels or percentage\n  height?: string | number;\n};\n\nexport type PluginExtensionEventHelpers<Context extends object = object> = {\n  context?: Readonly<Context>;\n  // The ID of the extension point that triggered this event\n  extensionPointId: string;\n  // Opens a modal dialog and renders the provided React component inside it\n  openModal: (options: PluginExtensionOpenModalOptions) => void;\n  /**\n   * @internal\n   * Opens the extension sidebar with the registered component.\n   * @param componentTitle The title of the component to be opened in the sidebar.\n   * @param props The props to be passed to the component.\n   */\n  openSidebar: (componentTitle: string, props?: Record<string, unknown>) => void;\n  /**\n   * @internal\n   * Closes the extension sidebar.\n   */\n  closeSidebar: () => void;\n  /**\n   * @internal\n   * Toggles the extension sidebar with the registered component.\n   * If the sidebar is open with the same component, it will be closed.\n   * If the sidebar is closed or open with a different component, it will be opened with the specified component.\n   * @param componentTitle The title of the component to be toggled in the sidebar.\n   * @param props The props to be passed to the component.\n   */\n  toggleSidebar: (componentTitle: string, props?: Record<string, unknown>) => void;\n};\n\n// Extension Points & Contexts\n// --------------------------------------------------------\n\n// Extension Points available in core Grafana\nexport enum PluginExtensionPoints {\n  AlertInstanceAction = 'grafana/alerting/instance/action',\n  AlertingHomePage = 'grafana/alerting/home',\n  AlertingAlertingRuleAction = 'grafana/alerting/alertingrule/action',\n  AlertingRecordingRuleAction = 'grafana/alerting/recordingrule/action',\n  AlertingRuleQueryEditor = 'grafana/alerting/alertingrule/queryeditor',\n  CommandPalette = 'grafana/commandpalette/action',\n  DashboardPanelMenu = 'grafana/dashboard/panel/menu',\n  DashboardEmpty = 'grafana/dashboard/empty',\n  DataSourceConfig = 'grafana/datasources/config',\n  DataSourceConfigActions = 'grafana/datasources/config/actions',\n  DataSourceConfigErrorStatus = 'grafana/datasources/config/error-status',\n  DataSourceConfigStatus = 'grafana/datasources/config/status',\n  ExploreToolbarAction = 'grafana/explore/toolbar/action',\n  UserProfileTab = 'grafana/user/profile/tab',\n  TraceViewDetails = 'grafana/traceview/details',\n  TraceViewHeaderActions = 'grafana/traceview/header/actions',\n  QueryEditorRowAdaptiveTelemetryV1 = 'grafana/query-editor-row/adaptivetelemetry/v1',\n  TraceViewResourceAttributes = 'grafana/traceview/resource-attributes',\n  LogsViewResourceAttributes = 'grafana/logsview/resource-attributes',\n  AppChrome = 'grafana/app/chrome/v1',\n  ExtensionSidebar = 'grafana/extension-sidebar/v0-alpha',\n  MegaMenuAction = 'grafana/megamenu/action',\n  SingleTopBarAction = 'grafana/singletopbar/action',\n}\n\n// Don't use directly in a plugin!\n// Extension point IDs that contain dynamic segments and are not valid as static values — they require runtime substitution of certain parts.\n// (They cannot be used as is. E.g. \"grafana/nav-landing-page/.*/v1\" becomes \"grafana/nav-landing-page/observability/v1\" during runtime.)\n//\n// IMPORTANT: NavLandingPage and NavLandingPageCards are mutually exclusive.\n// If a plugin extends NavLandingPage, it will replace the entire page content and any NavLandingPageCards extensions will be ignored.\n// Only use NavLandingPageCards if you want to add additional cards to the default landing page layout.\nexport enum PluginExtensionPointPatterns {\n  NavLandingPage = 'grafana/dynamic/nav-landing-page/nav-id-.*/v1',\n  NavLandingPageCards = 'grafana/dynamic/nav-landing-page/nav-id-.*/cards/v1',\n}\n\n// Extension Points available in plugins\nexport enum PluginExtensionExposedComponents {\n  CentralAlertHistorySceneV1 = 'grafana/central-alert-history-scene/v1',\n  AddToDashboardFormV1 = 'grafana/add-to-dashboard-form/v1',\n  PrometheusQueryResultsV1 = 'grafana/prometheus-query-results/v1',\n  CreateAlertFromPanelV1 = 'grafana/alerting/create-alert-from-panel/v1',\n  OpenQueryLibraryV1 = 'grafana/query-library-context/v1',\n}\n\nexport type PluginExtensionPanelContext = {\n  pluginId: string;\n  id: number;\n  title: string;\n  timeRange: RawTimeRange;\n  timeZone: TimeZone;\n  dashboard: Dashboard;\n  targets: DataQuery[];\n  scopedVars?: ScopedVars;\n  data?: PanelData;\n};\n\nexport type CentralAlertHistorySceneV1Props = {\n  defaultLabelsFilter?: string;\n  defaultTimeRange?: { from: string; to: string };\n  hideFilters?: boolean;\n  hideAlertRuleColumn?: boolean;\n};\n\nexport type PluginExtensionQueryEditorRowAdaptiveTelemetryV1Context = {\n  /** An ordered list of lower-case [a-z]+ string identifiers to provide context clues of where this component is being embedded and how we might want to consider displaying it */\n  contextHints?: string[];\n  query?: DataQuery & { expr?: string };\n};\n\nexport type PluginExtensionDataSourceConfigContext<\n  JsonData extends DataSourceJsonData = DataSourceJsonData,\n  SecureJsonData = {},\n> = {\n  // The current datasource settings\n  dataSource: DataSourceSettings<JsonData>;\n\n  // Meta information about the datasource plugin\n  dataSourceMeta: DataSourcePluginMeta;\n\n  // Testing status\n  testingStatus?: {\n    message?: string | null;\n    status?: string | null;\n  };\n\n  // Can be used to update the `jsonData` field on the datasource\n  // (Only updates the form, it still needs to be saved by the user)\n  setJsonData: (jsonData: JsonData) => void;\n  setSecureJsonData: (secureJsonData: SecureJsonData) => void;\n};\n\nexport type PluginExtensionCommandPaletteContext = {};\n\nexport type PluginExtensionResourceAttributesContext = {\n  // Key-value pairs of resource attributes, attribute name is the key\n  attributes: Record<string, string[]>;\n  spanAttributes?: Record<string, string[]>;\n  timeRange: AbsoluteTimeRange;\n  datasource: {\n    type: string;\n    uid: string;\n  };\n  traceID?: string;\n  spanID?: string;\n};\n\nexport type DataSourceConfigErrorStatusContext = {\n  dataSource: {\n    type: string;\n    uid: string;\n    name: string;\n  };\n  testingStatus: {\n    message?: string | null;\n    status?: string | null;\n    details?: Record<string, unknown>;\n  };\n};\n\nexport type PluginExtensionDataSourceConfigActionsContext = {\n  dataSource: {\n    type: string;\n    uid: string;\n    name: string;\n    typeName: string;\n  };\n};\n\nexport type PluginExtensionDataSourceConfigStatusContext = {\n  dataSource: {\n    type: string;\n    uid: string;\n    name: string;\n    typeName: string;\n  };\n  testingStatus?: {\n    message?: string | null;\n    status?: string | null;\n    details?: Record<string, unknown>;\n  };\n  severity: 'success' | 'error' | 'warning' | 'info';\n};\n\ntype Dashboard = {\n  uid: string;\n  title: string;\n  tags: string[];\n};\n"],"names":["PluginExtensionTypes","PluginExtensionPoints","PluginExtensionPointPatterns","PluginExtensionExposedComponents"],"mappings":";AAaO,IAAK,oBAAA,qBAAAA,qBAAAA,KAAL;AACL,EAAAA,sBAAA,MAAA,CAAA,GAAO,MAAA;AACP,EAAAA,sBAAA,WAAA,CAAA,GAAY,WAAA;AACZ,EAAAA,sBAAA,UAAA,CAAA,GAAW,UAAA;AAHD,EAAA,OAAAA,qBAAAA;AAAA,CAAA,EAAA,oBAAA,IAAA,EAAA;AAgML,IAAK,qBAAA,qBAAAC,sBAAAA,KAAL;AACL,EAAAA,uBAAA,qBAAA,CAAA,GAAsB,kCAAA;AACtB,EAAAA,uBAAA,kBAAA,CAAA,GAAmB,uBAAA;AACnB,EAAAA,uBAAA,4BAAA,CAAA,GAA6B,sCAAA;AAC7B,EAAAA,uBAAA,6BAAA,CAAA,GAA8B,uCAAA;AAC9B,EAAAA,uBAAA,yBAAA,CAAA,GAA0B,2CAAA;AAC1B,EAAAA,uBAAA,gBAAA,CAAA,GAAiB,+BAAA;AACjB,EAAAA,uBAAA,oBAAA,CAAA,GAAqB,8BAAA;AACrB,EAAAA,uBAAA,gBAAA,CAAA,GAAiB,yBAAA;AACjB,EAAAA,uBAAA,kBAAA,CAAA,GAAmB,4BAAA;AACnB,EAAAA,uBAAA,yBAAA,CAAA,GAA0B,oCAAA;AAC1B,EAAAA,uBAAA,6BAAA,CAAA,GAA8B,yCAAA;AAC9B,EAAAA,uBAAA,wBAAA,CAAA,GAAyB,mCAAA;AACzB,EAAAA,uBAAA,sBAAA,CAAA,GAAuB,gCAAA;AACvB,EAAAA,uBAAA,gBAAA,CAAA,GAAiB,0BAAA;AACjB,EAAAA,uBAAA,kBAAA,CAAA,GAAmB,2BAAA;AACnB,EAAAA,uBAAA,wBAAA,CAAA,GAAyB,kCAAA;AACzB,EAAAA,uBAAA,mCAAA,CAAA,GAAoC,+CAAA;AACpC,EAAAA,uBAAA,6BAAA,CAAA,GAA8B,uCAAA;AAC9B,EAAAA,uBAAA,4BAAA,CAAA,GAA6B,sCAAA;AAC7B,EAAAA,uBAAA,WAAA,CAAA,GAAY,uBAAA;AACZ,EAAAA,uBAAA,kBAAA,CAAA,GAAmB,oCAAA;AACnB,EAAAA,uBAAA,gBAAA,CAAA,GAAiB,yBAAA;AACjB,EAAAA,uBAAA,oBAAA,CAAA,GAAqB,6BAAA;AAvBX,EAAA,OAAAA,sBAAAA;AAAA,CAAA,EAAA,qBAAA,IAAA,EAAA;AAiCL,IAAK,4BAAA,qBAAAC,6BAAAA,KAAL;AACL,EAAAA,8BAAA,gBAAA,CAAA,GAAiB,+CAAA;AACjB,EAAAA,8BAAA,qBAAA,CAAA,GAAsB,qDAAA;AAFZ,EAAA,OAAAA,6BAAAA;AAAA,CAAA,EAAA,4BAAA,IAAA,EAAA;AAML,IAAK,gCAAA,qBAAAC,iCAAAA,KAAL;AACL,EAAAA,kCAAA,4BAAA,CAAA,GAA6B,wCAAA;AAC7B,EAAAA,kCAAA,sBAAA,CAAA,GAAuB,kCAAA;AACvB,EAAAA,kCAAA,0BAAA,CAAA,GAA2B,qCAAA;AAC3B,EAAAA,kCAAA,wBAAA,CAAA,GAAyB,6CAAA;AACzB,EAAAA,kCAAA,oBAAA,CAAA,GAAqB,kCAAA;AALX,EAAA,OAAAA,iCAAAA;AAAA,CAAA,EAAA,gCAAA,IAAA,EAAA;;;;"}