diff --git a/src/components/CodeEditor/declarations/customProperties.d.ts b/src/components/CodeEditor/declarations/customProperties.d.ts new file mode 100644 index 0000000..01710c8 --- /dev/null +++ b/src/components/CodeEditor/declarations/customProperties.d.ts @@ -0,0 +1,7 @@ +type JSONObject = { + [key in string]: JSONValue; +}; +type JSONValue = string | number | boolean | null | JSONObject | JSONValue[]; +type JSONType = JSONObject | JSONValue[]; + +export type CustomProperties = JSONType; diff --git a/src/components/CodeEditor/declarations/global.d.ts b/src/components/CodeEditor/declarations/global.d.ts index 8e197e8..a167f2d 100644 --- a/src/components/CodeEditor/declarations/global.d.ts +++ b/src/components/CodeEditor/declarations/global.d.ts @@ -12,7 +12,8 @@ import { getTemplateSrv as getTemplateSrvType, LocationService, } from '@grafana/runtime'; -import { HTMLNode, JSONType, OptionsInterface, PopulatedGetFieldDisplayValuesOptions } from './index'; +import { HTMLNode, OptionsInterface, PopulatedGetFieldDisplayValuesOptions } from './index'; +import type { CustomProperties } from './customProperties'; declare global { /** @@ -24,11 +25,11 @@ declare global { * * @deprecated in favor of {@link customProperties} */ - const codeData: JSONType; + const codeData: CustomProperties; /** * The parsed JSON object from the Custom properties option. */ - const customProperties: typeof codeData; + const customProperties: CustomProperties; /** * The PanelData interface passed into the panel by Grafana. */ diff --git a/src/components/CodeEditor/declarations/index.d.ts b/src/components/CodeEditor/declarations/index.d.ts index 87d6ae7..bc5cc9b 100644 --- a/src/components/CodeEditor/declarations/index.d.ts +++ b/src/components/CodeEditor/declarations/index.d.ts @@ -44,12 +44,6 @@ export interface HTMLNode extends ShadowRoot { onpanelwillunmount: () => void; } -export type JSONObject = { - [key in string]: JSONValue; -}; -export type JSONValue = string | number | boolean | null | JSONObject | JSONValue[]; -export type JSONType = JSONObject | JSONValue[]; - export interface PopulatedGetFieldDisplayValuesOptions { series?: GetFieldDisplayValuesOptions['data']; reduceOptions?: GetFieldDisplayValuesOptions['reduceOptions']; diff --git a/src/components/CodeEditor/index.tsx b/src/components/CodeEditor/index.tsx index eb66bcb..5ce8e21 100644 --- a/src/components/CodeEditor/index.tsx +++ b/src/components/CodeEditor/index.tsx @@ -12,8 +12,10 @@ interface Props { export const CodeEditor: FC = ({ settings, value, context, onChange }) => { const [declarations, setDeclarations] = useState>(); + const [monaco, setMonaco] = useState(); const editorDidMount = async (_: MonacoEditor, m: Monaco) => { + setMonaco(m); if (declarations) { // Add autocompletion for panel definitions (htmlNode, htmlGraphics, data, options, ETC) m.languages.typescript.javascriptDefaults.setExtraLibs(declarations); @@ -37,6 +39,27 @@ export const CodeEditor: FC = ({ settings, value, context, onChange }) => } }, [settings?.useHtmlGraphicsDeclarations]); + useEffect(() => { + if (!monaco || context.options?.codeData === undefined || !settings?.useHtmlGraphicsDeclarations === true) { + return; + } + + const createCustomPropertiesType = (json: string) => { + try { + return ( + `const customProperties = ${JSON.stringify(JSON.parse(json))} as const;\n` + + 'export type CustomProperties = typeof customProperties;' + ); + } catch (e) { + // If parsing fails the customProperties/codeData will be an empty object/dict + return 'export type CustomProperties = {};'; + } + }; + + const content = createCustomPropertiesType(context.options.codeData); + monaco.languages.typescript.javascriptDefaults.addExtraLib(content, 'customProperties.d.ts'); + }, [context, monaco, settings]); + return (
{!settings?.useHtmlGraphicsDeclarations || declarations ? (