@perses-dev/components 0.55.0-beta.8 → 0.55.0-rc.0

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 (108) hide show
  1. package/dist/DragAndDrop/DragAndDropList.d.ts +10 -2
  2. package/dist/DragAndDrop/DragAndDropList.d.ts.map +1 -1
  3. package/dist/DragAndDrop/DragAndDropList.js +6 -4
  4. package/dist/DragAndDrop/DragAndDropList.js.map +1 -1
  5. package/dist/EChart/EChart.d.ts +1 -1
  6. package/dist/EChart/EChart.d.ts.map +1 -1
  7. package/dist/EChart/EChart.js +12 -25
  8. package/dist/EChart/EChart.js.map +1 -1
  9. package/dist/ExemplarMetadata/ExemplarMetadataTooltip.d.ts +27 -0
  10. package/dist/ExemplarMetadata/ExemplarMetadataTooltip.d.ts.map +1 -0
  11. package/dist/ExemplarMetadata/ExemplarMetadataTooltip.js +239 -0
  12. package/dist/ExemplarMetadata/ExemplarMetadataTooltip.js.map +1 -0
  13. package/dist/ExemplarMetadata/index.d.ts +2 -0
  14. package/dist/ExemplarMetadata/index.d.ts.map +1 -0
  15. package/dist/{utils/component-ids.js → ExemplarMetadata/index.js} +2 -15
  16. package/dist/ExemplarMetadata/index.js.map +1 -0
  17. package/dist/FormatControls/FormatControls.d.ts.map +1 -1
  18. package/dist/FormatControls/FormatControls.js +42 -4
  19. package/dist/FormatControls/FormatControls.js.map +1 -1
  20. package/dist/FormatControls/UnitSelector.js +4 -4
  21. package/dist/FormatControls/UnitSelector.js.map +1 -1
  22. package/dist/Legend/TableLegend.d.ts.map +1 -1
  23. package/dist/Legend/TableLegend.js +2 -1
  24. package/dist/Legend/TableLegend.js.map +1 -1
  25. package/dist/LinksEditor/LinkEditorForm.d.ts +1 -0
  26. package/dist/LinksEditor/LinkEditorForm.d.ts.map +1 -1
  27. package/dist/LinksEditor/LinkEditorForm.js +1 -0
  28. package/dist/LinksEditor/LinkEditorForm.js.map +1 -1
  29. package/dist/OptionsEditorLayout/OptionsEditorControl.d.ts.map +1 -1
  30. package/dist/OptionsEditorLayout/OptionsEditorControl.js +2 -3
  31. package/dist/OptionsEditorLayout/OptionsEditorControl.js.map +1 -1
  32. package/dist/SettingsAutocomplete/SettingsAutocomplete.d.ts.map +1 -1
  33. package/dist/SettingsAutocomplete/SettingsAutocomplete.js +6 -3
  34. package/dist/SettingsAutocomplete/SettingsAutocomplete.js.map +1 -1
  35. package/dist/Table/Table.d.ts.map +1 -1
  36. package/dist/Table/Table.js +3 -0
  37. package/dist/Table/Table.js.map +1 -1
  38. package/dist/Table/TableToolbar.d.ts.map +1 -1
  39. package/dist/Table/TableToolbar.js +1 -0
  40. package/dist/Table/TableToolbar.js.map +1 -1
  41. package/dist/Table/VirtualizedTable.d.ts +1 -1
  42. package/dist/Table/VirtualizedTable.d.ts.map +1 -1
  43. package/dist/Table/VirtualizedTable.js +10 -19
  44. package/dist/Table/VirtualizedTable.js.map +1 -1
  45. package/dist/Table/model/table-model.d.ts +6 -2
  46. package/dist/Table/model/table-model.d.ts.map +1 -1
  47. package/dist/Table/model/table-model.js.map +1 -1
  48. package/dist/ThresholdsEditor/ThresholdsEditor.js +1 -3
  49. package/dist/ThresholdsEditor/ThresholdsEditor.js.map +1 -1
  50. package/dist/TimeRangeSelector/DateTimeRangePicker.js +1 -1
  51. package/dist/TimeRangeSelector/DateTimeRangePicker.js.map +1 -1
  52. package/dist/TimeRangeSelector/TimeRangeSelector.js +4 -4
  53. package/dist/TimeRangeSelector/TimeRangeSelector.js.map +1 -1
  54. package/dist/TimeSeriesTooltip/TimeChartTooltip.d.ts.map +1 -1
  55. package/dist/TimeSeriesTooltip/TimeChartTooltip.js +27 -16
  56. package/dist/TimeSeriesTooltip/TimeChartTooltip.js.map +1 -1
  57. package/dist/TimeSeriesTooltip/utils.d.ts.map +1 -1
  58. package/dist/TimeSeriesTooltip/utils.js +6 -2
  59. package/dist/TimeSeriesTooltip/utils.js.map +1 -1
  60. package/dist/TransformsEditor/TransformEditor.d.ts.map +1 -1
  61. package/dist/TransformsEditor/TransformEditor.js +89 -0
  62. package/dist/TransformsEditor/TransformEditor.js.map +1 -1
  63. package/dist/controls/TextField.d.ts.map +1 -1
  64. package/dist/controls/TextField.js +15 -10
  65. package/dist/controls/TextField.js.map +1 -1
  66. package/dist/index.d.ts +1 -0
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +1 -0
  69. package/dist/index.js.map +1 -1
  70. package/dist/model/custom.d.ts +22 -0
  71. package/dist/model/custom.d.ts.map +1 -0
  72. package/dist/model/custom.js +243 -0
  73. package/dist/model/custom.js.map +1 -0
  74. package/dist/model/index.d.ts +1 -0
  75. package/dist/model/index.d.ts.map +1 -1
  76. package/dist/model/index.js +1 -0
  77. package/dist/model/index.js.map +1 -1
  78. package/dist/model/transforms.d.ts +22 -1
  79. package/dist/model/transforms.d.ts.map +1 -1
  80. package/dist/model/transforms.js +2 -1
  81. package/dist/model/transforms.js.map +1 -1
  82. package/dist/model/units.d.ts +12 -10
  83. package/dist/model/units.d.ts.map +1 -1
  84. package/dist/model/units.js +33 -28
  85. package/dist/model/units.js.map +1 -1
  86. package/dist/utils/index.d.ts +0 -2
  87. package/dist/utils/index.d.ts.map +1 -1
  88. package/dist/utils/index.js +0 -2
  89. package/dist/utils/index.js.map +1 -1
  90. package/dist/utils/text.d.ts.map +1 -1
  91. package/dist/utils/text.js +14 -18
  92. package/dist/utils/text.js.map +1 -1
  93. package/dist/utils/transform-data.d.ts +5 -0
  94. package/dist/utils/transform-data.d.ts.map +1 -1
  95. package/dist/utils/transform-data.js +96 -0
  96. package/dist/utils/transform-data.js.map +1 -1
  97. package/dist/utils/variable-interpolation.d.ts +11 -0
  98. package/dist/utils/variable-interpolation.d.ts.map +1 -1
  99. package/dist/utils/variable-interpolation.js +64 -0
  100. package/dist/utils/variable-interpolation.js.map +1 -1
  101. package/package.json +3 -3
  102. package/dist/utils/component-ids.d.ts +0 -8
  103. package/dist/utils/component-ids.d.ts.map +0 -1
  104. package/dist/utils/component-ids.js.map +0 -1
  105. package/dist/utils/memo.d.ts +0 -13
  106. package/dist/utils/memo.d.ts.map +0 -1
  107. package/dist/utils/memo.js +0 -50
  108. package/dist/utils/memo.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import type { ReactElement, ReactNode } from 'react';
1
+ import type { ReactElement, ReactNode, RefObject } from 'react';
2
2
  interface MonitorElementsProps {
3
3
  elements: Array<Record<string, unknown>>;
4
4
  accessKey: string;
@@ -18,7 +18,15 @@ export declare function useDragAndDropMonitor({ elements, accessKey, axis, onCha
18
18
  export interface DragAndDropElementProps {
19
19
  children: ReactNode;
20
20
  data: Record<string, unknown>;
21
+ /**
22
+ * Ref of the element used as drag handle (e.g. a `DragButton`). When provided, the drag can only be started from
23
+ * this element. Otherwise, the drag can be started from anywhere in the element.
24
+ */
25
+ dragHandleRef?: RefObject<HTMLElement | null>;
21
26
  }
22
- export declare function DragAndDropElement({ children, data }: DragAndDropElementProps): ReactElement;
27
+ /**
28
+ * This component wraps the children that should be draggable.
29
+ */
30
+ export declare function DragAndDropElement({ children, data, dragHandleRef }: DragAndDropElementProps): ReactElement;
23
31
  export {};
24
32
  //# sourceMappingURL=DragAndDropList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DragAndDropList.d.ts","sourceRoot":"","sources":["../../src/DragAndDrop/DragAndDropList.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOrD,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,SAAS,EACT,IAAiB,EACjB,QAAQ,GACT,EAAE,oBAAoB,GAAG,IAAI,CAiC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAKD,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,uBAAuB,GAAG,YAAY,CA4E5F"}
1
+ {"version":3,"file":"DragAndDropList.d.ts","sourceRoot":"","sources":["../../src/DragAndDrop/DragAndDropList.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOhE,UAAU,oBAAoB;IAC5B,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,IAAI,CAAC;CAC9D;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,SAAS,EACT,IAAiB,EACjB,QAAQ,GACT,EAAE,oBAAoB,GAAG,IAAI,CAiC7B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;CAC/C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,uBAAuB,GAAG,YAAY,CA6E3G"}
@@ -59,9 +59,9 @@ import { idle } from "./model.js";
59
59
  onChange
60
60
  ]);
61
61
  }
62
- /*
63
- * This component wraps the children that should be draggable
64
- */ export function DragAndDropElement({ children, data }) {
62
+ /**
63
+ * This component wraps the children that should be draggable.
64
+ */ export function DragAndDropElement({ children, data, dragHandleRef }) {
65
65
  const ref = useRef(null);
66
66
  const [state, setState] = useState(idle);
67
67
  useEffect(()=>{
@@ -71,6 +71,7 @@ import { idle } from "./model.js";
71
71
  }
72
72
  return combine(draggable({
73
73
  element,
74
+ dragHandle: dragHandleRef?.current ?? undefined,
74
75
  getInitialData () {
75
76
  return data;
76
77
  },
@@ -134,7 +135,8 @@ import { idle } from "./model.js";
134
135
  }
135
136
  }));
136
137
  }, [
137
- data
138
+ data,
139
+ dragHandleRef
138
140
  ]);
139
141
  return /*#__PURE__*/ _jsxs(Stack, {
140
142
  ref: ref,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/DragAndDrop/DragAndDropList.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';\nimport { reorderWithEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge';\nimport { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';\nimport {\n monitorForElements,\n draggable,\n dropTargetForElements,\n} from '@atlaskit/pragmatic-drag-and-drop/element/adapter';\nimport { Stack } from '@mui/material';\nimport type { ReactElement, ReactNode } from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { DropIndicator } from './DropIndicator';\nimport type { State } from './model';\nimport { idle } from './model';\n\ninterface MonitorElementsProps {\n elements: Array<Record<string, unknown>>;\n accessKey: string;\n axis?: 'vertical' | 'horizontal';\n onChange: (elements: Array<Record<string, unknown>>) => void;\n}\n\n/**\n * This hook is responsible for monitoring the drag and drop of elements.\n * It will call the onChange function with the new order of elements when a drop is detected.\n *\n * @param elements - The list of elements to monitor\n * @param accessKey - The key to use to identify the elements (key of the object)\n * @param axis - The axis to monitor the drag and drop on\n * @param onChange - The function to call when a drop is detected\n */\nexport function useDragAndDropMonitor({\n elements,\n accessKey,\n axis = 'vertical',\n onChange,\n}: MonitorElementsProps): void {\n return useEffect(() => {\n return monitorForElements({\n onDrop({ location, source }) {\n const target = location.current.dropTargets[0];\n if (!target) {\n return;\n }\n\n const sourceData = source.data;\n const targetData = target.data;\n\n const indexOfSource = elements.findIndex((column) => column[accessKey] === sourceData[accessKey]);\n const indexOfTarget = elements.findIndex((column) => column[accessKey] === targetData[accessKey]);\n\n if (indexOfTarget < 0 || indexOfSource < 0) {\n return;\n }\n\n const closestEdgeOfTarget = extractClosestEdge(targetData);\n\n onChange(\n reorderWithEdge({\n list: elements,\n startIndex: indexOfSource,\n indexOfTarget,\n closestEdgeOfTarget,\n axis: axis,\n }),\n );\n },\n });\n }, [accessKey, axis, elements, onChange]);\n}\n\nexport interface DragAndDropElementProps {\n children: ReactNode;\n data: Record<string, unknown>;\n}\n\n/*\n * This component wraps the children that should be draggable\n */\nexport function DragAndDropElement({ children, data }: DragAndDropElementProps): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const [state, setState] = useState<State>(idle);\n\n useEffect(() => {\n const element = ref.current;\n if (!element) {\n return;\n }\n\n return combine(\n draggable({\n element,\n getInitialData() {\n return data;\n },\n onDragStart() {\n setState({ type: 'is-dragging' });\n },\n onDrop() {\n setState(idle);\n },\n }),\n dropTargetForElements({\n element,\n canDrop({ source }) {\n // not allowing dropping on yourself\n if (source.element === element) {\n return false;\n }\n // only allowing tasks to be dropped on me\n return true;\n },\n getData({ input }) {\n return attachClosestEdge(data, {\n element,\n input,\n allowedEdges: ['top', 'bottom'],\n });\n },\n getIsSticky() {\n return true;\n },\n onDragEnter({ self }) {\n const closestEdge = extractClosestEdge(self.data);\n setState({ type: 'is-dragging-over', closestEdge });\n },\n onDrag({ self }) {\n const closestEdge = extractClosestEdge(self.data);\n\n // Only need to update react state if nothing has changed.\n // Prevents re-rendering.\n setState((current) => {\n if (current.type === 'is-dragging-over' && current.closestEdge === closestEdge) {\n return current;\n }\n return { type: 'is-dragging-over', closestEdge };\n });\n },\n onDragLeave() {\n setState(idle);\n },\n onDrop() {\n setState(idle);\n },\n }),\n );\n }, [data]);\n\n return (\n <Stack ref={ref} spacing={1} style={{ opacity: state.type === 'is-dragging' ? 0.5 : 'unset' }}>\n {state.type === 'is-dragging-over' && state.closestEdge === 'top' ? <DropIndicator /> : null}\n {children}\n {state.type === 'is-dragging-over' && state.closestEdge === 'bottom' ? <DropIndicator /> : null}\n </Stack>\n );\n}\n"],"names":["attachClosestEdge","extractClosestEdge","reorderWithEdge","combine","monitorForElements","draggable","dropTargetForElements","Stack","useEffect","useRef","useState","DropIndicator","idle","useDragAndDropMonitor","elements","accessKey","axis","onChange","onDrop","location","source","target","current","dropTargets","sourceData","data","targetData","indexOfSource","findIndex","column","indexOfTarget","closestEdgeOfTarget","list","startIndex","DragAndDropElement","children","ref","state","setState","element","getInitialData","onDragStart","type","canDrop","getData","input","allowedEdges","getIsSticky","onDragEnter","self","closestEdge","onDrag","onDragLeave","spacing","style","opacity"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/DragAndDrop/DragAndDropList.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';\nimport { reorderWithEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/util/reorder-with-edge';\nimport { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';\nimport {\n monitorForElements,\n draggable,\n dropTargetForElements,\n} from '@atlaskit/pragmatic-drag-and-drop/element/adapter';\nimport { Stack } from '@mui/material';\nimport type { ReactElement, ReactNode, RefObject } from 'react';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { DropIndicator } from './DropIndicator';\nimport type { State } from './model';\nimport { idle } from './model';\n\ninterface MonitorElementsProps {\n elements: Array<Record<string, unknown>>;\n accessKey: string;\n axis?: 'vertical' | 'horizontal';\n onChange: (elements: Array<Record<string, unknown>>) => void;\n}\n\n/**\n * This hook is responsible for monitoring the drag and drop of elements.\n * It will call the onChange function with the new order of elements when a drop is detected.\n *\n * @param elements - The list of elements to monitor\n * @param accessKey - The key to use to identify the elements (key of the object)\n * @param axis - The axis to monitor the drag and drop on\n * @param onChange - The function to call when a drop is detected\n */\nexport function useDragAndDropMonitor({\n elements,\n accessKey,\n axis = 'vertical',\n onChange,\n}: MonitorElementsProps): void {\n return useEffect(() => {\n return monitorForElements({\n onDrop({ location, source }) {\n const target = location.current.dropTargets[0];\n if (!target) {\n return;\n }\n\n const sourceData = source.data;\n const targetData = target.data;\n\n const indexOfSource = elements.findIndex((column) => column[accessKey] === sourceData[accessKey]);\n const indexOfTarget = elements.findIndex((column) => column[accessKey] === targetData[accessKey]);\n\n if (indexOfTarget < 0 || indexOfSource < 0) {\n return;\n }\n\n const closestEdgeOfTarget = extractClosestEdge(targetData);\n\n onChange(\n reorderWithEdge({\n list: elements,\n startIndex: indexOfSource,\n indexOfTarget,\n closestEdgeOfTarget,\n axis: axis,\n }),\n );\n },\n });\n }, [accessKey, axis, elements, onChange]);\n}\n\nexport interface DragAndDropElementProps {\n children: ReactNode;\n data: Record<string, unknown>;\n /**\n * Ref of the element used as drag handle (e.g. a `DragButton`). When provided, the drag can only be started from\n * this element. Otherwise, the drag can be started from anywhere in the element.\n */\n dragHandleRef?: RefObject<HTMLElement | null>;\n}\n\n/**\n * This component wraps the children that should be draggable.\n */\nexport function DragAndDropElement({ children, data, dragHandleRef }: DragAndDropElementProps): ReactElement {\n const ref = useRef<HTMLDivElement>(null);\n const [state, setState] = useState<State>(idle);\n\n useEffect(() => {\n const element = ref.current;\n if (!element) {\n return;\n }\n\n return combine(\n draggable({\n element,\n dragHandle: dragHandleRef?.current ?? undefined,\n getInitialData() {\n return data;\n },\n onDragStart() {\n setState({ type: 'is-dragging' });\n },\n onDrop() {\n setState(idle);\n },\n }),\n dropTargetForElements({\n element,\n canDrop({ source }) {\n // not allowing dropping on yourself\n if (source.element === element) {\n return false;\n }\n // only allowing tasks to be dropped on me\n return true;\n },\n getData({ input }) {\n return attachClosestEdge(data, {\n element,\n input,\n allowedEdges: ['top', 'bottom'],\n });\n },\n getIsSticky() {\n return true;\n },\n onDragEnter({ self }) {\n const closestEdge = extractClosestEdge(self.data);\n setState({ type: 'is-dragging-over', closestEdge });\n },\n onDrag({ self }) {\n const closestEdge = extractClosestEdge(self.data);\n\n // Only need to update react state if nothing has changed.\n // Prevents re-rendering.\n setState((current) => {\n if (current.type === 'is-dragging-over' && current.closestEdge === closestEdge) {\n return current;\n }\n return { type: 'is-dragging-over', closestEdge };\n });\n },\n onDragLeave() {\n setState(idle);\n },\n onDrop() {\n setState(idle);\n },\n }),\n );\n }, [data, dragHandleRef]);\n\n return (\n <Stack ref={ref} spacing={1} style={{ opacity: state.type === 'is-dragging' ? 0.5 : 'unset' }}>\n {state.type === 'is-dragging-over' && state.closestEdge === 'top' ? <DropIndicator /> : null}\n {children}\n {state.type === 'is-dragging-over' && state.closestEdge === 'bottom' ? <DropIndicator /> : null}\n </Stack>\n );\n}\n"],"names":["attachClosestEdge","extractClosestEdge","reorderWithEdge","combine","monitorForElements","draggable","dropTargetForElements","Stack","useEffect","useRef","useState","DropIndicator","idle","useDragAndDropMonitor","elements","accessKey","axis","onChange","onDrop","location","source","target","current","dropTargets","sourceData","data","targetData","indexOfSource","findIndex","column","indexOfTarget","closestEdgeOfTarget","list","startIndex","DragAndDropElement","children","dragHandleRef","ref","state","setState","element","dragHandle","undefined","getInitialData","onDragStart","type","canDrop","getData","input","allowedEdges","getIsSticky","onDragEnter","self","closestEdge","onDrag","onDragLeave","spacing","style","opacity"],"mappings":"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"}
@@ -58,6 +58,6 @@ export interface EChartsProps<T> {
58
58
  syncGroup?: string;
59
59
  onChartInitialized?: (instance: ECharts) => void;
60
60
  }
61
- export declare const EChart: import("react").MemoExoticComponent<<T>({ option, theme, renderer, sx, style, onEvents, _instance, syncGroup, onChartInitialized, }: EChartsProps<T>) => import("react/jsx-runtime").JSX.Element>;
61
+ export declare const EChart: import("react").MemoExoticComponent<<T>({ option, theme, renderer, sx, style, onEvents, _instance: instanceRef, syncGroup, onChartInitialized, }: EChartsProps<T>) => import("react/jsx-runtime").JSX.Element>;
62
62
  export {};
63
63
  //# sourceMappingURL=EChart.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EChart.d.ts","sourceRoot":"","sources":["../../src/EChart/EChart.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EChart.d.ts","sourceRoot":"","sources":["../../src/EChart/EChart.tsx"],"names":[],"mappings":"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"}
@@ -58,7 +58,7 @@ const batchEvents = [
58
58
  'downplay',
59
59
  'highlight'
60
60
  ];
61
- export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, renderer, sx, style, onEvents, _instance, syncGroup, onChartInitialized }) {
61
+ export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, renderer, sx, style, onEvents, _instance: instanceRef, syncGroup, onChartInitialized }) {
62
62
  const initialOption = useRef(option);
63
63
  const prevOption = useRef(option);
64
64
  const containerRef = useRef(null);
@@ -72,8 +72,8 @@ export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, render
72
72
  if (chartElement.current === undefined) return;
73
73
  chartElement.current.setOption(initialOption.current, true);
74
74
  onChartInitialized?.(chartElement.current);
75
- if (_instance !== undefined) {
76
- _instance.current = chartElement.current;
75
+ if (instanceRef !== undefined) {
76
+ instanceRef.current = chartElement.current;
77
77
  }
78
78
  return ()=>{
79
79
  if (chartElement.current === null) return;
@@ -81,7 +81,7 @@ export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, render
81
81
  chartElement.current = null;
82
82
  };
83
83
  }, [
84
- _instance,
84
+ instanceRef,
85
85
  onChartInitialized,
86
86
  theme,
87
87
  renderer
@@ -106,16 +106,21 @@ export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, render
106
106
  }, [
107
107
  option
108
108
  ]);
109
- // Resize chart, cleanup listener on unmount
109
+ // Observe actual container size, including layout and style changes.
110
110
  useLayoutEffect(()=>{
111
+ const container = containerRef.current;
112
+ if (!container) return;
111
113
  const updateSize = debounce(()=>{
112
- if (!chartElement.current) return;
113
- chartElement.current.resize();
114
+ chartElement.current?.resize();
114
115
  }, 200);
116
+ const observer = new ResizeObserver(updateSize);
117
+ observer.observe(container);
115
118
  window.addEventListener('resize', updateSize);
116
119
  updateSize();
117
120
  return ()=>{
121
+ observer.disconnect();
118
122
  window.removeEventListener('resize', updateSize);
123
+ updateSize.cancel();
119
124
  };
120
125
  }, []);
121
126
  // Bind and unbind chart events passed as prop
@@ -133,24 +138,6 @@ export const EChart = /*#__PURE__*/ memo(function EChart({ option, theme, render
133
138
  }, [
134
139
  onEvents
135
140
  ]);
136
- // TODO: re-evaluate how this is triggered. It's technically working right
137
- // now because the sx prop is an object that gets re-created, but that also
138
- // means it runs unnecessarily some of the time and theoretically might
139
- // not run in some other cases. Maybe it should use a resize observer?
140
- useEffect(()=>{
141
- // TODO: fix this debouncing. This likely isn't working as intended because
142
- // the debounced function is re-created every time this useEffect is called.
143
- const updateSize = debounce(()=>{
144
- if (!chartElement.current) return;
145
- chartElement.current.resize();
146
- }, 200, {
147
- leading: true
148
- });
149
- updateSize();
150
- }, [
151
- sx,
152
- style
153
- ]);
154
141
  return /*#__PURE__*/ _jsx(Box, {
155
142
  ref: containerRef,
156
143
  sx: sx,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/EChart/EChart.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { SxProps, Theme } from '@mui/material';\nimport { Box } from '@mui/material';\nimport {\n BarChart as EChartsBarChart,\n LineChart as EChartsLineChart,\n GaugeChart as EChartsGaugeChart,\n PieChart as EChartsPieChart,\n ScatterChart as EChartsScatterChart,\n CustomChart as EChartsCustomChart,\n HeatmapChart as EChartsHeatmapChart,\n} from 'echarts/charts';\nimport {\n DatasetComponent,\n DataZoomComponent,\n LegendComponent,\n GridComponent,\n TitleComponent,\n TooltipComponent,\n VisualMapComponent,\n ToolboxComponent,\n MarkPointComponent,\n MarkAreaComponent,\n MarkLineComponent,\n} from 'echarts/components';\nimport type { ECharts, EChartsCoreOption } from 'echarts/core';\nimport { init, connect, use as registerEChartsComponents } from 'echarts/core';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport debounce from 'lodash/debounce';\nimport isEqual from 'lodash/isEqual';\nimport type { CSSProperties } from 'react';\nimport { memo, useEffect, useLayoutEffect, useRef } from 'react';\n\nimport type { EChartsTheme } from '../model';\n\n// Loading the ECharts extensions should happen in the respective plugins.\n// This is a workaround for https://github.com/perses/plugins/issues/83.\nregisterEChartsComponents([\n DatasetComponent,\n DataZoomComponent,\n LegendComponent,\n EChartsBarChart,\n EChartsLineChart,\n EChartsGaugeChart,\n EChartsPieChart,\n EChartsScatterChart,\n EChartsCustomChart,\n EChartsHeatmapChart,\n GridComponent,\n TitleComponent,\n ToolboxComponent,\n TooltipComponent,\n CanvasRenderer,\n VisualMapComponent,\n MarkAreaComponent,\n MarkLineComponent,\n MarkPointComponent,\n]);\n\n// see docs for info about each property: https://echarts.apache.org/en/api.html#events\nexport interface MouseEventsParameters<T> {\n componentType: string;\n seriesType: string;\n seriesIndex: number;\n seriesName: string;\n name: string;\n dataIndex: number;\n data: Record<string, unknown> & T;\n dataType: string;\n value: number | number[];\n color: string;\n info: Record<string, unknown>;\n}\n\ntype OnEventFunction<T> = (\n params: MouseEventsParameters<T>,\n // This is potentially undefined for testing purposes\n instance?: ECharts,\n) => void;\n\nconst mouseEvents = [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'mouseover',\n 'mouseout',\n 'globalout',\n 'contextmenu',\n] as const;\n\nexport type MouseEventName = (typeof mouseEvents)[number];\n\n// batch event types\nexport interface DataZoomPayloadBatchItem {\n dataZoomId: string;\n // start and end not returned unless dataZoom is based on percentProp,\n // which is for cases when a dataZoom component controls multiple axes\n start?: number;\n end?: number;\n // startValue and endValue return data index for 'category' axes,\n // for axis types 'value' and 'time', actual values are returned\n startValue?: number;\n endValue?: number;\n}\n\nexport interface HighlightPayloadBatchItem {\n dataIndex: number;\n dataIndexInside: number;\n seriesIndex: number;\n // highlight action can effect multiple connected charts\n escapeConnect?: boolean;\n // whether blur state was triggered\n notBlur?: boolean;\n}\n\nexport interface BatchEventsParameters {\n type: BatchEventName;\n batch: DataZoomPayloadBatchItem[] & HighlightPayloadBatchItem[];\n}\n\ntype OnBatchEventFunction = (params: BatchEventsParameters) => void;\n\nconst batchEvents = ['datazoom', 'downplay', 'highlight'] as const;\n\nexport type BatchEventName = (typeof batchEvents)[number];\n\ntype ChartEventName = 'finished';\n\ntype EventName = MouseEventName | ChartEventName | BatchEventName;\n\nexport type OnEventsType<T> = {\n [mouseEventName in MouseEventName]?: OnEventFunction<T>;\n} & {\n [batchEventName in BatchEventName]?: OnBatchEventFunction;\n} & {\n [eventName in ChartEventName]?: () => void;\n};\n\nexport interface EChartsProps<T> {\n option: EChartsCoreOption;\n theme?: string | EChartsTheme;\n renderer?: 'canvas' | 'svg';\n sx?: SxProps<Theme>;\n style?: CSSProperties;\n onEvents?: OnEventsType<T>;\n _instance?: React.MutableRefObject<ECharts | undefined>;\n syncGroup?: string;\n onChartInitialized?: (instance: ECharts) => void;\n}\n\nexport const EChart = memo(function EChart<T>({\n option,\n theme,\n renderer,\n sx,\n style,\n onEvents,\n _instance,\n syncGroup,\n onChartInitialized,\n}: EChartsProps<T>) {\n const initialOption = useRef<EChartsCoreOption>(option);\n const prevOption = useRef<EChartsCoreOption>(option);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const chartElement = useRef<ECharts | null>(null);\n\n // Initialize chart, dispose on unmount\n useLayoutEffect(() => {\n if (containerRef.current === null || chartElement.current !== null) return;\n chartElement.current = init(containerRef.current, theme, { renderer: renderer ?? 'canvas' });\n if (chartElement.current === undefined) return;\n chartElement.current.setOption(initialOption.current, true);\n onChartInitialized?.(chartElement.current);\n if (_instance !== undefined) {\n _instance.current = chartElement.current;\n }\n return (): void => {\n if (chartElement.current === null) return;\n chartElement.current.dispose();\n chartElement.current = null;\n };\n }, [_instance, onChartInitialized, theme, renderer]);\n\n // When syncGroup is explicitly set, charts within same group share interactions such as crosshair\n useEffect(() => {\n if (!chartElement.current || !syncGroup) return;\n chartElement.current.group = syncGroup;\n connect([chartElement.current]); // more info: https://echarts.apache.org/en/api.html#echarts.connect\n }, [syncGroup, chartElement]);\n\n // Update chart data when option changes\n useEffect(() => {\n if (prevOption.current === undefined || isEqual(prevOption.current, option)) return;\n if (!chartElement.current) return;\n chartElement.current.setOption(option, true);\n prevOption.current = option;\n }, [option]);\n\n // Resize chart, cleanup listener on unmount\n useLayoutEffect(() => {\n const updateSize = debounce(() => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n }, 200);\n window.addEventListener('resize', updateSize);\n updateSize();\n return (): void => {\n window.removeEventListener('resize', updateSize);\n };\n }, []);\n\n // Bind and unbind chart events passed as prop\n useEffect(() => {\n const chart = chartElement.current;\n if (!chart || onEvents === undefined) return;\n bindEvents(chart, onEvents);\n return (): void => {\n if (chart === undefined) return;\n if (chart.isDisposed() === true) return;\n for (const event in onEvents) {\n chart.off(event);\n }\n };\n }, [onEvents]);\n\n // TODO: re-evaluate how this is triggered. It's technically working right\n // now because the sx prop is an object that gets re-created, but that also\n // means it runs unnecessarily some of the time and theoretically might\n // not run in some other cases. Maybe it should use a resize observer?\n useEffect(() => {\n // TODO: fix this debouncing. This likely isn't working as intended because\n // the debounced function is re-created every time this useEffect is called.\n const updateSize = debounce(\n () => {\n if (!chartElement.current) return;\n chartElement.current.resize();\n },\n 200,\n {\n leading: true,\n },\n );\n updateSize();\n }, [sx, style]);\n\n return <Box ref={containerRef} sx={sx} style={style}></Box>;\n});\n\n// Validate event config and bind custom events\nfunction bindEvents<T>(instance: ECharts, events?: OnEventsType<T>): void {\n if (events === undefined) return;\n\n function bindEvent(eventName: EventName, OnEventFunction: unknown): void {\n if (typeof OnEventFunction === 'function') {\n if (isMouseEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params, instance));\n } else if (isBatchEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params));\n } else {\n instance.on(eventName, () => OnEventFunction(null, instance));\n }\n }\n }\n\n for (const eventName in events) {\n if (Object.prototype.hasOwnProperty.call(events, eventName)) {\n const customEvent = events[eventName as EventName] ?? null;\n if (customEvent) {\n bindEvent(eventName as EventName, customEvent);\n }\n }\n }\n}\n\nfunction isMouseEvent(eventName: EventName): eventName is MouseEventName {\n return (mouseEvents as readonly string[]).includes(eventName);\n}\n\nfunction isBatchEvent(eventName: EventName): eventName is BatchEventName {\n return (batchEvents as readonly string[]).includes(eventName);\n}\n"],"names":["Box","BarChart","EChartsBarChart","LineChart","EChartsLineChart","GaugeChart","EChartsGaugeChart","PieChart","EChartsPieChart","ScatterChart","EChartsScatterChart","CustomChart","EChartsCustomChart","HeatmapChart","EChartsHeatmapChart","DatasetComponent","DataZoomComponent","LegendComponent","GridComponent","TitleComponent","TooltipComponent","VisualMapComponent","ToolboxComponent","MarkPointComponent","MarkAreaComponent","MarkLineComponent","init","connect","use","registerEChartsComponents","CanvasRenderer","debounce","isEqual","memo","useEffect","useLayoutEffect","useRef","mouseEvents","batchEvents","EChart","option","theme","renderer","sx","style","onEvents","_instance","syncGroup","onChartInitialized","initialOption","prevOption","containerRef","chartElement","current","undefined","setOption","dispose","group","updateSize","resize","window","addEventListener","removeEventListener","chart","bindEvents","isDisposed","event","off","leading","ref","instance","events","bindEvent","eventName","OnEventFunction","isMouseEvent","on","params","isBatchEvent","Object","prototype","hasOwnProperty","call","customEvent","includes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/EChart/EChart.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport type { SxProps, Theme } from '@mui/material';\nimport { Box } from '@mui/material';\nimport {\n BarChart as EChartsBarChart,\n LineChart as EChartsLineChart,\n GaugeChart as EChartsGaugeChart,\n PieChart as EChartsPieChart,\n ScatterChart as EChartsScatterChart,\n CustomChart as EChartsCustomChart,\n HeatmapChart as EChartsHeatmapChart,\n} from 'echarts/charts';\nimport {\n DatasetComponent,\n DataZoomComponent,\n LegendComponent,\n GridComponent,\n TitleComponent,\n TooltipComponent,\n VisualMapComponent,\n ToolboxComponent,\n MarkPointComponent,\n MarkAreaComponent,\n MarkLineComponent,\n} from 'echarts/components';\nimport type { ECharts, EChartsCoreOption } from 'echarts/core';\nimport { init, connect, use as registerEChartsComponents } from 'echarts/core';\nimport { CanvasRenderer } from 'echarts/renderers';\nimport debounce from 'lodash/debounce';\nimport isEqual from 'lodash/isEqual';\nimport type { CSSProperties } from 'react';\nimport { memo, useEffect, useLayoutEffect, useRef } from 'react';\n\nimport type { EChartsTheme } from '../model';\n\n// Loading the ECharts extensions should happen in the respective plugins.\n// This is a workaround for https://github.com/perses/plugins/issues/83.\nregisterEChartsComponents([\n DatasetComponent,\n DataZoomComponent,\n LegendComponent,\n EChartsBarChart,\n EChartsLineChart,\n EChartsGaugeChart,\n EChartsPieChart,\n EChartsScatterChart,\n EChartsCustomChart,\n EChartsHeatmapChart,\n GridComponent,\n TitleComponent,\n ToolboxComponent,\n TooltipComponent,\n CanvasRenderer,\n VisualMapComponent,\n MarkAreaComponent,\n MarkLineComponent,\n MarkPointComponent,\n]);\n\n// see docs for info about each property: https://echarts.apache.org/en/api.html#events\nexport interface MouseEventsParameters<T> {\n componentType: string;\n seriesType: string;\n seriesIndex: number;\n seriesName: string;\n name: string;\n dataIndex: number;\n data: Record<string, unknown> & T;\n dataType: string;\n value: number | number[];\n color: string;\n info: Record<string, unknown>;\n}\n\ntype OnEventFunction<T> = (\n params: MouseEventsParameters<T>,\n // This is potentially undefined for testing purposes\n instance?: ECharts,\n) => void;\n\nconst mouseEvents = [\n 'click',\n 'dblclick',\n 'mousedown',\n 'mousemove',\n 'mouseup',\n 'mouseover',\n 'mouseout',\n 'globalout',\n 'contextmenu',\n] as const;\n\nexport type MouseEventName = (typeof mouseEvents)[number];\n\n// batch event types\nexport interface DataZoomPayloadBatchItem {\n dataZoomId: string;\n // start and end not returned unless dataZoom is based on percentProp,\n // which is for cases when a dataZoom component controls multiple axes\n start?: number;\n end?: number;\n // startValue and endValue return data index for 'category' axes,\n // for axis types 'value' and 'time', actual values are returned\n startValue?: number;\n endValue?: number;\n}\n\nexport interface HighlightPayloadBatchItem {\n dataIndex: number;\n dataIndexInside: number;\n seriesIndex: number;\n // highlight action can effect multiple connected charts\n escapeConnect?: boolean;\n // whether blur state was triggered\n notBlur?: boolean;\n}\n\nexport interface BatchEventsParameters {\n type: BatchEventName;\n batch: DataZoomPayloadBatchItem[] & HighlightPayloadBatchItem[];\n}\n\ntype OnBatchEventFunction = (params: BatchEventsParameters) => void;\n\nconst batchEvents = ['datazoom', 'downplay', 'highlight'] as const;\n\nexport type BatchEventName = (typeof batchEvents)[number];\n\ntype ChartEventName = 'finished';\n\ntype EventName = MouseEventName | ChartEventName | BatchEventName;\n\nexport type OnEventsType<T> = {\n [mouseEventName in MouseEventName]?: OnEventFunction<T>;\n} & {\n [batchEventName in BatchEventName]?: OnBatchEventFunction;\n} & {\n [eventName in ChartEventName]?: () => void;\n};\n\nexport interface EChartsProps<T> {\n option: EChartsCoreOption;\n theme?: string | EChartsTheme;\n renderer?: 'canvas' | 'svg';\n sx?: SxProps<Theme>;\n style?: CSSProperties;\n onEvents?: OnEventsType<T>;\n _instance?: React.MutableRefObject<ECharts | undefined>;\n syncGroup?: string;\n onChartInitialized?: (instance: ECharts) => void;\n}\n\nexport const EChart = memo(function EChart<T>({\n option,\n theme,\n renderer,\n sx,\n style,\n onEvents,\n _instance: instanceRef,\n syncGroup,\n onChartInitialized,\n}: EChartsProps<T>) {\n const initialOption = useRef<EChartsCoreOption>(option);\n const prevOption = useRef<EChartsCoreOption>(option);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const chartElement = useRef<ECharts | null>(null);\n\n // Initialize chart, dispose on unmount\n useLayoutEffect(() => {\n if (containerRef.current === null || chartElement.current !== null) return;\n chartElement.current = init(containerRef.current, theme, { renderer: renderer ?? 'canvas' });\n if (chartElement.current === undefined) return;\n chartElement.current.setOption(initialOption.current, true);\n onChartInitialized?.(chartElement.current);\n if (instanceRef !== undefined) {\n instanceRef.current = chartElement.current;\n }\n return (): void => {\n if (chartElement.current === null) return;\n chartElement.current.dispose();\n chartElement.current = null;\n };\n }, [instanceRef, onChartInitialized, theme, renderer]);\n\n // When syncGroup is explicitly set, charts within same group share interactions such as crosshair\n useEffect(() => {\n if (!chartElement.current || !syncGroup) return;\n chartElement.current.group = syncGroup;\n connect([chartElement.current]); // more info: https://echarts.apache.org/en/api.html#echarts.connect\n }, [syncGroup, chartElement]);\n\n // Update chart data when option changes\n useEffect(() => {\n if (prevOption.current === undefined || isEqual(prevOption.current, option)) return;\n if (!chartElement.current) return;\n chartElement.current.setOption(option, true);\n prevOption.current = option;\n }, [option]);\n\n // Observe actual container size, including layout and style changes.\n useLayoutEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const updateSize = debounce(() => {\n chartElement.current?.resize();\n }, 200);\n const observer = new ResizeObserver(updateSize);\n observer.observe(container);\n window.addEventListener('resize', updateSize);\n updateSize();\n return (): void => {\n observer.disconnect();\n window.removeEventListener('resize', updateSize);\n updateSize.cancel();\n };\n }, []);\n\n // Bind and unbind chart events passed as prop\n useEffect(() => {\n const chart = chartElement.current;\n if (!chart || onEvents === undefined) return;\n bindEvents(chart, onEvents);\n return (): void => {\n if (chart === undefined) return;\n if (chart.isDisposed() === true) return;\n for (const event in onEvents) {\n chart.off(event);\n }\n };\n }, [onEvents]);\n\n return <Box ref={containerRef} sx={sx} style={style}></Box>;\n});\n\n// Validate event config and bind custom events\nfunction bindEvents<T>(instance: ECharts, events?: OnEventsType<T>): void {\n if (events === undefined) return;\n\n function bindEvent(eventName: EventName, OnEventFunction: unknown): void {\n if (typeof OnEventFunction === 'function') {\n if (isMouseEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params, instance));\n } else if (isBatchEvent(eventName)) {\n instance.on(eventName, (params) => OnEventFunction(params));\n } else {\n instance.on(eventName, () => OnEventFunction(null, instance));\n }\n }\n }\n\n for (const eventName in events) {\n if (Object.prototype.hasOwnProperty.call(events, eventName)) {\n const customEvent = events[eventName as EventName] ?? null;\n if (customEvent) {\n bindEvent(eventName as EventName, customEvent);\n }\n }\n }\n}\n\nfunction isMouseEvent(eventName: EventName): eventName is MouseEventName {\n return (mouseEvents as readonly string[]).includes(eventName);\n}\n\nfunction isBatchEvent(eventName: EventName): eventName is BatchEventName {\n return (batchEvents as readonly string[]).includes(eventName);\n}\n"],"names":["Box","BarChart","EChartsBarChart","LineChart","EChartsLineChart","GaugeChart","EChartsGaugeChart","PieChart","EChartsPieChart","ScatterChart","EChartsScatterChart","CustomChart","EChartsCustomChart","HeatmapChart","EChartsHeatmapChart","DatasetComponent","DataZoomComponent","LegendComponent","GridComponent","TitleComponent","TooltipComponent","VisualMapComponent","ToolboxComponent","MarkPointComponent","MarkAreaComponent","MarkLineComponent","init","connect","use","registerEChartsComponents","CanvasRenderer","debounce","isEqual","memo","useEffect","useLayoutEffect","useRef","mouseEvents","batchEvents","EChart","option","theme","renderer","sx","style","onEvents","_instance","instanceRef","syncGroup","onChartInitialized","initialOption","prevOption","containerRef","chartElement","current","undefined","setOption","dispose","group","container","updateSize","resize","observer","ResizeObserver","observe","window","addEventListener","disconnect","removeEventListener","cancel","chart","bindEvents","isDisposed","event","off","ref","instance","events","bindEvent","eventName","OnEventFunction","isMouseEvent","on","params","isBatchEvent","Object","prototype","hasOwnProperty","call","customEvent","includes"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Exemplar, Labels } from '@perses-dev/spec';
2
+ import type { ReactElement } from 'react';
3
+ import type { FormatOptions } from '../model/units';
4
+ import type { CursorCoordinates } from '../TimeSeriesTooltip/tooltip-model';
5
+ export interface ExemplarMetadataTooltipProps {
6
+ exemplar: Exemplar;
7
+ seriesLabels?: Labels;
8
+ /**
9
+ * CSS selector of the element the tooltip should be portaled into (e.g. `#dashboard`).
10
+ * Passed as-is to `document.querySelector`, so it must be a selector and not a bare element id.
11
+ */
12
+ containerId?: string;
13
+ format?: FormatOptions;
14
+ /**
15
+ * Position where the tooltip has been pinned, or null when it follows the mouse.
16
+ */
17
+ pinnedPos: CursorCoordinates | null;
18
+ enablePinning?: boolean;
19
+ onUnpinClick?: () => void;
20
+ }
21
+ /**
22
+ * Tooltip showing an exemplar's metadata (series labels, exemplar labels, value and timestamp).
23
+ * Follows the mouse while hovering an exemplar marker and can be pinned in place, the same way
24
+ * the annotation tooltip works.
25
+ */
26
+ export declare function ExemplarMetadataTooltip({ exemplar, seriesLabels, containerId, format, pinnedPos, enablePinning, onUnpinClick, }: ExemplarMetadataTooltipProps): ReactElement | null;
27
+ //# sourceMappingURL=ExemplarMetadataTooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExemplarMetadataTooltip.d.ts","sourceRoot":"","sources":["../../src/ExemplarMetadata/ExemplarMetadataTooltip.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAGzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAWpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;OAEG;IACH,SAAS,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,MAAM,EACN,SAAS,EACT,aAAoB,EACpB,YAAY,GACb,EAAE,4BAA4B,GAAG,YAAY,GAAG,IAAI,CAwGpD"}
@@ -0,0 +1,239 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Copyright The Perses Authors
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ import { Box, Divider, IconButton, Portal, Stack, Typography } from "@mui/material";
14
+ import Pin from "mdi-material-ui/Pin";
15
+ import PinOutline from "mdi-material-ui/PinOutline";
16
+ import { Fragment } from "react";
17
+ import useResizeObserver from "use-resize-observer";
18
+ import { useTimeZone } from "../context/TimeZoneProvider.js";
19
+ import { formatValue } from "../model/units.js";
20
+ import { assembleTransform, getTooltipStyles, PIN_TOOLTIP_HELP_TEXT, TOOLTIP_BG_COLOR_FALLBACK, TOOLTIP_MAX_WIDTH, UNPIN_TOOLTIP_HELP_TEXT, useMousePosition } from "../TimeSeriesTooltip/index.js";
21
+ /**
22
+ * Tooltip showing an exemplar's metadata (series labels, exemplar labels, value and timestamp).
23
+ * Follows the mouse while hovering an exemplar marker and can be pinned in place, the same way
24
+ * the annotation tooltip works.
25
+ */ export function ExemplarMetadataTooltip({ exemplar, seriesLabels, containerId, format, pinnedPos, enablePinning = true, onUnpinClick }) {
26
+ const { formatWithUserTimeZone } = useTimeZone();
27
+ const mousePos = useMousePosition();
28
+ const { height, width, ref: tooltipRef } = useResizeObserver();
29
+ const isPinned = pinnedPos !== null;
30
+ if (!isPinned && mousePos === null) return null;
31
+ const containerElement = containerId ? document.querySelector(containerId) : undefined;
32
+ const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;
33
+ // Fall back to the pinned position: a pinned tooltip can render before any mousemove happened.
34
+ const transform = assembleTransform(mousePos ?? pinnedPos, pinnedPos, height ?? 0, width ?? 0, containerElement);
35
+ const { labels, value, timestamp } = exemplar;
36
+ const formattedValue = formatValue(value, format);
37
+ const date = new Date(timestamp);
38
+ const formattedDate = formatWithUserTimeZone(date, 'MMM dd, yyyy - ');
39
+ const formattedTime = formatWithUserTimeZone(date, 'HH:mm:ss');
40
+ // Only sections with content take part in the layout, so no divider is left dangling
41
+ // when a label set is empty.
42
+ const sections = [];
43
+ if (seriesLabels && Object.keys(seriesLabels).length > 0) {
44
+ sections.push({
45
+ key: 'series-labels',
46
+ content: /*#__PURE__*/ _jsx(LabelGrid, {
47
+ title: "Series labels",
48
+ labels: seriesLabels
49
+ })
50
+ });
51
+ }
52
+ if (Object.keys(labels).length > 0) {
53
+ sections.push({
54
+ key: 'exemplar-labels',
55
+ content: /*#__PURE__*/ _jsx(LabelGrid, {
56
+ title: "Exemplar labels",
57
+ labels: labels
58
+ })
59
+ });
60
+ }
61
+ sections.push({
62
+ key: 'value',
63
+ content: /*#__PURE__*/ _jsxs(Box, {
64
+ children: [
65
+ /*#__PURE__*/ _jsx(Typography, {
66
+ variant: "overline",
67
+ component: "div",
68
+ children: "Value"
69
+ }),
70
+ /*#__PURE__*/ _jsx(Typography, {
71
+ fontWeight: 700,
72
+ children: formattedValue
73
+ })
74
+ ]
75
+ })
76
+ });
77
+ return /*#__PURE__*/ _jsx(Portal, {
78
+ container: containerElement,
79
+ children: /*#__PURE__*/ _jsx(Box, {
80
+ ref: tooltipRef,
81
+ sx: (theme)=>getTooltipStyles(theme, pinnedPos, maxHeight),
82
+ style: {
83
+ transform
84
+ },
85
+ children: /*#__PURE__*/ _jsxs(Stack, {
86
+ spacing: 0.5,
87
+ children: [
88
+ /*#__PURE__*/ _jsxs(Box, {
89
+ sx: (theme)=>({
90
+ width: '100%',
91
+ maxWidth: TOOLTIP_MAX_WIDTH,
92
+ padding: theme.spacing(1.5, 2, 0.5, 2),
93
+ backgroundColor: theme.palette.designSystem?.grey[800] ?? TOOLTIP_BG_COLOR_FALLBACK,
94
+ position: 'sticky',
95
+ top: 0,
96
+ left: 0
97
+ }),
98
+ children: [
99
+ /*#__PURE__*/ _jsxs(Box, {
100
+ sx: {
101
+ display: 'flex',
102
+ alignItems: 'center',
103
+ paddingBottom: 0.5,
104
+ width: '100%'
105
+ },
106
+ children: [
107
+ /*#__PURE__*/ _jsxs(Box, {
108
+ sx: {
109
+ flexGrow: 1,
110
+ minWidth: 0
111
+ },
112
+ children: [
113
+ /*#__PURE__*/ _jsx(Typography, {
114
+ variant: "caption",
115
+ sx: (theme)=>({
116
+ color: theme.palette.common.white
117
+ }),
118
+ children: formattedDate
119
+ }),
120
+ /*#__PURE__*/ _jsx(Typography, {
121
+ variant: "caption",
122
+ children: /*#__PURE__*/ _jsx("strong", {
123
+ children: formattedTime
124
+ })
125
+ })
126
+ ]
127
+ }),
128
+ enablePinning && /*#__PURE__*/ _jsxs(Stack, {
129
+ direction: "row",
130
+ alignItems: "center",
131
+ sx: {
132
+ marginLeft: 1,
133
+ flexShrink: 0
134
+ },
135
+ children: [
136
+ /*#__PURE__*/ _jsx(Typography, {
137
+ sx: {
138
+ marginRight: 0.5,
139
+ fontSize: 11,
140
+ verticalAlign: 'middle'
141
+ },
142
+ children: isPinned ? UNPIN_TOOLTIP_HELP_TEXT : PIN_TOOLTIP_HELP_TEXT
143
+ }),
144
+ isPinned ? /*#__PURE__*/ _jsx(IconButton, {
145
+ "aria-label": UNPIN_TOOLTIP_HELP_TEXT,
146
+ onClick: ()=>{
147
+ if (onUnpinClick !== undefined) onUnpinClick();
148
+ },
149
+ sx: {
150
+ padding: 0,
151
+ color: 'inherit'
152
+ },
153
+ children: /*#__PURE__*/ _jsx(Pin, {
154
+ sx: {
155
+ fontSize: 16
156
+ }
157
+ })
158
+ }) : /*#__PURE__*/ _jsx(PinOutline, {
159
+ sx: {
160
+ fontSize: 16
161
+ }
162
+ })
163
+ ]
164
+ })
165
+ ]
166
+ }),
167
+ /*#__PURE__*/ _jsx(Divider, {
168
+ sx: (theme)=>({
169
+ width: '100%',
170
+ borderColor: theme.palette.grey['500']
171
+ })
172
+ })
173
+ ]
174
+ }),
175
+ /*#__PURE__*/ _jsx(Stack, {
176
+ spacing: 1,
177
+ sx: (theme)=>({
178
+ padding: theme.spacing(0.5, 2, 1.5, 2)
179
+ }),
180
+ children: sections.map((section, index)=>/*#__PURE__*/ _jsxs(Fragment, {
181
+ children: [
182
+ index > 0 && /*#__PURE__*/ _jsx(Divider, {
183
+ sx: (theme)=>({
184
+ borderColor: theme.palette.grey['500']
185
+ })
186
+ }),
187
+ section.content
188
+ ]
189
+ }, section.key))
190
+ })
191
+ ]
192
+ })
193
+ })
194
+ });
195
+ }
196
+ function LabelGrid({ title, labels }) {
197
+ const entries = Object.entries(labels);
198
+ return /*#__PURE__*/ _jsxs(Box, {
199
+ children: [
200
+ /*#__PURE__*/ _jsx(Typography, {
201
+ variant: "overline",
202
+ component: "div",
203
+ children: title
204
+ }),
205
+ /*#__PURE__*/ _jsx(Box, {
206
+ sx: {
207
+ display: 'grid',
208
+ // The first column is sized by the longest label name, so all values line up
209
+ // at the same horizontal position.
210
+ gridTemplateColumns: 'minmax(0, max-content) minmax(0, 1fr)',
211
+ columnGap: 0.5,
212
+ rowGap: 0.25
213
+ },
214
+ children: entries.map(([labelName, labelValue])=>/*#__PURE__*/ _jsxs(Fragment, {
215
+ children: [
216
+ /*#__PURE__*/ _jsxs(Typography, {
217
+ sx: {
218
+ wordBreak: 'break-all'
219
+ },
220
+ children: [
221
+ labelName,
222
+ ":"
223
+ ]
224
+ }),
225
+ /*#__PURE__*/ _jsx(Typography, {
226
+ fontWeight: 700,
227
+ sx: {
228
+ wordBreak: 'break-all'
229
+ },
230
+ children: labelValue
231
+ })
232
+ ]
233
+ }, labelName))
234
+ })
235
+ ]
236
+ });
237
+ }
238
+
239
+ //# sourceMappingURL=ExemplarMetadataTooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/ExemplarMetadata/ExemplarMetadataTooltip.tsx"],"sourcesContent":["// Copyright The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { Box, Divider, IconButton, Portal, Stack, Typography } from '@mui/material';\nimport type { Exemplar, Labels } from '@perses-dev/spec';\nimport Pin from 'mdi-material-ui/Pin';\nimport PinOutline from 'mdi-material-ui/PinOutline';\nimport type { ReactElement } from 'react';\nimport { Fragment } from 'react';\nimport useResizeObserver from 'use-resize-observer';\n\nimport { useTimeZone } from '../context/TimeZoneProvider';\nimport type { FormatOptions } from '../model/units';\nimport { formatValue } from '../model/units';\nimport {\n assembleTransform,\n getTooltipStyles,\n PIN_TOOLTIP_HELP_TEXT,\n TOOLTIP_BG_COLOR_FALLBACK,\n TOOLTIP_MAX_WIDTH,\n UNPIN_TOOLTIP_HELP_TEXT,\n useMousePosition,\n} from '../TimeSeriesTooltip';\nimport type { CursorCoordinates } from '../TimeSeriesTooltip/tooltip-model';\n\nexport interface ExemplarMetadataTooltipProps {\n exemplar: Exemplar;\n seriesLabels?: Labels;\n /**\n * CSS selector of the element the tooltip should be portaled into (e.g. `#dashboard`).\n * Passed as-is to `document.querySelector`, so it must be a selector and not a bare element id.\n */\n containerId?: string;\n format?: FormatOptions;\n /**\n * Position where the tooltip has been pinned, or null when it follows the mouse.\n */\n pinnedPos: CursorCoordinates | null;\n enablePinning?: boolean;\n onUnpinClick?: () => void;\n}\n\n/**\n * Tooltip showing an exemplar's metadata (series labels, exemplar labels, value and timestamp).\n * Follows the mouse while hovering an exemplar marker and can be pinned in place, the same way\n * the annotation tooltip works.\n */\nexport function ExemplarMetadataTooltip({\n exemplar,\n seriesLabels,\n containerId,\n format,\n pinnedPos,\n enablePinning = true,\n onUnpinClick,\n}: ExemplarMetadataTooltipProps): ReactElement | null {\n const { formatWithUserTimeZone } = useTimeZone();\n const mousePos = useMousePosition();\n const { height, width, ref: tooltipRef } = useResizeObserver<HTMLDivElement>();\n\n const isPinned = pinnedPos !== null;\n if (!isPinned && mousePos === null) return null;\n\n const containerElement = containerId ? document.querySelector(containerId) : undefined;\n const maxHeight = containerElement ? containerElement.getBoundingClientRect().height : undefined;\n // Fall back to the pinned position: a pinned tooltip can render before any mousemove happened.\n const transform = assembleTransform(mousePos ?? pinnedPos, pinnedPos, height ?? 0, width ?? 0, containerElement);\n\n const { labels, value, timestamp } = exemplar;\n const formattedValue = formatValue(value, format);\n const date = new Date(timestamp);\n const formattedDate = formatWithUserTimeZone(date, 'MMM dd, yyyy - ');\n const formattedTime = formatWithUserTimeZone(date, 'HH:mm:ss');\n\n // Only sections with content take part in the layout, so no divider is left dangling\n // when a label set is empty.\n const sections: Array<{ key: string; content: ReactElement }> = [];\n if (seriesLabels && Object.keys(seriesLabels).length > 0) {\n sections.push({ key: 'series-labels', content: <LabelGrid title=\"Series labels\" labels={seriesLabels} /> });\n }\n if (Object.keys(labels).length > 0) {\n sections.push({ key: 'exemplar-labels', content: <LabelGrid title=\"Exemplar labels\" labels={labels} /> });\n }\n sections.push({\n key: 'value',\n content: (\n <Box>\n <Typography variant=\"overline\" component=\"div\">\n Value\n </Typography>\n <Typography fontWeight={700}>{formattedValue}</Typography>\n </Box>\n ),\n });\n\n return (\n <Portal container={containerElement}>\n <Box ref={tooltipRef} sx={(theme) => getTooltipStyles(theme, pinnedPos, maxHeight)} style={{ transform }}>\n <Stack spacing={0.5}>\n <Box\n sx={(theme) => ({\n width: '100%',\n maxWidth: TOOLTIP_MAX_WIDTH,\n padding: theme.spacing(1.5, 2, 0.5, 2),\n backgroundColor: theme.palette.designSystem?.grey[800] ?? TOOLTIP_BG_COLOR_FALLBACK,\n position: 'sticky',\n top: 0,\n left: 0,\n })}\n >\n <Box sx={{ display: 'flex', alignItems: 'center', paddingBottom: 0.5, width: '100%' }}>\n <Box sx={{ flexGrow: 1, minWidth: 0 }}>\n <Typography\n variant=\"caption\"\n sx={(theme) => ({\n color: theme.palette.common.white,\n })}\n >\n {formattedDate}\n </Typography>\n <Typography variant=\"caption\">\n <strong>{formattedTime}</strong>\n </Typography>\n </Box>\n {enablePinning && (\n <Stack direction=\"row\" alignItems=\"center\" sx={{ marginLeft: 1, flexShrink: 0 }}>\n <Typography sx={{ marginRight: 0.5, fontSize: 11, verticalAlign: 'middle' }}>\n {isPinned ? UNPIN_TOOLTIP_HELP_TEXT : PIN_TOOLTIP_HELP_TEXT}\n </Typography>\n {isPinned ? (\n <IconButton\n aria-label={UNPIN_TOOLTIP_HELP_TEXT}\n onClick={() => {\n if (onUnpinClick !== undefined) onUnpinClick();\n }}\n sx={{ padding: 0, color: 'inherit' }}\n >\n <Pin sx={{ fontSize: 16 }} />\n </IconButton>\n ) : (\n <PinOutline sx={{ fontSize: 16 }} />\n )}\n </Stack>\n )}\n </Box>\n <Divider sx={(theme) => ({ width: '100%', borderColor: theme.palette.grey['500'] })} />\n </Box>\n <Stack spacing={1} sx={(theme) => ({ padding: theme.spacing(0.5, 2, 1.5, 2) })}>\n {sections.map((section, index) => (\n <Fragment key={section.key}>\n {index > 0 && <Divider sx={(theme) => ({ borderColor: theme.palette.grey['500'] })} />}\n {section.content}\n </Fragment>\n ))}\n </Stack>\n </Stack>\n </Box>\n </Portal>\n );\n}\n\nfunction LabelGrid({ title, labels }: { title: string; labels: Labels }): ReactElement {\n const entries = Object.entries(labels);\n return (\n <Box>\n <Typography variant=\"overline\" component=\"div\">\n {title}\n </Typography>\n <Box\n sx={{\n display: 'grid',\n // The first column is sized by the longest label name, so all values line up\n // at the same horizontal position.\n gridTemplateColumns: 'minmax(0, max-content) minmax(0, 1fr)',\n columnGap: 0.5,\n rowGap: 0.25,\n }}\n >\n {entries.map(([labelName, labelValue]) => (\n <Fragment key={labelName}>\n <Typography sx={{ wordBreak: 'break-all' }}>{labelName}:</Typography>\n <Typography fontWeight={700} sx={{ wordBreak: 'break-all' }}>\n {labelValue}\n </Typography>\n </Fragment>\n ))}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","Divider","IconButton","Portal","Stack","Typography","Pin","PinOutline","Fragment","useResizeObserver","useTimeZone","formatValue","assembleTransform","getTooltipStyles","PIN_TOOLTIP_HELP_TEXT","TOOLTIP_BG_COLOR_FALLBACK","TOOLTIP_MAX_WIDTH","UNPIN_TOOLTIP_HELP_TEXT","useMousePosition","ExemplarMetadataTooltip","exemplar","seriesLabels","containerId","format","pinnedPos","enablePinning","onUnpinClick","formatWithUserTimeZone","mousePos","height","width","ref","tooltipRef","isPinned","containerElement","document","querySelector","undefined","maxHeight","getBoundingClientRect","transform","labels","value","timestamp","formattedValue","date","Date","formattedDate","formattedTime","sections","Object","keys","length","push","key","content","LabelGrid","title","variant","component","fontWeight","container","sx","theme","style","spacing","maxWidth","padding","backgroundColor","palette","designSystem","grey","position","top","left","display","alignItems","paddingBottom","flexGrow","minWidth","color","common","white","strong","direction","marginLeft","flexShrink","marginRight","fontSize","verticalAlign","aria-label","onClick","borderColor","map","section","index","entries","gridTemplateColumns","columnGap","rowGap","labelName","labelValue","wordBreak"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from './ExemplarMetadataTooltip';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ExemplarMetadata/index.ts"],"names":[],"mappings":"AAYA,cAAc,2BAA2B,CAAC"}