@grafana/components 0.0.30 → 0.0.32
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.
- package/README.md +33 -0
- package/dist/cjs/index.cjs +52 -27
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +88 -5
- package/dist/esm/components/ColorModeProvider/ColorModeProvider.js +0 -1
- package/dist/esm/components/ColorModeProvider/ColorModeProvider.js.map +1 -1
- package/dist/esm/components/Popover/Popover.js +15 -2
- package/dist/esm/components/Popover/Popover.js.map +1 -1
- package/dist/esm/components/PortalProvider/PortalProvider.js +22 -0
- package/dist/esm/components/PortalProvider/PortalProvider.js.map +1 -0
- package/dist/esm/components/StackedChart/StackedChart.js.map +1 -1
- package/dist/esm/hooks/useColorModeChange.js +20 -11
- package/dist/esm/hooks/useColorModeChange.js.map +1 -1
- package/dist/esm/index.d.ts +88 -5
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/esm/node_modules/@grafana/runtime/dist/esm/services/appEvents.js +0 -17
- package/dist/esm/node_modules/@grafana/runtime/dist/esm/services/appEvents.js.map +0 -1
package/dist/cjs/index.d.cts
CHANGED
|
@@ -4,7 +4,7 @@ import { EventBus, GrafanaTheme2 } from '@grafana/data';
|
|
|
4
4
|
import { ThemeColorMode } from '@grafana/design-tokens';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
import { IconName } from '@grafana/ui';
|
|
7
|
-
import { Placement } from '@floating-ui/react';
|
|
7
|
+
import { Placement, FloatingPortalProps } from '@floating-ui/react';
|
|
8
8
|
|
|
9
9
|
interface ColorModeChangeProps {
|
|
10
10
|
getAppEvents: () => EventBus;
|
|
@@ -84,6 +84,10 @@ interface PopoverProps {
|
|
|
84
84
|
* Virtual element to anchor the popover to instead of the trigger
|
|
85
85
|
*/
|
|
86
86
|
virtualElement?: React.RefObject<Element>;
|
|
87
|
+
/**
|
|
88
|
+
* DOM element or ID to render the portal into, falls back to document.body
|
|
89
|
+
*/
|
|
90
|
+
portalContainer?: FloatingPortalProps['root'];
|
|
87
91
|
}
|
|
88
92
|
declare const Popover: React$1.ForwardRefExoticComponent<PopoverProps & React$1.RefAttributes<HTMLElement>>;
|
|
89
93
|
|
|
@@ -117,6 +121,39 @@ interface GenericSkeletonProps {
|
|
|
117
121
|
}
|
|
118
122
|
declare const GenericSkeleton: ({ animationDuration }: GenericSkeletonProps) => react_jsx_runtime.JSX.Element;
|
|
119
123
|
|
|
124
|
+
type PortalRoot = FloatingPortalProps['root'];
|
|
125
|
+
interface PortalContextType {
|
|
126
|
+
root: PortalRoot;
|
|
127
|
+
setRoot: (root: PortalRoot) => void;
|
|
128
|
+
}
|
|
129
|
+
interface PortalProviderProps {
|
|
130
|
+
children: ReactNode;
|
|
131
|
+
defaultRoot?: PortalRoot;
|
|
132
|
+
}
|
|
133
|
+
interface UsePortalOptions {
|
|
134
|
+
/** If true, returns document.body instead of throwing when outside provider */
|
|
135
|
+
allowOutsideProvider?: boolean;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Provides a shared context for a portal root, which can be a selector string,
|
|
139
|
+
* an HTMLElement, or null.
|
|
140
|
+
*
|
|
141
|
+
* Wrap your application (or a subtree) in this provider to enable
|
|
142
|
+
* Popover, Tooltip, and other floating components to render correctly.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```tsx
|
|
146
|
+
* <PortalProvider defaultRoot={document.getElementById('grafana-portal-container')}>
|
|
147
|
+
* <App />
|
|
148
|
+
* </PortalProvider>
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare const PortalProvider: React__default.FC<PortalProviderProps>;
|
|
152
|
+
/**
|
|
153
|
+
* Use this hook to access the portal root context.
|
|
154
|
+
*/
|
|
155
|
+
declare const usePortal: ({ allowOutsideProvider }?: UsePortalOptions) => PortalContextType;
|
|
156
|
+
|
|
120
157
|
type StackedChartNoDataMessageFormatter = (args: {
|
|
121
158
|
period: string;
|
|
122
159
|
className: string;
|
|
@@ -143,6 +180,30 @@ interface StackedChartCategory {
|
|
|
143
180
|
}
|
|
144
181
|
type StackedChartCategories<T extends string> = Partial<Record<T, StackedChartCategory>>;
|
|
145
182
|
type StackedChartSortOrder = 'largest-first' | 'smallest-first' | 'natural';
|
|
183
|
+
/**
|
|
184
|
+
* Callback function invoked when a mouse event occurs on a chart segment.
|
|
185
|
+
*
|
|
186
|
+
* This is a simplified callback (not a React event handler) that receives
|
|
187
|
+
* segment metadata. It's called after the internal event handling is complete.
|
|
188
|
+
*
|
|
189
|
+
* @param args - Object containing segment metadata
|
|
190
|
+
* @param args.categoryId - The unique identifier of the segment that triggered the event
|
|
191
|
+
* @param args.ref - React ref to the segment's DOM element, useful for positioning tooltips or popovers
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```tsx
|
|
195
|
+
* <StackedChart
|
|
196
|
+
* categories={categories}
|
|
197
|
+
* onSegmentMouseOver={({ categoryId, ref }) => {
|
|
198
|
+
* console.log(`Hovered segment: ${categoryId}`);
|
|
199
|
+
* // ref.current gives you the DOM element if needed
|
|
200
|
+
* }}
|
|
201
|
+
* onSegmentMouseOut={({ categoryId }) => {
|
|
202
|
+
* console.log(`Left segment: ${categoryId}`);
|
|
203
|
+
* }}
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
146
207
|
type MouseEventHandler = ({ categoryId, ref, }: {
|
|
147
208
|
categoryId: string;
|
|
148
209
|
ref: React.ForwardedRef<HTMLDivElement>;
|
|
@@ -167,11 +228,33 @@ interface StackedChartProps<T extends string> {
|
|
|
167
228
|
*/
|
|
168
229
|
isDimmed?: boolean;
|
|
169
230
|
/**
|
|
170
|
-
*
|
|
231
|
+
* Callback invoked when the mouse enters a chart segment.
|
|
232
|
+
*
|
|
233
|
+
* Receives the segment's `categoryId` and a `ref` to its DOM element.
|
|
234
|
+
* Use this to implement custom hover behavior, analytics tracking,
|
|
235
|
+
* or coordination with external UI elements.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```tsx
|
|
239
|
+
* onSegmentMouseOver={({ categoryId, ref }) => {
|
|
240
|
+
* setActiveCategory(categoryId);
|
|
241
|
+
* // Optional: use ref.current for DOM measurements
|
|
242
|
+
* }}
|
|
243
|
+
* ```
|
|
171
244
|
*/
|
|
172
245
|
onSegmentMouseOver?: MouseEventHandler;
|
|
173
246
|
/**
|
|
174
|
-
*
|
|
247
|
+
* Callback invoked when the mouse leaves a chart segment.
|
|
248
|
+
*
|
|
249
|
+
* Receives the segment's `categoryId` and a `ref` to its DOM element.
|
|
250
|
+
* Use this to clean up hover state or hide related UI elements.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```tsx
|
|
254
|
+
* onSegmentMouseOut={({ categoryId }) => {
|
|
255
|
+
* setActiveCategory(null);
|
|
256
|
+
* }}
|
|
257
|
+
* ```
|
|
175
258
|
*/
|
|
176
259
|
onSegmentMouseOut?: MouseEventHandler;
|
|
177
260
|
/**
|
|
@@ -310,5 +393,5 @@ interface FormatNumberOptions {
|
|
|
310
393
|
*/
|
|
311
394
|
declare const formatNumber: (value: number | string | "loading", options?: FormatNumberOptions) => string;
|
|
312
395
|
|
|
313
|
-
export { ColorMode, ColorModeChangeHandler, ColorModeProvider, ComparisonBadge, ComparisonTooltip, GenericSkeleton, Popover, StackedChart, StackedChartNoData, StackedChartSegment, StackedChartSegmentTooltip, StackedChartSkeleton, calculateComparison, formatNumber, useColorMode, useColorModeChange };
|
|
314
|
-
export type { ColorModeChangeProps, ColorModeContextType, ColorModeProviderProps, ColorModeWrapper, ComparisonResult, ComparisonTooltipProps, FormatNumberOptions, GenericSkeletonProps, PopoverProps, StackedChartCategories, StackedChartCategory, StackedChartNoDataMessageFormatter, StackedChartNoDataProps, StackedChartProps, StackedChartSegmentTooltipProps, StackedChartSkeletonProps, StackedChartSortOrder, StackedChartTooltipContentFormatter };
|
|
396
|
+
export { ColorMode, ColorModeChangeHandler, ColorModeProvider, ComparisonBadge, ComparisonTooltip, GenericSkeleton, Popover, PortalProvider, StackedChart, StackedChartNoData, StackedChartSegment, StackedChartSegmentTooltip, StackedChartSkeleton, calculateComparison, formatNumber, useColorMode, useColorModeChange, usePortal };
|
|
397
|
+
export type { ColorModeChangeProps, ColorModeContextType, ColorModeProviderProps, ColorModeWrapper, ComparisonResult, ComparisonTooltipProps, FormatNumberOptions, GenericSkeletonProps, PopoverProps, PortalContextType, PortalProviderProps, PortalRoot, SegmentMouseEventHandler, StackedChartCategories, StackedChartCategory, StackedChartNoDataMessageFormatter, StackedChartNoDataProps, StackedChartProps, StackedChartSegmentProps, StackedChartSegmentState, StackedChartSegmentTooltipProps, StackedChartSkeletonProps, StackedChartSortOrder, StackedChartTooltipContentFormatter, UsePortalOptions };
|
|
@@ -11,7 +11,6 @@ const ColorModeProvider = ({
|
|
|
11
11
|
}) => {
|
|
12
12
|
const [colorMode, setColorMode] = useState(defaultColorMode);
|
|
13
13
|
useEffect(() => {
|
|
14
|
-
console.log("ColorModeProvider", { colorMode });
|
|
15
14
|
document.documentElement.setAttribute("data-color-mode", colorMode);
|
|
16
15
|
}, [colorMode]);
|
|
17
16
|
return /* @__PURE__ */ jsx(ColorModeContext.Provider, { value: { colorMode, setColorMode }, children });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColorModeProvider.js","sources":["../../../../src/components/ColorModeProvider/ColorModeProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';\nimport { ThemeColorMode } from '@grafana/design-tokens';\n\nimport '@grafana/design-tokens/dist/css/legacy/primitives.css';\nimport '@grafana/design-tokens/dist/css/legacy/colors.light.css';\nimport '@grafana/design-tokens/dist/css/legacy/colors.dark.css';\n\nexport interface ColorModeContextType {\n colorMode: ThemeColorMode;\n setColorMode: (colorMode: ThemeColorMode) => void;\n}\n\nexport interface ColorModeProviderProps {\n children: ReactNode;\n defaultColorMode?: ThemeColorMode;\n}\n\nconst ColorModeContext = createContext<ColorModeContextType | undefined>(undefined);\n\n/**\n * Provides a shared context for the currently-active theme color mode, and sets\n * the data-color-mode attribute on the document element whenever it changes.\n */\nexport const ColorModeProvider: React.FC<ColorModeProviderProps> = ({\n children,\n defaultColorMode = 'light',\n}) => {\n const [colorMode, setColorMode] = useState<ThemeColorMode>(defaultColorMode);\n\n useEffect(() => {\n
|
|
1
|
+
{"version":3,"file":"ColorModeProvider.js","sources":["../../../../src/components/ColorModeProvider/ColorModeProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';\nimport { ThemeColorMode } from '@grafana/design-tokens';\n\nimport '@grafana/design-tokens/dist/css/legacy/primitives.css';\nimport '@grafana/design-tokens/dist/css/legacy/colors.light.css';\nimport '@grafana/design-tokens/dist/css/legacy/colors.dark.css';\n\nexport interface ColorModeContextType {\n colorMode: ThemeColorMode;\n setColorMode: (colorMode: ThemeColorMode) => void;\n}\n\nexport interface ColorModeProviderProps {\n children: ReactNode;\n defaultColorMode?: ThemeColorMode;\n}\n\nconst ColorModeContext = createContext<ColorModeContextType | undefined>(undefined);\n\n/**\n * Provides a shared context for the currently-active theme color mode, and sets\n * the data-color-mode attribute on the document element whenever it changes.\n */\nexport const ColorModeProvider: React.FC<ColorModeProviderProps> = ({\n children,\n defaultColorMode = 'light',\n}) => {\n const [colorMode, setColorMode] = useState<ThemeColorMode>(defaultColorMode);\n\n useEffect(() => {\n document.documentElement.setAttribute('data-color-mode', colorMode);\n }, [colorMode]);\n\n return (\n <ColorModeContext.Provider value={{ colorMode, setColorMode }}>\n {children}\n </ColorModeContext.Provider>\n );\n};\n\n/**\n * Use this to query the active color mode, or to set it, e.g. with an effect\n * hook within a component which explicitly changes the active color mode:\n *\n * useEffect(() => {\n * setColorMode(colorMode);\n * }, [colorMode]);\n *\n */\nexport const useColorMode = () => {\n const context = useContext(ColorModeContext);\n\n if (context === undefined) {\n throw new Error('useColorMode must be used within a ColorModeProvider');\n }\n\n return context;\n};\n"],"names":[],"mappings":";;;;;;AAiBA,MAAM,gBAAA,GAAmB,cAAgD,MAAS,CAAA;AAM3E,MAAM,oBAAsD,CAAC;AAAA,EAClE,QAAA;AAAA,EACA,gBAAA,GAAmB;AACrB,CAAA,KAAM;AACJ,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAyB,gBAAgB,CAAA;AAE3E,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,QAAA,CAAS,eAAA,CAAgB,YAAA,CAAa,iBAAA,EAAmB,SAAS,CAAA;AAAA,EACpE,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,uBACE,GAAA,CAAC,iBAAiB,QAAA,EAAjB,EAA0B,OAAO,EAAE,SAAA,EAAW,YAAA,EAAa,EACzD,QAAA,EACH,CAAA;AAEJ;AAWO,MAAM,eAAe,MAAM;AAChC,EAAA,MAAM,OAAA,GAAU,WAAW,gBAAgB,CAAA;AAE3C,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AAEA,EAAA,OAAO,OAAA;AACT;;;;"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { forwardRef, useRef, useId, useState, useLayoutEffect, useCallback, cloneElement } from 'react';
|
|
3
3
|
import { useFloating, autoUpdate, useInteractions, useDismiss, useHover, useFocus, useRole, safePolygon, useTransitionStyles, FloatingPortal, FloatingArrow, flip, shift, offset, arrow } from '@floating-ui/react';
|
|
4
|
+
import { usePortal } from '../PortalProvider/PortalProvider.js';
|
|
4
5
|
import { getStyles } from './Popover.styles.js';
|
|
5
6
|
|
|
6
7
|
const POPOVER_OFFSET = 8;
|
|
@@ -35,7 +36,8 @@ const Popover = forwardRef(
|
|
|
35
36
|
placement = "bottom",
|
|
36
37
|
transitionDuration = 200,
|
|
37
38
|
hideDelay = 500,
|
|
38
|
-
virtualElement
|
|
39
|
+
virtualElement,
|
|
40
|
+
portalContainer
|
|
39
41
|
}, forwardedRef) => {
|
|
40
42
|
const arrowRef = useRef(null);
|
|
41
43
|
const closeTimer = useRef(void 0);
|
|
@@ -45,6 +47,17 @@ const Popover = forwardRef(
|
|
|
45
47
|
const isOpen = isOpenControlled != null ? isOpenControlled : isOpenState;
|
|
46
48
|
const middleware = getMiddleware({ placement, arrowRef });
|
|
47
49
|
const styles = getStyles();
|
|
50
|
+
const { root } = usePortal();
|
|
51
|
+
const portalRoot = (() => {
|
|
52
|
+
switch (true) {
|
|
53
|
+
case portalContainer instanceof HTMLElement:
|
|
54
|
+
return portalContainer;
|
|
55
|
+
case typeof portalContainer === "string":
|
|
56
|
+
return document.getElementById(portalContainer);
|
|
57
|
+
default:
|
|
58
|
+
return root;
|
|
59
|
+
}
|
|
60
|
+
})();
|
|
48
61
|
const { context, refs, floatingStyles } = useFloating({
|
|
49
62
|
open: isOpen,
|
|
50
63
|
placement,
|
|
@@ -121,7 +134,7 @@ const Popover = forwardRef(
|
|
|
121
134
|
"aria-describedby": isOpen ? popoverId : void 0,
|
|
122
135
|
...getReferenceProps()
|
|
123
136
|
}),
|
|
124
|
-
(isDelayedOpen || isOpen) && /* @__PURE__ */ jsx(FloatingPortal, { root:
|
|
137
|
+
(isDelayedOpen || isOpen) && /* @__PURE__ */ jsx(FloatingPortal, { root: portalRoot, children: /* @__PURE__ */ jsx("div", { ref: refs.setFloating, style: floatingStyles, ...getFloatingProps(), children: /* @__PURE__ */ jsxs("div", { style: transitionStyles, className: styles.shadow, children: [
|
|
125
138
|
/* @__PURE__ */ jsx(FloatingArrow, { className: styles.arrow, ref: arrowRef, context }),
|
|
126
139
|
/* @__PURE__ */ jsx("div", { id: popoverId, role: "tooltip", className: styles.container, children })
|
|
127
140
|
] }) }) })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Popover.js","sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n forwardRef,\n cloneElement,\n useCallback,\n useId,\n useRef,\n useState,\n useLayoutEffect,\n JSX,\n} from 'react';\nimport {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n offset,\n Placement,\n safePolygon,\n shift,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useRole,\n useInteractions,\n useTransitionStyles,\n FloatingPortal,\n} from '@floating-ui/react';\nimport { getStyles } from './Popover.styles';\n\nexport interface PopoverProps {\n /**\n * Content used to trigger the Popover being displayed\n */\n trigger: JSX.Element;\n\n /**\n * Content to render within the Popover\n */\n children: JSX.Element;\n /**\n * Should the popover be open? Implicitly means the popover visibility is\n * controlled; if omitted, the popover target will control visibility\n */\n isOpen?: boolean;\n\n /**\n * Set to true if you want the tooltip to stay long enough so the user can\n * move mouse over content to select text or click a link\n */\n isInteractive?: boolean;\n\n /**\n * Placement of the Popover relative to the trigger content\n */\n placement?: Placement;\n\n /**\n * Transition duration for hide/show effects, in milliseconds\n */\n transitionDuration?: number;\n\n /**\n * Additional delay before hiding the popover after mouseout, in milliseconds\n */\n hideDelay?: number;\n\n /**\n * Virtual element to anchor the popover to instead of the trigger\n */\n virtualElement?: React.RefObject<Element>;\n}\n\nconst POPOVER_OFFSET = 8;\n\nconst getMiddleware = ({\n placement,\n arrowRef,\n}: {\n placement?: Placement;\n arrowRef: React.RefObject<null>;\n}) => {\n const BOUNDARY_ELEMENT_ID = 'floating-boundary';\n const _flip = flip({\n // Ensure we flip to the perpendicular axis if it doesn't fit\n // on narrow viewports.\n crossAxis: 'alignment',\n fallbackAxisSideDirection: 'end',\n boundary: document.getElementById(BOUNDARY_ELEMENT_ID) ?? undefined,\n });\n\n const middleware = placement?.includes('-') ? [_flip, shift()] : [shift(), _flip];\n\n // the order of middleware is important!\n // `arrow` should almost always be at the end\n // see https://floating-ui.com/docs/arrow#order\n return [\n offset(POPOVER_OFFSET),\n ...middleware,\n arrow({\n element: arrowRef,\n }),\n ];\n};\n\nexport const Popover = forwardRef<HTMLElement, PopoverProps>(\n (\n {\n trigger,\n children,\n isOpen: isOpenControlled,\n isInteractive = false,\n placement = 'bottom',\n transitionDuration = 200,\n hideDelay = 500,\n virtualElement,\n },\n forwardedRef,\n ) => {\n const arrowRef = useRef(null);\n const closeTimer = useRef<number | undefined>(undefined);\n const popoverId = useId();\n const [isOpenState, setOpen] = useState(isOpenControlled);\n const [isDelayedOpen, setDelayedOpen] = useState(isOpenControlled);\n const isOpen = isOpenControlled ?? isOpenState;\n const middleware = getMiddleware({ placement, arrowRef });\n const styles = getStyles();\n\n const { context, refs, floatingStyles } = useFloating({\n open: isOpen,\n placement,\n onOpenChange: (open) => {\n setOpen(open);\n clearTimeout(closeTimer.current);\n\n if (!open) {\n closeTimer.current = window.setTimeout(() => {\n setDelayedOpen(open);\n }, transitionDuration + hideDelay);\n } else {\n setDelayedOpen(open);\n }\n },\n middleware,\n whileElementsMounted: autoUpdate,\n });\n\n useLayoutEffect(() => {\n if (virtualElement && virtualElement.current !== null) {\n const domRect = virtualElement.current.getBoundingClientRect();\n\n refs.setPositionReference({\n getBoundingClientRect: () => {\n if (virtualElement.current !== null)\n return virtualElement.current.getBoundingClientRect();\n return domRect;\n },\n contextElement: virtualElement.current,\n });\n }\n }, [refs, virtualElement]);\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useDismiss(context),\n useHover(context, {\n handleClose: isInteractive ? safePolygon() : undefined,\n move: false,\n delay: {\n open: 0,\n close: hideDelay,\n },\n }),\n useFocus(context),\n useRole(context),\n ]);\n\n const { styles: transitionStyles } = useTransitionStyles(context, {\n duration: transitionDuration,\n initial: ({ side }) => ({\n opacity: 0,\n transform:\n side === 'top' || side === 'bottom'\n ? `translateY(${POPOVER_OFFSET}px)`\n : `translateX(${POPOVER_OFFSET}px)`,\n }),\n open: ({ side }) => ({\n opacity: 1,\n transform: side === 'top' || side === 'bottom' ? `translateY(0)` : `translateX(0)`,\n }),\n close: ({ side }) => ({\n opacity: 0,\n transform:\n side === 'top' || side === 'bottom'\n ? `translateY(${POPOVER_OFFSET}px)`\n : `translateX(${POPOVER_OFFSET}px)`,\n }),\n });\n\n const handleRef = useCallback(\n (ref: HTMLElement | null) => {\n refs.setReference(ref);\n\n if (typeof forwardedRef === 'function') {\n forwardedRef(ref);\n } else if (forwardedRef) {\n forwardedRef.current = ref;\n }\n },\n [forwardedRef, refs],\n );\n\n return (\n <>\n {/* element to trigger displaying the popover */}\n {cloneElement(trigger, {\n ref: handleRef,\n tabIndex: 0,\n 'aria-describedby': isOpen ? popoverId : undefined,\n ...getReferenceProps(),\n })}\n {/* content to render inside the popover when open */}\n {(isDelayedOpen || isOpen) && (\n <FloatingPortal root={document.getElementById('grafana-portal-container')}>\n <div ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>\n <div style={transitionStyles} className={styles.shadow}>\n <FloatingArrow className={styles.arrow} ref={arrowRef} context={context} />\n <div id={popoverId} role=\"tooltip\" className={styles.container}>\n {children}\n </div>\n </div>\n </div>\n </FloatingPortal>\n )}\n </>\n );\n },\n);\n\nPopover.displayName = 'Popover';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Popover.js","sources":["../../../../src/components/Popover/Popover.tsx"],"sourcesContent":["import {\n forwardRef,\n cloneElement,\n useCallback,\n useId,\n useRef,\n useState,\n useLayoutEffect,\n JSX,\n} from 'react';\nimport {\n arrow,\n autoUpdate,\n flip,\n FloatingArrow,\n offset,\n Placement,\n safePolygon,\n shift,\n useDismiss,\n useFloating,\n useFocus,\n useHover,\n useRole,\n useInteractions,\n useTransitionStyles,\n FloatingPortal,\n FloatingPortalProps,\n} from '@floating-ui/react';\nimport { usePortal } from '../PortalProvider';\nimport { getStyles } from './Popover.styles';\n\nexport interface PopoverProps {\n /**\n * Content used to trigger the Popover being displayed\n */\n trigger: JSX.Element;\n\n /**\n * Content to render within the Popover\n */\n children: JSX.Element;\n /**\n * Should the popover be open? Implicitly means the popover visibility is\n * controlled; if omitted, the popover target will control visibility\n */\n isOpen?: boolean;\n\n /**\n * Set to true if you want the tooltip to stay long enough so the user can\n * move mouse over content to select text or click a link\n */\n isInteractive?: boolean;\n\n /**\n * Placement of the Popover relative to the trigger content\n */\n placement?: Placement;\n\n /**\n * Transition duration for hide/show effects, in milliseconds\n */\n transitionDuration?: number;\n\n /**\n * Additional delay before hiding the popover after mouseout, in milliseconds\n */\n hideDelay?: number;\n\n /**\n * Virtual element to anchor the popover to instead of the trigger\n */\n virtualElement?: React.RefObject<Element>;\n\n /**\n * DOM element or ID to render the portal into, falls back to document.body\n */\n portalContainer?: FloatingPortalProps['root'];\n}\n\nconst POPOVER_OFFSET = 8;\n\nconst getMiddleware = ({\n placement,\n arrowRef,\n}: {\n placement?: Placement;\n arrowRef: React.RefObject<null>;\n}) => {\n const BOUNDARY_ELEMENT_ID = 'floating-boundary';\n const _flip = flip({\n // Ensure we flip to the perpendicular axis if it doesn't fit\n // on narrow viewports.\n crossAxis: 'alignment',\n fallbackAxisSideDirection: 'end',\n boundary: document.getElementById(BOUNDARY_ELEMENT_ID) ?? undefined,\n });\n\n const middleware = placement?.includes('-') ? [_flip, shift()] : [shift(), _flip];\n\n // the order of middleware is important!\n // `arrow` should almost always be at the end\n // see https://floating-ui.com/docs/arrow#order\n return [\n offset(POPOVER_OFFSET),\n ...middleware,\n arrow({\n element: arrowRef,\n }),\n ];\n};\n\nexport const Popover = forwardRef<HTMLElement, PopoverProps>(\n (\n {\n trigger,\n children,\n isOpen: isOpenControlled,\n isInteractive = false,\n placement = 'bottom',\n transitionDuration = 200,\n hideDelay = 500,\n virtualElement,\n portalContainer,\n },\n forwardedRef,\n ) => {\n const arrowRef = useRef(null);\n const closeTimer = useRef<number | undefined>(undefined);\n const popoverId = useId();\n const [isOpenState, setOpen] = useState(isOpenControlled);\n const [isDelayedOpen, setDelayedOpen] = useState(isOpenControlled);\n const isOpen = isOpenControlled ?? isOpenState;\n const middleware = getMiddleware({ placement, arrowRef });\n const styles = getStyles();\n const { root } = usePortal();\n\n const portalRoot = (() => {\n switch (true) {\n case portalContainer instanceof HTMLElement:\n return portalContainer;\n case typeof portalContainer === 'string':\n return document.getElementById(portalContainer);\n default:\n return root;\n }\n })();\n\n const { context, refs, floatingStyles } = useFloating({\n open: isOpen,\n placement,\n onOpenChange: (open) => {\n setOpen(open);\n clearTimeout(closeTimer.current);\n\n if (!open) {\n closeTimer.current = window.setTimeout(() => {\n setDelayedOpen(open);\n }, transitionDuration + hideDelay);\n } else {\n setDelayedOpen(open);\n }\n },\n middleware,\n whileElementsMounted: autoUpdate,\n });\n\n useLayoutEffect(() => {\n if (virtualElement && virtualElement.current !== null) {\n const domRect = virtualElement.current.getBoundingClientRect();\n\n refs.setPositionReference({\n getBoundingClientRect: () => {\n if (virtualElement.current !== null)\n return virtualElement.current.getBoundingClientRect();\n return domRect;\n },\n contextElement: virtualElement.current,\n });\n }\n }, [refs, virtualElement]);\n\n const { getReferenceProps, getFloatingProps } = useInteractions([\n useDismiss(context),\n useHover(context, {\n handleClose: isInteractive ? safePolygon() : undefined,\n move: false,\n delay: {\n open: 0,\n close: hideDelay,\n },\n }),\n useFocus(context),\n useRole(context),\n ]);\n\n const { styles: transitionStyles } = useTransitionStyles(context, {\n duration: transitionDuration,\n initial: ({ side }) => ({\n opacity: 0,\n transform:\n side === 'top' || side === 'bottom'\n ? `translateY(${POPOVER_OFFSET}px)`\n : `translateX(${POPOVER_OFFSET}px)`,\n }),\n open: ({ side }) => ({\n opacity: 1,\n transform: side === 'top' || side === 'bottom' ? `translateY(0)` : `translateX(0)`,\n }),\n close: ({ side }) => ({\n opacity: 0,\n transform:\n side === 'top' || side === 'bottom'\n ? `translateY(${POPOVER_OFFSET}px)`\n : `translateX(${POPOVER_OFFSET}px)`,\n }),\n });\n\n const handleRef = useCallback(\n (ref: HTMLElement | null) => {\n refs.setReference(ref);\n\n if (typeof forwardedRef === 'function') {\n forwardedRef(ref);\n } else if (forwardedRef) {\n forwardedRef.current = ref;\n }\n },\n [forwardedRef, refs],\n );\n\n return (\n <>\n {/* element to trigger displaying the popover */}\n {cloneElement(trigger, {\n ref: handleRef,\n tabIndex: 0,\n 'aria-describedby': isOpen ? popoverId : undefined,\n ...getReferenceProps(),\n })}\n {/* content to render inside the popover when open */}\n {(isDelayedOpen || isOpen) && (\n <FloatingPortal root={portalRoot}>\n <div ref={refs.setFloating} style={floatingStyles} {...getFloatingProps()}>\n <div style={transitionStyles} className={styles.shadow}>\n <FloatingArrow className={styles.arrow} ref={arrowRef} context={context} />\n <div id={popoverId} role=\"tooltip\" className={styles.container}>\n {children}\n </div>\n </div>\n </div>\n </FloatingPortal>\n )}\n </>\n );\n },\n);\n\nPopover.displayName = 'Popover';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useContext, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
const PortalContext = createContext(void 0);
|
|
5
|
+
const PortalProvider = ({ children, defaultRoot = null }) => {
|
|
6
|
+
const [root, setRoot] = useState(defaultRoot != null ? defaultRoot : document.body);
|
|
7
|
+
return /* @__PURE__ */ jsx(PortalContext.Provider, { value: { root, setRoot }, children });
|
|
8
|
+
};
|
|
9
|
+
const usePortal = ({ allowOutsideProvider = false } = {}) => {
|
|
10
|
+
const context = useContext(PortalContext);
|
|
11
|
+
if (context === void 0) {
|
|
12
|
+
if (allowOutsideProvider) {
|
|
13
|
+
return { root: document.body, setRoot: () => {
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
throw new Error("usePortal must be used within a PortalProvider");
|
|
17
|
+
}
|
|
18
|
+
return context;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { PortalProvider, usePortal };
|
|
22
|
+
//# sourceMappingURL=PortalProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortalProvider.js","sources":["../../../../src/components/PortalProvider/PortalProvider.tsx"],"sourcesContent":["import React, { createContext, useContext, useState, ReactNode } from 'react';\nimport type { FloatingPortalProps } from '@floating-ui/react';\n\nexport type PortalRoot = FloatingPortalProps['root'];\n\nexport interface PortalContextType {\n root: PortalRoot;\n setRoot: (root: PortalRoot) => void;\n}\n\nexport interface PortalProviderProps {\n children: ReactNode;\n defaultRoot?: PortalRoot;\n}\n\nexport interface UsePortalOptions {\n /** If true, returns document.body instead of throwing when outside provider */\n allowOutsideProvider?: boolean;\n}\n\nconst PortalContext = createContext<PortalContextType | undefined>(undefined);\n\n/**\n * Provides a shared context for a portal root, which can be a selector string,\n * an HTMLElement, or null.\n *\n * Wrap your application (or a subtree) in this provider to enable\n * Popover, Tooltip, and other floating components to render correctly.\n *\n * @example\n * ```tsx\n * <PortalProvider defaultRoot={document.getElementById('grafana-portal-container')}>\n * <App />\n * </PortalProvider>\n * ```\n */\nexport const PortalProvider: React.FC<PortalProviderProps> = ({ children, defaultRoot = null }) => {\n const [root, setRoot] = useState<PortalRoot>(defaultRoot ?? document.body);\n\n return <PortalContext.Provider value={{ root, setRoot }}>{children}</PortalContext.Provider>;\n};\n\n/**\n * Use this hook to access the portal root context.\n */\nexport const usePortal = ({ allowOutsideProvider = false }: UsePortalOptions = {}) => {\n const context = useContext(PortalContext);\n\n if (context === undefined) {\n if (allowOutsideProvider) {\n return { root: document.body, setRoot: () => {} };\n }\n throw new Error('usePortal must be used within a PortalProvider');\n }\n\n return context;\n};\n"],"names":[],"mappings":";;;AAoBA,MAAM,aAAA,GAAgB,cAA6C,MAAS,CAAA;AAgBrE,MAAM,iBAAgD,CAAC,EAAE,QAAA,EAAU,WAAA,GAAc,MAAK,KAAM;AACjG,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,IAAI,QAAA,CAAqB,WAAA,IAAA,IAAA,GAAA,WAAA,GAAe,SAAS,IAAI,CAAA;AAEzE,EAAA,uBAAO,GAAA,CAAC,cAAc,QAAA,EAAd,EAAuB,OAAO,EAAE,IAAA,EAAM,OAAA,EAAQ,EAAI,QAAA,EAAS,CAAA;AACrE;AAKO,MAAM,YAAY,CAAC,EAAE,uBAAuB,KAAA,EAAM,GAAsB,EAAC,KAAM;AACpF,EAAA,MAAM,OAAA,GAAU,WAAW,aAAa,CAAA;AAExC,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,IAAI,oBAAA,EAAsB;AACxB,MAAA,OAAO,EAAE,IAAA,EAAM,QAAA,CAAS,IAAA,EAAM,SAAS,MAAM;AAAA,MAAC,CAAA,EAAE;AAAA,IAClD;AACA,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AAEA,EAAA,OAAO,OAAA;AACT;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StackedChart.js","sources":["../../../../src/components/StackedChart/StackedChart.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { StackedChartSegment } from '../StackedChartSegment';\nimport { getStyles } from './StackedChart.styles';\nimport { StackedChartSegmentState, SegmentMouseEventHandler } from '../StackedChartSegment/types';\nimport { StackedChartSegmentTooltip } from '../StackedChartSegmentTooltip';\nimport { StackedChartSkeleton } from '../StackedChartSkeleton';\nimport { StackedChartNoData, StackedChartNoDataProps } from '../StackedChartNoData';\nimport { STACKED_CHART_DEFAULT_HEIGHT } from './common';\n\nexport interface StackedChartCategory {\n title: string;\n value: number;\n}\n\nconst DUMMY_CATEGORY: StackedChartCategory = {\n title: 'Category',\n value: 0.01,\n};\n\nexport type StackedChartCategories<T extends string> = Partial<Record<T, StackedChartCategory>>;\n\nexport type StackedChartSortOrder = 'largest-first' | 'smallest-first' | 'natural';\n\ntype MouseEventHandler = ({\n categoryId,\n ref,\n}: {\n categoryId: string;\n ref: React.ForwardedRef<HTMLDivElement>;\n}) => void;\n\nexport interface StackedChartProps<T extends string> {\n /**\n * How should category segments be sorted?\n */\n sortOrder?: StackedChartSortOrder;\n\n /**\n * Height to render the stacked chart, in pixels\n */\n height?: number;\n\n /**\n * initial category ID to highlight; if omitted then all segments will render\n * in colour and highlight based on mouseover events.\n */\n highlightedCategoryId?: T;\n\n /**\n * Should the whole StackedChart be dimmed, i.e. with a highlighted category\n * not in color, all other categories faded out?\n */\n isDimmed?: boolean;\n\n /**\n * Event handler for whenever a segment gets a mouseover event\n */\n onSegmentMouseOver?: MouseEventHandler;\n\n /**\n * Event handler for whenever a segment gets a mouseout event\n */\n onSegmentMouseOut?: MouseEventHandler;\n\n /**\n * String representing the period for which the chart is displaying data\n */\n period?: string;\n\n formatNoDataMessage?: StackedChartNoDataProps['formatMessage'];\n\n /**\n * Is the StackedChart explicitly in a loading state?\n */\n isSkeleton?: boolean;\n\n /**\n * Array of StackedChartCategory to build the chart from\n */\n categories?: StackedChartCategories<T>;\n}\n\n/**\n * Custom hook to assign a ref per categoryId\n */\nconst useCategoryRefs = <T extends string>(\n categoryIds: T[],\n): Record<T, React.RefObject<HTMLDivElement>> => {\n const refsMap = useRef<Map<T, React.RefObject<HTMLDivElement>>>(new Map());\n\n for (const categoryId of categoryIds) {\n if (!refsMap.current.has(categoryId)) {\n refsMap.current.set(categoryId, { current: null });\n }\n }\n\n const result = {} as Record<T, React.RefObject<HTMLDivElement>>;\n for (const categoryId of categoryIds) {\n result[categoryId] = refsMap.current.get(categoryId)!;\n }\n\n return result;\n};\n\nexport const StackedChart = <T extends string>({\n categories,\n highlightedCategoryId: initialHighlightedCategoryId,\n isSkeleton = false,\n isDimmed = false,\n sortOrder = 'largest-first',\n height = STACKED_CHART_DEFAULT_HEIGHT,\n onSegmentMouseOver,\n onSegmentMouseOut,\n period = 'current',\n formatNoDataMessage,\n}: StackedChartProps<T>) => {\n const shouldRenderSkeleton = isSkeleton || !categories;\n let highlightedSegmentRef = useRef<HTMLDivElement>(null);\n const [highlightedCategoryId, setHighlightedCategoryId] = useState<string | undefined>(\n /**\n * Using a type assertion here ultimately because you can’t pass a generic\n * type argument to the type of props in React.forwardRef (it is inferred as\n * of type string).\n *\n * See: https://stackoverflow.com/questions/51884498/using-react-forwardref-with-typescript-generic-jsx-arguments\n */\n initialHighlightedCategoryId as string,\n );\n const [isHovered, setHovered] = useState<boolean>(false);\n const timer = useRef<number | undefined>(undefined);\n\n const sortedCategoryIds = (() => {\n let categoryIds: T[] = [];\n\n for (const categoryId in categories) {\n categoryIds.push(categoryId);\n }\n\n // return early since we may not even have any categories at this point\n if (shouldRenderSkeleton) return categoryIds;\n\n switch (sortOrder) {\n case 'largest-first':\n return categoryIds.sort(\n (a, b) => (categories[b]?.value ?? 0) - (categories[a]?.value ?? 0),\n );\n case 'smallest-first':\n return categoryIds.sort(\n (a, b) => (categories[a]?.value ?? 0) - (categories[b]?.value ?? 0),\n );\n default:\n return categoryIds;\n }\n })();\n\n const categoryRefs = useCategoryRefs(sortedCategoryIds);\n\n /**\n * Determine what the total value is for all category values combined\n */\n const total = shouldRenderSkeleton\n ? 0\n : Math.round(\n sortedCategoryIds.reduce((sum, categoryId) => {\n return sum + (categories[categoryId]?.value ?? 0);\n }, 0),\n );\n\n const styles = getStyles({ height });\n\n const onMouseOver: SegmentMouseEventHandler =\n ({ ref, categoryId }) =>\n () => {\n clearTimeout(timer.current);\n setHovered(true);\n\n /**\n * Only update the highlighted category ID if an initial category wasn’t\n * supplied\n */\n if (!initialHighlightedCategoryId) {\n setHighlightedCategoryId(categoryId);\n }\n\n if (onSegmentMouseOver) onSegmentMouseOver({ ref, categoryId });\n };\n\n const onMouseOut: SegmentMouseEventHandler =\n ({ ref, categoryId }) =>\n () => {\n /**\n * TODO: rather than use a timeout, maybe use the parent element being\n * moused over (event bubbling?) to validate whether the mouse has left\n * the entire chart vs an individual segment?\n */\n timer.current = window.setTimeout(() => {\n setHovered(false);\n /**\n * Only clear the highlighted category if an initial category wasn’t\n * supplied\n */\n if (!initialHighlightedCategoryId) {\n setHighlightedCategoryId(undefined);\n }\n }, 50);\n\n if (onSegmentMouseOut) onSegmentMouseOut({ ref, categoryId });\n };\n\n const highlightedCategory: (StackedChartCategory & { index: number }) | undefined =\n !shouldRenderSkeleton &&\n initialHighlightedCategoryId &&\n categories[initialHighlightedCategoryId]\n ? {\n ...categories[initialHighlightedCategoryId],\n index: sortedCategoryIds.indexOf(initialHighlightedCategoryId),\n }\n : undefined;\n\n const content = (\n <div className={styles.container}>\n {sortedCategoryIds.map((categoryId, index) => {\n /**\n * Some dummy category data is returned here for the scenario when\n * rendering a skeleton\n */\n const category =\n !shouldRenderSkeleton && categories?.[categoryId] !== undefined\n ? categories?.[categoryId]\n : DUMMY_CATEGORY;\n const ref = categoryRefs[categoryId];\n\n if (categoryId === initialHighlightedCategoryId && ref) highlightedSegmentRef = ref;\n\n const segmentState = ((): StackedChartSegmentState => {\n switch (true) {\n /**\n * If no initial highlighted category was set, and a category is\n * moused over, use the _active_ state for that category rather\n * than the color state; this adds a drop shadow to the segment.\n * Also, if an initial highlighted category _was_ set, and it\n * receives a hover event, also set it to active.\n */\n case !initialHighlightedCategoryId && highlightedCategoryId === categoryId && !isDimmed:\n case initialHighlightedCategoryId === categoryId && isHovered && !isDimmed:\n return 'active';\n\n /**\n * - no initial highlighted category ID was passed _and_ there is\n * no highlightedCategoryId (i.e. all segments in colour)\n * - the highlighted category is this category (but the chart\n * isn’t dimmed)\n * - the initial highlighted category is this category (but the\n * chart isn’t dimmed)\n */\n case !initialHighlightedCategoryId && !highlightedCategoryId && !isDimmed:\n case initialHighlightedCategoryId === categoryId && !isDimmed:\n return 'color';\n\n /**\n * Has an initial highlighted category, but is dimmed (i.e. all\n * segments excepted the highlighted category)\n */\n case Boolean(initialHighlightedCategoryId) &&\n initialHighlightedCategoryId !== categoryId &&\n isDimmed:\n case !initialHighlightedCategoryId && !highlightedCategoryId && isDimmed:\n case highlightedCategoryId !== categoryId && isDimmed:\n return 'dimmed';\n\n /**\n * In any other case, the segment should be the default grey\n */\n default:\n return 'default';\n }\n })();\n\n const segmentProps = {\n key: categoryId,\n index,\n ref,\n categoryId,\n title: category.title,\n value: category.value,\n total,\n state: segmentState,\n onMouseOver,\n onMouseOut,\n };\n\n /**\n * Only wrap the segment in a tooltip if no initially highlighted\n * category ID was supplied.\n */\n return initialHighlightedCategoryId ? (\n <StackedChartSegment {...segmentProps} />\n ) : (\n <StackedChartSegmentTooltip\n key={categoryId}\n title={category.title}\n value={category.value}\n index={index}\n hideDelay={0}\n trigger={<StackedChartSegment {...segmentProps} />}\n />\n );\n })}\n </div>\n );\n\n /**\n * If we should only render a skeleton, return early with that component\n */\n if (shouldRenderSkeleton) return <StackedChartSkeleton height={height} />;\n\n /**\n * If the initial highlighted category isn’t within the provided set of\n * categories, fall back to displaying the No Data component\n */\n if (\n initialHighlightedCategoryId &&\n sortedCategoryIds.indexOf(initialHighlightedCategoryId) === -1\n )\n return (\n <StackedChartNoData height={height} period={period} formatMessage={formatNoDataMessage} />\n );\n\n /**\n * If an initial highlight category was provided, wrap the entire chart inside\n * a tooltip using the props for the highlighted segment to drive the tooltip\n * content.\n */\n return initialHighlightedCategoryId && highlightedCategory ? (\n <StackedChartSegmentTooltip\n hideDelay={0}\n trigger={content}\n virtualElement={highlightedSegmentRef}\n {...highlightedCategory}\n />\n ) : (\n content\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StackedChart.js","sources":["../../../../src/components/StackedChart/StackedChart.tsx"],"sourcesContent":["import { useRef, useState } from 'react';\nimport { StackedChartSegment } from '../StackedChartSegment';\nimport { getStyles } from './StackedChart.styles';\nimport { StackedChartSegmentState, SegmentMouseEventHandler } from '../StackedChartSegment/types';\nimport { StackedChartSegmentTooltip } from '../StackedChartSegmentTooltip';\nimport { StackedChartSkeleton } from '../StackedChartSkeleton';\nimport { StackedChartNoData, StackedChartNoDataProps } from '../StackedChartNoData';\nimport { STACKED_CHART_DEFAULT_HEIGHT } from './common';\n\nexport interface StackedChartCategory {\n title: string;\n value: number;\n}\n\nconst DUMMY_CATEGORY: StackedChartCategory = {\n title: 'Category',\n value: 0.01,\n};\n\nexport type StackedChartCategories<T extends string> = Partial<Record<T, StackedChartCategory>>;\n\nexport type StackedChartSortOrder = 'largest-first' | 'smallest-first' | 'natural';\n\n/**\n * Callback function invoked when a mouse event occurs on a chart segment.\n *\n * This is a simplified callback (not a React event handler) that receives\n * segment metadata. It's called after the internal event handling is complete.\n *\n * @param args - Object containing segment metadata\n * @param args.categoryId - The unique identifier of the segment that triggered the event\n * @param args.ref - React ref to the segment's DOM element, useful for positioning tooltips or popovers\n *\n * @example\n * ```tsx\n * <StackedChart\n * categories={categories}\n * onSegmentMouseOver={({ categoryId, ref }) => {\n * console.log(`Hovered segment: ${categoryId}`);\n * // ref.current gives you the DOM element if needed\n * }}\n * onSegmentMouseOut={({ categoryId }) => {\n * console.log(`Left segment: ${categoryId}`);\n * }}\n * />\n * ```\n */\ntype MouseEventHandler = ({\n categoryId,\n ref,\n}: {\n categoryId: string;\n ref: React.ForwardedRef<HTMLDivElement>;\n}) => void;\n\nexport interface StackedChartProps<T extends string> {\n /**\n * How should category segments be sorted?\n */\n sortOrder?: StackedChartSortOrder;\n\n /**\n * Height to render the stacked chart, in pixels\n */\n height?: number;\n\n /**\n * initial category ID to highlight; if omitted then all segments will render\n * in colour and highlight based on mouseover events.\n */\n highlightedCategoryId?: T;\n\n /**\n * Should the whole StackedChart be dimmed, i.e. with a highlighted category\n * not in color, all other categories faded out?\n */\n isDimmed?: boolean;\n\n /**\n * Callback invoked when the mouse enters a chart segment.\n *\n * Receives the segment's `categoryId` and a `ref` to its DOM element.\n * Use this to implement custom hover behavior, analytics tracking,\n * or coordination with external UI elements.\n *\n * @example\n * ```tsx\n * onSegmentMouseOver={({ categoryId, ref }) => {\n * setActiveCategory(categoryId);\n * // Optional: use ref.current for DOM measurements\n * }}\n * ```\n */\n onSegmentMouseOver?: MouseEventHandler;\n\n /**\n * Callback invoked when the mouse leaves a chart segment.\n *\n * Receives the segment's `categoryId` and a `ref` to its DOM element.\n * Use this to clean up hover state or hide related UI elements.\n *\n * @example\n * ```tsx\n * onSegmentMouseOut={({ categoryId }) => {\n * setActiveCategory(null);\n * }}\n * ```\n */\n onSegmentMouseOut?: MouseEventHandler;\n\n /**\n * String representing the period for which the chart is displaying data\n */\n period?: string;\n\n formatNoDataMessage?: StackedChartNoDataProps['formatMessage'];\n\n /**\n * Is the StackedChart explicitly in a loading state?\n */\n isSkeleton?: boolean;\n\n /**\n * Array of StackedChartCategory to build the chart from\n */\n categories?: StackedChartCategories<T>;\n}\n\n/**\n * Custom hook to assign a ref per categoryId\n */\nconst useCategoryRefs = <T extends string>(\n categoryIds: T[],\n): Record<T, React.RefObject<HTMLDivElement>> => {\n const refsMap = useRef<Map<T, React.RefObject<HTMLDivElement>>>(new Map());\n\n for (const categoryId of categoryIds) {\n if (!refsMap.current.has(categoryId)) {\n refsMap.current.set(categoryId, { current: null });\n }\n }\n\n const result = {} as Record<T, React.RefObject<HTMLDivElement>>;\n for (const categoryId of categoryIds) {\n result[categoryId] = refsMap.current.get(categoryId)!;\n }\n\n return result;\n};\n\nexport const StackedChart = <T extends string>({\n categories,\n highlightedCategoryId: initialHighlightedCategoryId,\n isSkeleton = false,\n isDimmed = false,\n sortOrder = 'largest-first',\n height = STACKED_CHART_DEFAULT_HEIGHT,\n onSegmentMouseOver,\n onSegmentMouseOut,\n period = 'current',\n formatNoDataMessage,\n}: StackedChartProps<T>) => {\n const shouldRenderSkeleton = isSkeleton || !categories;\n let highlightedSegmentRef = useRef<HTMLDivElement>(null);\n const [highlightedCategoryId, setHighlightedCategoryId] = useState<string | undefined>(\n /**\n * Using a type assertion here ultimately because you can’t pass a generic\n * type argument to the type of props in React.forwardRef (it is inferred as\n * of type string).\n *\n * See: https://stackoverflow.com/questions/51884498/using-react-forwardref-with-typescript-generic-jsx-arguments\n */\n initialHighlightedCategoryId as string,\n );\n const [isHovered, setHovered] = useState<boolean>(false);\n const timer = useRef<number | undefined>(undefined);\n\n const sortedCategoryIds = (() => {\n let categoryIds: T[] = [];\n\n for (const categoryId in categories) {\n categoryIds.push(categoryId);\n }\n\n // return early since we may not even have any categories at this point\n if (shouldRenderSkeleton) return categoryIds;\n\n switch (sortOrder) {\n case 'largest-first':\n return categoryIds.sort(\n (a, b) => (categories[b]?.value ?? 0) - (categories[a]?.value ?? 0),\n );\n case 'smallest-first':\n return categoryIds.sort(\n (a, b) => (categories[a]?.value ?? 0) - (categories[b]?.value ?? 0),\n );\n default:\n return categoryIds;\n }\n })();\n\n const categoryRefs = useCategoryRefs(sortedCategoryIds);\n\n /**\n * Determine what the total value is for all category values combined\n */\n const total = shouldRenderSkeleton\n ? 0\n : Math.round(\n sortedCategoryIds.reduce((sum, categoryId) => {\n return sum + (categories[categoryId]?.value ?? 0);\n }, 0),\n );\n\n const styles = getStyles({ height });\n\n const onMouseOver: SegmentMouseEventHandler =\n ({ ref, categoryId }) =>\n () => {\n clearTimeout(timer.current);\n setHovered(true);\n\n /**\n * Only update the highlighted category ID if an initial category wasn’t\n * supplied\n */\n if (!initialHighlightedCategoryId) {\n setHighlightedCategoryId(categoryId);\n }\n\n if (onSegmentMouseOver) onSegmentMouseOver({ ref, categoryId });\n };\n\n const onMouseOut: SegmentMouseEventHandler =\n ({ ref, categoryId }) =>\n () => {\n /**\n * TODO: rather than use a timeout, maybe use the parent element being\n * moused over (event bubbling?) to validate whether the mouse has left\n * the entire chart vs an individual segment?\n */\n timer.current = window.setTimeout(() => {\n setHovered(false);\n /**\n * Only clear the highlighted category if an initial category wasn’t\n * supplied\n */\n if (!initialHighlightedCategoryId) {\n setHighlightedCategoryId(undefined);\n }\n }, 50);\n\n if (onSegmentMouseOut) onSegmentMouseOut({ ref, categoryId });\n };\n\n const highlightedCategory: (StackedChartCategory & { index: number }) | undefined =\n !shouldRenderSkeleton &&\n initialHighlightedCategoryId &&\n categories[initialHighlightedCategoryId]\n ? {\n ...categories[initialHighlightedCategoryId],\n index: sortedCategoryIds.indexOf(initialHighlightedCategoryId),\n }\n : undefined;\n\n const content = (\n <div className={styles.container}>\n {sortedCategoryIds.map((categoryId, index) => {\n /**\n * Some dummy category data is returned here for the scenario when\n * rendering a skeleton\n */\n const category =\n !shouldRenderSkeleton && categories?.[categoryId] !== undefined\n ? categories?.[categoryId]\n : DUMMY_CATEGORY;\n const ref = categoryRefs[categoryId];\n\n if (categoryId === initialHighlightedCategoryId && ref) highlightedSegmentRef = ref;\n\n const segmentState = ((): StackedChartSegmentState => {\n switch (true) {\n /**\n * If no initial highlighted category was set, and a category is\n * moused over, use the _active_ state for that category rather\n * than the color state; this adds a drop shadow to the segment.\n * Also, if an initial highlighted category _was_ set, and it\n * receives a hover event, also set it to active.\n */\n case !initialHighlightedCategoryId && highlightedCategoryId === categoryId && !isDimmed:\n case initialHighlightedCategoryId === categoryId && isHovered && !isDimmed:\n return 'active';\n\n /**\n * - no initial highlighted category ID was passed _and_ there is\n * no highlightedCategoryId (i.e. all segments in colour)\n * - the highlighted category is this category (but the chart\n * isn’t dimmed)\n * - the initial highlighted category is this category (but the\n * chart isn’t dimmed)\n */\n case !initialHighlightedCategoryId && !highlightedCategoryId && !isDimmed:\n case initialHighlightedCategoryId === categoryId && !isDimmed:\n return 'color';\n\n /**\n * Has an initial highlighted category, but is dimmed (i.e. all\n * segments excepted the highlighted category)\n */\n case Boolean(initialHighlightedCategoryId) &&\n initialHighlightedCategoryId !== categoryId &&\n isDimmed:\n case !initialHighlightedCategoryId && !highlightedCategoryId && isDimmed:\n case highlightedCategoryId !== categoryId && isDimmed:\n return 'dimmed';\n\n /**\n * In any other case, the segment should be the default grey\n */\n default:\n return 'default';\n }\n })();\n\n const segmentProps = {\n key: categoryId,\n index,\n ref,\n categoryId,\n title: category.title,\n value: category.value,\n total,\n state: segmentState,\n onMouseOver,\n onMouseOut,\n };\n\n /**\n * Only wrap the segment in a tooltip if no initially highlighted\n * category ID was supplied.\n */\n return initialHighlightedCategoryId ? (\n <StackedChartSegment {...segmentProps} />\n ) : (\n <StackedChartSegmentTooltip\n key={categoryId}\n title={category.title}\n value={category.value}\n index={index}\n hideDelay={0}\n trigger={<StackedChartSegment {...segmentProps} />}\n />\n );\n })}\n </div>\n );\n\n /**\n * If we should only render a skeleton, return early with that component\n */\n if (shouldRenderSkeleton) return <StackedChartSkeleton height={height} />;\n\n /**\n * If the initial highlighted category isn’t within the provided set of\n * categories, fall back to displaying the No Data component\n */\n if (\n initialHighlightedCategoryId &&\n sortedCategoryIds.indexOf(initialHighlightedCategoryId) === -1\n )\n return (\n <StackedChartNoData height={height} period={period} formatMessage={formatNoDataMessage} />\n );\n\n /**\n * If an initial highlight category was provided, wrap the entire chart inside\n * a tooltip using the props for the highlighted segment to drive the tooltip\n * content.\n */\n return initialHighlightedCategoryId && highlightedCategory ? (\n <StackedChartSegmentTooltip\n hideDelay={0}\n trigger={content}\n virtualElement={highlightedSegmentRef}\n {...highlightedCategory}\n />\n ) : (\n content\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { ThemeChangedEvent } from '@grafana/runtime';
|
|
1
3
|
import { useColorMode } from '../components/ColorModeProvider/ColorModeProvider.js';
|
|
2
|
-
import { ThemeChangedEvent } from '../node_modules/@grafana/runtime/dist/esm/services/appEvents.js';
|
|
3
4
|
|
|
4
5
|
const getThemeColorMode = (isLight) => {
|
|
5
6
|
return isLight ? "light" : "dark";
|
|
@@ -8,18 +9,26 @@ const useColorModeChange = ({
|
|
|
8
9
|
getAppEvents,
|
|
9
10
|
useTheme2
|
|
10
11
|
}) => {
|
|
11
|
-
const { setColorMode } = useColorMode();
|
|
12
|
+
const { colorMode, setColorMode } = useColorMode();
|
|
12
13
|
const appEvents = getAppEvents();
|
|
13
|
-
appEvents.subscribe(ThemeChangedEvent, ({ payload }) => {
|
|
14
|
-
const { isLight: isLight2 } = payload;
|
|
15
|
-
const newColorMode2 = getThemeColorMode(isLight2);
|
|
16
|
-
console.log("ThemeChangedEvent", { colorMode: newColorMode2 });
|
|
17
|
-
setColorMode(newColorMode2);
|
|
18
|
-
});
|
|
19
14
|
const { isLight } = useTheme2();
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const themeChangedEvent = appEvents.subscribe(
|
|
17
|
+
ThemeChangedEvent,
|
|
18
|
+
({ payload }) => {
|
|
19
|
+
const newColorMode = getThemeColorMode(payload.isLight);
|
|
20
|
+
setColorMode(newColorMode);
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
return () => {
|
|
24
|
+
themeChangedEvent.unsubscribe();
|
|
25
|
+
};
|
|
26
|
+
}, [appEvents, setColorMode]);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const newColorMode = getThemeColorMode(isLight);
|
|
29
|
+
setColorMode(newColorMode);
|
|
30
|
+
}, [isLight, setColorMode]);
|
|
31
|
+
return colorMode;
|
|
23
32
|
};
|
|
24
33
|
|
|
25
34
|
export { useColorModeChange };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useColorModeChange.js","sources":["../../../src/hooks/useColorModeChange.ts"],"sourcesContent":["import type { EventBus, GrafanaTheme2 } from '@grafana/data';\nimport { ThemeChangedEvent } from '@grafana/runtime';\nimport type { ThemeColorMode } from '@grafana/design-tokens';\nimport { useColorMode } from '../components/ColorModeProvider/ColorModeProvider';\n\nconst getThemeColorMode = (isLight: boolean): ThemeColorMode => {\n return isLight ? 'light' : 'dark';\n};\n\nexport interface ColorModeChangeProps {\n getAppEvents: () => EventBus;\n useTheme2: () => GrafanaTheme2;\n}\n\n/**\n * This allows us to register an event listener for when the ThemeChangedEvent\n * is fired, and update the currently active color mode accordingly. It will\n * also determine the color mode on initial registration, and update the context\n * provider accordingly.\n */\nexport const useColorModeChange = ({\n getAppEvents,\n useTheme2,\n}: ColorModeChangeProps): ThemeColorMode => {\n const { setColorMode } = useColorMode();\n const appEvents = getAppEvents();\n\n
|
|
1
|
+
{"version":3,"file":"useColorModeChange.js","sources":["../../../src/hooks/useColorModeChange.ts"],"sourcesContent":["import { useEffect } from 'react';\nimport type { EventBus, GrafanaTheme2 } from '@grafana/data';\nimport { ThemeChangedEvent } from '@grafana/runtime';\nimport type { ThemeColorMode } from '@grafana/design-tokens';\nimport { useColorMode } from '../components/ColorModeProvider/ColorModeProvider';\n\nconst getThemeColorMode = (isLight: boolean): ThemeColorMode => {\n return isLight ? 'light' : 'dark';\n};\n\nexport interface ColorModeChangeProps {\n getAppEvents: () => EventBus;\n useTheme2: () => GrafanaTheme2;\n}\n\n/**\n * This allows us to register an event listener for when the ThemeChangedEvent\n * is fired, and update the currently active color mode accordingly. It will\n * also determine the color mode on initial registration, and update the context\n * provider accordingly.\n */\nexport const useColorModeChange = ({\n getAppEvents,\n useTheme2,\n}: ColorModeChangeProps): ThemeColorMode => {\n const { colorMode, setColorMode } = useColorMode();\n const appEvents = getAppEvents();\n\n /**\n * Longterm the current colorMode should ideally exist outside of useTheme2\n */\n const { isLight } = useTheme2();\n\n useEffect(() => {\n const themeChangedEvent = appEvents.subscribe<ThemeChangedEvent>(\n ThemeChangedEvent,\n ({ payload }) => {\n const newColorMode = getThemeColorMode(payload.isLight);\n setColorMode(newColorMode);\n },\n );\n\n return () => {\n themeChangedEvent.unsubscribe();\n };\n }, [appEvents, setColorMode]);\n\n // Sync color mode when theme changes (runs on mount and when isLight changes)\n useEffect(() => {\n const newColorMode = getThemeColorMode(isLight);\n setColorMode(newColorMode);\n }, [isLight, setColorMode]);\n\n return colorMode;\n};\n"],"names":[],"mappings":";;;;AAMA,MAAM,iBAAA,GAAoB,CAAC,OAAA,KAAqC;AAC9D,EAAA,OAAO,UAAU,OAAA,GAAU,MAAA;AAC7B,CAAA;AAaO,MAAM,qBAAqB,CAAC;AAAA,EACjC,YAAA;AAAA,EACA;AACF,CAAA,KAA4C;AAC1C,EAAA,MAAM,EAAE,SAAA,EAAW,YAAA,EAAa,GAAI,YAAA,EAAa;AACjD,EAAA,MAAM,YAAY,YAAA,EAAa;AAK/B,EAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,SAAA,EAAU;AAE9B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,oBAAoB,SAAA,CAAU,SAAA;AAAA,MAClC,iBAAA;AAAA,MACA,CAAC,EAAE,OAAA,EAAQ,KAAM;AACf,QAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,OAAA,CAAQ,OAAO,CAAA;AACtD,QAAA,YAAA,CAAa,YAAY,CAAA;AAAA,MAC3B;AAAA,KACF;AAEA,IAAA,OAAO,MAAM;AACX,MAAA,iBAAA,CAAkB,WAAA,EAAY;AAAA,IAChC,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAA,EAAW,YAAY,CAAC,CAAA;AAG5B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,MAAM,YAAA,GAAe,kBAAkB,OAAO,CAAA;AAC9C,IAAA,YAAA,CAAa,YAAY,CAAA;AAAA,EAC3B,CAAA,EAAG,CAAC,OAAA,EAAS,YAAY,CAAC,CAAA;AAE1B,EAAA,OAAO,SAAA;AACT;;;;"}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { EventBus, GrafanaTheme2 } from '@grafana/data';
|
|
|
4
4
|
import { ThemeColorMode } from '@grafana/design-tokens';
|
|
5
5
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
6
|
import { IconName } from '@grafana/ui';
|
|
7
|
-
import { Placement } from '@floating-ui/react';
|
|
7
|
+
import { Placement, FloatingPortalProps } from '@floating-ui/react';
|
|
8
8
|
|
|
9
9
|
interface ColorModeChangeProps {
|
|
10
10
|
getAppEvents: () => EventBus;
|
|
@@ -84,6 +84,10 @@ interface PopoverProps {
|
|
|
84
84
|
* Virtual element to anchor the popover to instead of the trigger
|
|
85
85
|
*/
|
|
86
86
|
virtualElement?: React.RefObject<Element>;
|
|
87
|
+
/**
|
|
88
|
+
* DOM element or ID to render the portal into, falls back to document.body
|
|
89
|
+
*/
|
|
90
|
+
portalContainer?: FloatingPortalProps['root'];
|
|
87
91
|
}
|
|
88
92
|
declare const Popover: React$1.ForwardRefExoticComponent<PopoverProps & React$1.RefAttributes<HTMLElement>>;
|
|
89
93
|
|
|
@@ -117,6 +121,39 @@ interface GenericSkeletonProps {
|
|
|
117
121
|
}
|
|
118
122
|
declare const GenericSkeleton: ({ animationDuration }: GenericSkeletonProps) => react_jsx_runtime.JSX.Element;
|
|
119
123
|
|
|
124
|
+
type PortalRoot = FloatingPortalProps['root'];
|
|
125
|
+
interface PortalContextType {
|
|
126
|
+
root: PortalRoot;
|
|
127
|
+
setRoot: (root: PortalRoot) => void;
|
|
128
|
+
}
|
|
129
|
+
interface PortalProviderProps {
|
|
130
|
+
children: ReactNode;
|
|
131
|
+
defaultRoot?: PortalRoot;
|
|
132
|
+
}
|
|
133
|
+
interface UsePortalOptions {
|
|
134
|
+
/** If true, returns document.body instead of throwing when outside provider */
|
|
135
|
+
allowOutsideProvider?: boolean;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Provides a shared context for a portal root, which can be a selector string,
|
|
139
|
+
* an HTMLElement, or null.
|
|
140
|
+
*
|
|
141
|
+
* Wrap your application (or a subtree) in this provider to enable
|
|
142
|
+
* Popover, Tooltip, and other floating components to render correctly.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```tsx
|
|
146
|
+
* <PortalProvider defaultRoot={document.getElementById('grafana-portal-container')}>
|
|
147
|
+
* <App />
|
|
148
|
+
* </PortalProvider>
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
declare const PortalProvider: React__default.FC<PortalProviderProps>;
|
|
152
|
+
/**
|
|
153
|
+
* Use this hook to access the portal root context.
|
|
154
|
+
*/
|
|
155
|
+
declare const usePortal: ({ allowOutsideProvider }?: UsePortalOptions) => PortalContextType;
|
|
156
|
+
|
|
120
157
|
type StackedChartNoDataMessageFormatter = (args: {
|
|
121
158
|
period: string;
|
|
122
159
|
className: string;
|
|
@@ -143,6 +180,30 @@ interface StackedChartCategory {
|
|
|
143
180
|
}
|
|
144
181
|
type StackedChartCategories<T extends string> = Partial<Record<T, StackedChartCategory>>;
|
|
145
182
|
type StackedChartSortOrder = 'largest-first' | 'smallest-first' | 'natural';
|
|
183
|
+
/**
|
|
184
|
+
* Callback function invoked when a mouse event occurs on a chart segment.
|
|
185
|
+
*
|
|
186
|
+
* This is a simplified callback (not a React event handler) that receives
|
|
187
|
+
* segment metadata. It's called after the internal event handling is complete.
|
|
188
|
+
*
|
|
189
|
+
* @param args - Object containing segment metadata
|
|
190
|
+
* @param args.categoryId - The unique identifier of the segment that triggered the event
|
|
191
|
+
* @param args.ref - React ref to the segment's DOM element, useful for positioning tooltips or popovers
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```tsx
|
|
195
|
+
* <StackedChart
|
|
196
|
+
* categories={categories}
|
|
197
|
+
* onSegmentMouseOver={({ categoryId, ref }) => {
|
|
198
|
+
* console.log(`Hovered segment: ${categoryId}`);
|
|
199
|
+
* // ref.current gives you the DOM element if needed
|
|
200
|
+
* }}
|
|
201
|
+
* onSegmentMouseOut={({ categoryId }) => {
|
|
202
|
+
* console.log(`Left segment: ${categoryId}`);
|
|
203
|
+
* }}
|
|
204
|
+
* />
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
146
207
|
type MouseEventHandler = ({ categoryId, ref, }: {
|
|
147
208
|
categoryId: string;
|
|
148
209
|
ref: React.ForwardedRef<HTMLDivElement>;
|
|
@@ -167,11 +228,33 @@ interface StackedChartProps<T extends string> {
|
|
|
167
228
|
*/
|
|
168
229
|
isDimmed?: boolean;
|
|
169
230
|
/**
|
|
170
|
-
*
|
|
231
|
+
* Callback invoked when the mouse enters a chart segment.
|
|
232
|
+
*
|
|
233
|
+
* Receives the segment's `categoryId` and a `ref` to its DOM element.
|
|
234
|
+
* Use this to implement custom hover behavior, analytics tracking,
|
|
235
|
+
* or coordination with external UI elements.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```tsx
|
|
239
|
+
* onSegmentMouseOver={({ categoryId, ref }) => {
|
|
240
|
+
* setActiveCategory(categoryId);
|
|
241
|
+
* // Optional: use ref.current for DOM measurements
|
|
242
|
+
* }}
|
|
243
|
+
* ```
|
|
171
244
|
*/
|
|
172
245
|
onSegmentMouseOver?: MouseEventHandler;
|
|
173
246
|
/**
|
|
174
|
-
*
|
|
247
|
+
* Callback invoked when the mouse leaves a chart segment.
|
|
248
|
+
*
|
|
249
|
+
* Receives the segment's `categoryId` and a `ref` to its DOM element.
|
|
250
|
+
* Use this to clean up hover state or hide related UI elements.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```tsx
|
|
254
|
+
* onSegmentMouseOut={({ categoryId }) => {
|
|
255
|
+
* setActiveCategory(null);
|
|
256
|
+
* }}
|
|
257
|
+
* ```
|
|
175
258
|
*/
|
|
176
259
|
onSegmentMouseOut?: MouseEventHandler;
|
|
177
260
|
/**
|
|
@@ -310,5 +393,5 @@ interface FormatNumberOptions {
|
|
|
310
393
|
*/
|
|
311
394
|
declare const formatNumber: (value: number | string | "loading", options?: FormatNumberOptions) => string;
|
|
312
395
|
|
|
313
|
-
export { ColorMode, ColorModeChangeHandler, ColorModeProvider, ComparisonBadge, ComparisonTooltip, GenericSkeleton, Popover, StackedChart, StackedChartNoData, StackedChartSegment, StackedChartSegmentTooltip, StackedChartSkeleton, calculateComparison, formatNumber, useColorMode, useColorModeChange };
|
|
314
|
-
export type { ColorModeChangeProps, ColorModeContextType, ColorModeProviderProps, ColorModeWrapper, ComparisonResult, ComparisonTooltipProps, FormatNumberOptions, GenericSkeletonProps, PopoverProps, StackedChartCategories, StackedChartCategory, StackedChartNoDataMessageFormatter, StackedChartNoDataProps, StackedChartProps, StackedChartSegmentTooltipProps, StackedChartSkeletonProps, StackedChartSortOrder, StackedChartTooltipContentFormatter };
|
|
396
|
+
export { ColorMode, ColorModeChangeHandler, ColorModeProvider, ComparisonBadge, ComparisonTooltip, GenericSkeleton, Popover, PortalProvider, StackedChart, StackedChartNoData, StackedChartSegment, StackedChartSegmentTooltip, StackedChartSkeleton, calculateComparison, formatNumber, useColorMode, useColorModeChange, usePortal };
|
|
397
|
+
export type { ColorModeChangeProps, ColorModeContextType, ColorModeProviderProps, ColorModeWrapper, ComparisonResult, ComparisonTooltipProps, FormatNumberOptions, GenericSkeletonProps, PopoverProps, PortalContextType, PortalProviderProps, PortalRoot, SegmentMouseEventHandler, StackedChartCategories, StackedChartCategory, StackedChartNoDataMessageFormatter, StackedChartNoDataProps, StackedChartProps, StackedChartSegmentProps, StackedChartSegmentState, StackedChartSegmentTooltipProps, StackedChartSkeletonProps, StackedChartSortOrder, StackedChartTooltipContentFormatter, UsePortalOptions };
|
package/dist/esm/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { ComparisonBadge } from './components/ComparisonBadge/ComparisonBadge.js
|
|
|
5
5
|
export { ComparisonTooltip } from './components/ComparisonTooltip/ComparisonTooltip.js';
|
|
6
6
|
export { GenericSkeleton } from './components/GenericSkeleton/GenericSkeleton.js';
|
|
7
7
|
export { Popover } from './components/Popover/Popover.js';
|
|
8
|
+
export { PortalProvider, usePortal } from './components/PortalProvider/PortalProvider.js';
|
|
8
9
|
export { StackedChart } from './components/StackedChart/StackedChart.js';
|
|
9
10
|
export { StackedChartNoData } from './components/StackedChartNoData/StackedChartNoData.js';
|
|
10
11
|
export { StackedChartSegment } from './components/StackedChartSegment/StackedChartSegment.js';
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Grafana Labs",
|
|
3
3
|
"name": "@grafana/components",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.32",
|
|
6
6
|
"description": "Product Design Engineering Components for Grafana",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -68,7 +68,6 @@
|
|
|
68
68
|
"@eslint/eslintrc": "^3.3.1",
|
|
69
69
|
"@eslint/js": "^9.37.0",
|
|
70
70
|
"@grafana/eslint-config": "^9.0.0",
|
|
71
|
-
"@grafana/runtime": "^11.5.3",
|
|
72
71
|
"@grafana/tsconfig": "^2.0.1",
|
|
73
72
|
"@rollup/plugin-commonjs": "^29",
|
|
74
73
|
"@rollup/plugin-eslint": "^9.2.0",
|
|
@@ -120,6 +119,7 @@
|
|
|
120
119
|
"@floating-ui/react": "^0.27.16",
|
|
121
120
|
"@grafana/data": "^11.5.3",
|
|
122
121
|
"@grafana/design-tokens": "^0.0.26",
|
|
122
|
+
"@grafana/runtime": "^11.5.3",
|
|
123
123
|
"@grafana/ui": "^11.5.3",
|
|
124
124
|
"clsx": "^2.1.1",
|
|
125
125
|
"react-useportal": "^1.0.19"
|