/* @oracle/oraclejet-preact: undefined */
import { jsxs, Fragment, jsx } from 'preact/jsx-runtime';
import { styles as styles$1, dimensionStyle } from './PRIVATE_Chart/themes/ChartStyles.css.js';
import { T as TrackResizeContainer } from './TrackResizeContainer-04a2c642.js';
import { u as useTextDimensions } from './useTextDimensions-e08928cc.js';
import { u as useCssVars } from './useCssVars-d72a8439.js';
import { useState, useRef, useMemo } from 'preact/hooks';
import { G as Gridlines, P as PlotArea } from './Gridlines-6098cb5b.js';
import { u as useId } from './useId-03dbfdf0.js';
import { A as Axis } from './Axis-9e78ee61.js';
import { u as useChartViewport } from './useChartViewport-1e396126.js';
import { u as updateViewportFromOverview, a as getAxesPosition, b as getScrollBarSpace, c as getLayoutInfo, d as updateScrollBarSpace, e as getAvailSpace, f as getOuterGaps } from './layoutUtils-5d62f2b4.js';
import { u as useChartNav } from './useChartNav-19d0b379.js';
import { m as mergeProps } from './mergeProps-88ea8306.js';
import { a as useSelectDrill, u as useChartDatatipAndCursor } from './useSelectDrill-f4781439.js';
import { u as useUser } from './useUser-1cd223a9.js';
import { u as useTestId } from './useTestId-9b504481.js';
import { g as getChartVars } from './cssUtils-71c7d7b0.js';
import { u as useChartContextMenu } from './useChartContextMenu-61fe46b8.js';
import { u as useChartDnd } from './useChartDnd-fc7ba21c.js';
import { a as getElementData } from './eventsUtils-e5fc62d5.js';
import './accUtils-ce2d6588.js';
import { c as calculateOffset } from './layoutUtils-d7613d0c.js';
import { u as useTooltip } from './useTooltip-89ca3f3e.js';
import './logger-c92f309c.js';
import './LayerHost-e6402730.js';
import 'preact/compat';
import './TooltipContentStyles.styles.css';
import './hooks/UNSAFE_useTooltip/themes/redwood/TooltipContentBaseTheme.styles.css';
import './hooks/UNSAFE_useTooltip/themes/redwood/TooltipContentVariants.css.js';
import './tooltipUtils-768450a7.js';
import { u as useChartMarquee } from './useChartMarquee-7cd47205.js';
import { u as useVisTouchResponse } from './useVisTouchResponse-a59ab166.js';
import { m as merge } from './stringUtils-16f617bc.js';
import { O as OverviewContext, u as useOverviewContext } from './useOverviewContext-79377674.js';
import { a as ScaleLinear } from './scale-3b7850b9.js';
import { O as OverviewSlidingWindow } from './OverviewSlidingWindow-8936526e.js';
import { styles } from './PRIVATE_VisOverview/themes/VisOverview.css.js';
import { S as ScrollBar } from './ScrollBar-a431a4f0.js';

function getNextGroup(info, viewportEndIndex, isGroupNavigable) {
    const groupIndex = info.groupIndex + 1;
    if (groupIndex >= viewportEndIndex) {
        return;
    }
    if (isGroupNavigable(groupIndex)) {
        return { groupIndex };
    }
    return getNextGroup({ groupIndex }, viewportEndIndex, isGroupNavigable);
}
function getPreviousGroup(info, isGroupNavigable) {
    const groupIndex = info.groupIndex - 1;
    if (groupIndex < 0) {
        return;
    }
    if (isGroupNavigable(groupIndex)) {
        return { groupIndex };
    }
    return getPreviousGroup({ groupIndex }, isGroupNavigable);
}
function getGroupNavUtil(groups, renderedGroups, xIndexExtent, drilling, isRtl) {
    const isGroupNavigable = (groupIndex) => {
        const groupsDrilling = groups[renderedGroups[groupIndex]].drilling;
        return (drilling === 'on' || drilling === 'groupsOnly') && groupsDrilling != 'off';
    };
    const getDefaultNavGroup = (info) => {
        if (xIndexExtent.startIndex > renderedGroups[info.groupIndex]) {
            info.groupIndex = 0;
            return info;
        }
        else if (xIndexExtent.endIndex < renderedGroups[info.groupIndex]) {
            info.groupIndex = renderedGroups.length - 1;
            return info;
        }
        return;
    };
    const getNextNavGroup = (info, arrow) => {
        let nextGroup = getDefaultNavGroup(info);
        if (nextGroup)
            return nextGroup;
        if (arrow === 'ArrowRight') {
            nextGroup = isRtl
                ? getPreviousGroup(info, isGroupNavigable)
                : getNextGroup(info, renderedGroups.length, isGroupNavigable);
        }
        else {
            nextGroup = isRtl
                ? getNextGroup(info, renderedGroups.length, isGroupNavigable)
                : getPreviousGroup(info, isGroupNavigable);
        }
        return nextGroup || info;
    };
    return { getDefaultNavGroup, getNextNavGroup };
}

/**
 * @license
 * Copyright (c) %FIRST_YEAR% %CURRENT_YEAR%, Oracle and/or its affiliates.
 * Licensed under The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 * @ignore
 */
function useTextTruncation({ getTextAndBounds, width, isRtl }) {
    const [text, setText] = useState();
    const bounds = useRef();
    const { tooltipContent, tooltipProps } = useTooltip({
        text,
        position: 'top-start',
        offset: calculateOffset(isRtl, width, bounds.current)
    });
    const onPointerMove = (event) => {
        const textAndBounds = getTextAndBounds(event.target);
        if (textAndBounds) {
            bounds.current = textAndBounds.bounds;
            setText(textAndBounds.text);
        }
        else {
            setText(undefined);
        }
    };
    return {
        tooltipContent,
        tooltipProps: mergeProps({ onPointerMove }, tooltipProps)
    };
}

/**
 * @license
 * Copyright (c) %FIRST_YEAR% %CURRENT_YEAR%, Oracle and/or its affiliates.
 * Licensed under The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 * @ignore
 */
function getWindowCoords(isRtl, xViewportExtent, xAxisExtent, yViewportExtent, yAxisExtent, plotAreaSpace) {
    const xDomain = [xAxisExtent.min, xAxisExtent.max];
    const xRange = (isRtl
        ? [plotAreaSpace.x + plotAreaSpace.width, plotAreaSpace.x]
        : [plotAreaSpace.x, plotAreaSpace.x + plotAreaSpace.width]);
    const xScale = new ScaleLinear(xDomain, xRange);
    const yDomain = [yAxisExtent.min, yAxisExtent.max];
    const yRange = [plotAreaSpace.y + plotAreaSpace.height, plotAreaSpace.y];
    const yScale = new ScaleLinear(yDomain, yRange);
    const windowX = xScale.transform(xViewportExtent.viewportMin);
    const windowWidth = Math.abs(xScale.transform(xViewportExtent.viewportMax) - xScale.transform(xViewportExtent.viewportMin));
    return {
        windowX: isRtl ? windowX - windowWidth : windowX + 0.5,
        windowWidth: windowWidth - 0.5,
        windowY: yScale.transform(yViewportExtent.viewportMax),
        windowHeight: Math.abs(yScale.transform(yViewportExtent.viewportMax) - yScale.transform(yViewportExtent.viewportMin)),
        xScale,
        yScale
    };
}

function OverviewBackground({ x, width, height, y, windowX, windowHeight, windowWidth, windowY }) {
    return (jsxs(Fragment, { children: [jsx("rect", { x: x, y: y, width: Math.max(0, windowX - x), height: height, class: styles.overviewBackground }), jsx("rect", { x: windowX + windowWidth, width: Math.max(0, x + width - windowX - windowWidth), y: y, height: height, class: styles.overviewBackground }), jsx("rect", { x: windowX, y: y, height: Math.max(0, windowY - y), width: windowWidth, class: styles.overviewBackground }), jsx("rect", { x: windowX, y: windowY + windowHeight, width: windowWidth, class: styles.overviewBackground, height: Math.max(y + height - windowY - windowHeight, 0) })] }));
}

function getRenderer(xAxisExtent, isRtl, overviewXScale, plotAreaSpace, windowCoords, hasHandles, onViewportChange) {
    return {
        slidingWindow: (jsx(OverviewSlidingWindow, { ...plotAreaSpace, ...windowCoords, hasHandles: hasHandles, onWindowDimsChange: (props) => {
                updateViewportFromOverview(xAxisExtent, isRtl, windowCoords.windowX, windowCoords.windowWidth, props.deltaX, props.deltaWidth, overviewXScale, onViewportChange);
            } })),
        background: jsx(OverviewBackground, { ...plotAreaSpace, ...windowCoords })
    };
}

const OVERVIEW_GAP = 10;
const chartVars = getChartVars();
function ChartWithDimensions({ width, height, selectedIds, hiddenIds, hideAndShowBehavior = 'none', orientation = 'vertical', xAxis, yAxis, plotArea, dragMode = 'user', series, groups, isStacked = false, getDataItem, selectionMode = 'none', drilling = 'off', dataCursorPosition, onSelectionChange, isDataCursorEnabled, dataCursorStyle, onViewportChange, onDataCursorPositionChange, onItemDrill, onGroupDrill, onItemHover, onItemFocus, datatip, zoomAndScroll = 'off', offset, getNavUtil, getDataItemPos, getGapRatio, valueFormats, findNearest, getMarkerInfo, isRtl, children, testId, renderGridLinesInFront, isDataXAxis, contextMenuConfig, overview = 'off', defaultOverviewContentRenderer, isOverview, yAxisSize, overviewRenderer, ...props }) {
    const testIdProps = useTestId(testId);
    const rootRef = useRef(null);
    const isTestEnv = testIdProps['data-testid'] !== undefined;
    const isHoriz = orientation === 'horizontal';
    const { xAxisPosition, yAxisPosition } = getAxesPosition(yAxis, isHoriz, isRtl);
    const { resolvedVars, cssContent } = useCssVars(chartVars);
    const colors = Array.from(Array(12)).map((_, index) => {
        return resolvedVars[`color${index + 1}`];
    });
    const { textMeasureContent, getTextDimensions } = useTextDimensions();
    let availSpace = getAvailSpace(width, height);
    if (isOverview && yAxisSize) {
        const w = availSpace.width - yAxisSize;
        const gaps = getOuterGaps(w, height);
        availSpace.width -= yAxisSize - 2 * gaps.width;
        availSpace.x += yAxisSize - gaps.width;
    }
    const isTimeAxis = xAxis?.timeAxisType != null;
    const updatedSpace = getScrollBarSpace(isTimeAxis, availSpace, zoomAndScroll, xAxisPosition, overview);
    let scrollDims = updatedSpace.scrollDims;
    availSpace = updatedSpace.availSpace;
    const { locale } = useUser();
    const { x, y, width: _width, height: _height } = availSpace;
    const labelFontSize = resolvedVars['labelFontSize'];
    const layoutInfo = useMemo(() => {
        const hiddenSet = new Set(hiddenIds);
        return getLayoutInfo(series, groups, getDataItem, xAxis, yAxis, { x, y, width: _width, height: _height }, // availSpace
        hiddenSet, hideAndShowBehavior, isHoriz, isRtl, isStacked, labelFontSize, offset, locale, getTextDimensions, isTestEnv, isDataXAxis);
    }, [
        x,
        y,
        _width,
        _height,
        getDataItem,
        getTextDimensions,
        groups,
        hiddenIds,
        hideAndShowBehavior,
        isDataXAxis,
        isHoriz,
        isRtl,
        isStacked,
        isTestEnv,
        locale,
        offset,
        labelFontSize,
        series,
        xAxis,
        yAxis
    ]);
    const { xProps, xScale, xViewportExtent, xAxisExtent, xIndexExtent, xAxisMinExtent, yViewportExtent, yAxisExtent, groupWidth, yProps, yScale, yMaxDim, yMajorTicks, xMajorTicks, yMinorTicks, xMinorTicks, plotAreaSpace, xSpace, ySpace, idToDataMap, formatAxisLabel, formatYValue } = layoutInfo;
    scrollDims = updateScrollBarSpace(scrollDims, xAxisPosition === 'bottom', isRtl, yMaxDim);
    const gapRatio = getGapRatio(xIndexExtent.startIndex, xIndexExtent.endIndex);
    const getNextChartItem = getNavUtil(xIndexExtent.startIndex, xIndexExtent.endIndex);
    const renderedGroupsIndex = xProps.tickLabels.map(({ index }) => index + xIndexExtent.startIndex);
    const { getNextNavGroup, getDefaultNavGroup } = getGroupNavUtil(groups, renderedGroupsIndex, xIndexExtent, // TODO : JET-71301 | Scatter should have different nav utils call.
    drilling, isRtl);
    const { ignoreSelectPointerUp, cursor, yAxisCursor, marqueeProps, marqueeContent, toggleButtonContent, isPointInsideMarquee, dragMode: mode } = useChartMarquee({
        plotAreaSpace,
        xSpace,
        ySpace,
        dragMode,
        chartWidth: width,
        isMultiSelection: selectionMode === 'multiple',
        onViewportChange,
        isZoomScroll: zoomAndScroll === 'live',
        xAxisExtent,
        xScale,
        selectedIds,
        getDataById: (id) => idToDataMap.get(id),
        onSelectionChange,
        viewportMax: xViewportExtent.viewportMax,
        viewportMin: xViewportExtent.viewportMin,
        isRtl,
        xAxisMinExtent
    });
    const { touchResponse, touchResponseStyle } = useVisTouchResponse({
        type: 'auto',
        supportsTouchDragGestures: mode !== 'off',
        rootRef
    });
    const { activeId, focusedItemInfo, hoveredItemInfo, focusedGroupInfo, navProps, onFocusUpdate } = useChartNav({
        rootRef,
        getNextChartItem,
        getNextNavGroup,
        getDefaultNavGroup,
        touchResponse,
        onItemHover,
        onItemFocus,
        drilling,
        xIndexExtent
    });
    const onContextMenuDismissed = (gesture) => {
        if (gesture === 'keyboard') {
            onFocusUpdate();
        }
    };
    const getTextAndBounds = (target) => {
        if (target != rootRef.current) {
            const dataSet = getElementData(rootRef, target);
            const text = dataSet?.['ojText'];
            if (!text) {
                return;
            }
            if (text === xAxis?.title) {
                return {
                    text,
                    bounds: xProps.titleProps?.dims
                };
            }
            else if (text === yAxis?.title) {
                return {
                    text,
                    bounds: yProps.titleProps?.dims
                };
            }
            else if (dataSet?.['ojGroupIndex']) {
                const index = parseInt(dataSet['ojGroupIndex']);
                return {
                    bounds: xProps.tickLabels[index].dims,
                    text: text
                };
            }
        }
        if (target === rootRef.current && focusedGroupInfo.isFocusVisible) {
            const group = groups[focusedGroupInfo.groupIndex];
            return {
                bounds: xProps.tickLabels[focusedGroupInfo.groupIndex].dims,
                text: group.name || group.id
            };
        }
        return;
    };
    const { tooltipContent, tooltipProps } = useTextTruncation({
        getTextAndBounds,
        width,
        isRtl
    });
    const viewportProps = useChartViewport({
        rootRef,
        width,
        height,
        xViewportExtent,
        yViewportExtent,
        xAxisExtent,
        yAxisExtent,
        xScale,
        yScale,
        plotAreaSpace,
        isRtl,
        isHoriz,
        zoomAndScroll,
        onViewportChange
    });
    const ignoreAsTrigger = (target) => {
        if (!target) {
            return false;
        }
        const dataset = getElementData(rootRef, target);
        if ((dataset &&
            (dataset['ojPrivateObject'] === 'marquee' ||
                dataset['ojPrivateObject'] === 'dragModeControls' ||
                dataset['ojPrivateObject'] === 'scrollBar')) ||
            ignoreSelectPointerUp) {
            return true;
        }
        return false;
    };
    const { selectDrillProps, selectionContent } = useSelectDrill({
        selectionMode,
        selection: [...selectedIds],
        onChange: onSelectionChange,
        rootRef,
        drilling,
        onItemDrill,
        onGroupDrill,
        focusedGroupInfo,
        focusedItemInfo,
        groups,
        getDataItem,
        getDataById: (id) => idToDataMap.get(id),
        ignoreAsTrigger
    });
    const findNearestData = findNearest(xScale, yScale, groupWidth, gapRatio);
    const getDataItemPosition = getDataItemPos(xScale, yScale, groupWidth, gapRatio);
    const [datatipDisabled, setDatatipDisabled] = useState(false);
    const { datatipContent, dataCursorContent, datatipProps: { 'aria-describedby': datatipAriaDescribedby, ...datatipProps } } = useChartDatatipAndCursor({
        series,
        groups,
        width,
        height,
        findNearest: findNearestData,
        plotAreaSpace,
        onDataCursorPositionChange,
        isDataCursorEnabled,
        dataCursorPosition,
        dataCursorStyle,
        hoveredItemInfo,
        focusedItemInfo,
        getDataItem,
        getMarkerInfo,
        getDataItemPos: getDataItemPosition,
        datatip,
        valueFormats,
        isHoriz,
        touchResponse,
        isDisabled: datatipDisabled,
        xScale: xScale,
        yScale,
        timeAxisType: xAxis?.timeAxisType,
        formatAxisLabel,
        formatYValue,
        hasXYValues: isDataXAxis
    });
    const isGroupInteractive = (index) => {
        if (xAxis?.timeAxisType != null) {
            return false;
        }
        const groupDrill = groups[index]?.drilling;
        if (groupDrill === 'on') {
            return true;
        }
        if (groupDrill != 'off' && (drilling === 'on' || drilling === 'groupsOnly')) {
            return true;
        }
        return false;
    };
    const plotAreaClipPathId = useId();
    const { startIndex: xStartIndex, endIndex: xEndIndex } = xIndexExtent;
    const gridLines = (jsx(Gridlines, { plotArea: plotArea, yMinorTicks: yMinorTicks, xMinorTicks: xMinorTicks, xScale: xScale, yScale: yScale, isLog: yAxis?.scale === 'log', yTicks: yMajorTicks, xTicks: xMajorTicks, yAxisPosition: yAxisPosition, isDataXAxis: isDataXAxis }));
    const hasData = series.length > 0 && groups.length > 0;
    const { contextMenuContent, contextMenuProps } = useChartContextMenu({
        isRtl,
        width,
        height,
        getDataItemPosition,
        series,
        groups,
        getDataItem,
        focusedItemInfo,
        rootRef,
        xAxisTitle: xAxis?.title,
        yAxisTitle: yAxis?.title,
        contextMenuConfig: hasData ? contextMenuConfig : undefined,
        onContextMenuDismissed
    });
    const [dragOver, setDragOver] = useState({
        accepted: undefined,
        type: ''
    });
    const { draggable, dndProps, dndContent } = useChartDnd({
        onDrag: props.onDrag,
        onDragStart: props.onDragStart,
        onDragEnd: props.onDragEnd,
        onDragEnter: props.onDragEnter,
        onDragLeave: props.onDragLeave,
        onDragOver: props.onDragOver,
        onDrop: props.onDrop,
        itemsDraggable: props.itemsDraggable,
        groupDraggable: props.groupDraggable,
        rootRef,
        groups,
        series,
        selectedIds,
        getDataItem,
        xSpace,
        ySpace,
        plotAreaSpace,
        setDragOver,
        setDatatipDisabled,
        onSelectionChange
    });
    const eventsProps = mergeProps(navProps, selectDrillProps, viewportProps, datatipProps, marqueeProps, tooltipProps, contextMenuProps, dndProps);
    const overviewContentRenderer = overview != 'off' && (overview === 'on' || !overview.renderer)
        ? defaultOverviewContentRenderer
        : undefined;
    const { background, slidingWindow } = overviewRenderer(plotAreaSpace);
    return (jsxs(Fragment, { children: [getTextDimensions && resolvedVars['labelFontSize'] != undefined && (jsxs("div", { tabIndex: isOverview ? undefined : 0, draggable: draggable, ref: rootRef, "aria-activedescendant": activeId, "aria-label": props['aria-label'], "aria-labelledby": props['aria-labelledby'], "aria-describedby": merge([props['aria-describedby'], datatipAriaDescribedby]), style: { ...touchResponseStyle }, role: isOverview ? undefined : 'application', className: styles$1.baseChartStyle, "data-oj-private-selection-mode": isTestEnv ? selectionMode : undefined, ...testIdProps, ...(isOverview ? {} : eventsProps), children: [jsxs("svg", { width: "100%", height: scrollDims.height != 0 && overview != 'off'
                            ? `${Math.ceil((updatedSpace.availSpace.height + OVERVIEW_GAP) * 100) / height}%`
                            : '100%', children: [jsx("clipPath", { id: `${plotAreaClipPathId}`, children: jsx("rect", { ...plotAreaSpace }) }), background, jsx(PlotArea, { color: plotArea?.color, dragOverStyle: dragOver.type !== 'plotArea' ? 'none' : dragOver.accepted ? 'accept' : 'reject', yScale: yScale, hasAxisLine: !isOverview, cursor: cursor, isLog: yAxis?.scale === 'log', availSpace: plotAreaSpace, xAxisPosition: xAxisPosition, isDataXAxis: isDataXAxis, isRtl: isRtl }), !renderGridLinesInFront && gridLines, jsx(Axis, { ...yProps, axisPosition: yAxisPosition, isRtl: isRtl, cursor: yAxisCursor, availSpace: ySpace, dragOverStyle: dragOver.type !== 'yAxis' ? 'none' : dragOver.accepted ? 'accept' : 'reject' }), jsx(Axis, { ...xProps, isRtl: isRtl, axisPosition: xAxisPosition, isTextInteractive: isGroupInteractive, activeId: activeId, cursor: cursor, focusedGroupIndex: focusedGroupInfo.isFocusVisible ? focusedGroupInfo.groupIndex : undefined, availSpace: xSpace, dragOverStyle: dragOver.type !== 'xAxis' ? 'none' : dragOver.accepted ? 'accept' : 'reject' }), jsxs("g", { "clip-path": `url(#${plotAreaClipPathId})`, children: [children({
                                        xStartIndex,
                                        xEndIndex,
                                        colors,
                                        xScale: xScale,
                                        yScale,
                                        isPointInsideMarquee,
                                        defaultFontSize: resolvedVars['labelFontSize'],
                                        gapRatio,
                                        activeId,
                                        focusedItemInfo,
                                        hoveredItemInfo,
                                        getTextDimensions,
                                        groupWidth
                                    }), renderGridLinesInFront && gridLines, dataCursorContent] }), slidingWindow, zoomAndScroll === 'live' && !isOverview && (jsx(ScrollBar, { availSpace: scrollDims, isRtl: isRtl, viewport: xViewportExtent, axisExtent: xAxisExtent, isHoriz: xAxisPosition === 'bottom' })), marqueeContent] }), jsx(OverviewContext.Provider, { value: {
                            yAxisSize: ySpace.width,
                            isOverview: true,
                            width,
                            height: scrollDims.height,
                            overviewRenderer: (overviewChartPlotArea) => {
                                const { xScale: overviewXScale, ...windowCoords } = getWindowCoords(isRtl, xViewportExtent, xAxisExtent, yViewportExtent, yAxisExtent, overviewChartPlotArea);
                                return getRenderer(xAxisExtent, isRtl, overviewXScale, overviewChartPlotArea, windowCoords, true, onViewportChange);
                            }
                        }, children: !isOverview && overview !== 'off' && overviewContentRenderer && (jsx("div", { style: { width, height: scrollDims.height }, children: overviewContentRenderer() })) }), toggleButtonContent, datatipContent, tooltipContent, contextMenuContent, selectionContent, dndContent] })), textMeasureContent, cssContent] }));
}

function Chart({ width, height, ...props }) {
    // TODO: reevaluate how we handle empty data
    const { isOverview, overviewRenderer, yAxisSize, width: overviewWidth, height: overviewHeight } = useOverviewContext();
    let chartWidth = width;
    let chartHeight = height;
    if (chartWidth === undefined && isOverview && overviewWidth !== undefined) {
        chartWidth = `${overviewWidth}px`;
    }
    if (chartHeight === undefined && isOverview && overviewHeight !== undefined) {
        chartHeight = `${overviewHeight}px`;
    }
    return (jsx(TrackResizeContainer, { width: chartWidth, height: chartHeight, class: dimensionStyle, children: (width, height) => width || height ? (jsx(ChartWithDimensions, { width: width, height: height, ...props, yAxisSize: yAxisSize, isOverview: isOverview, overviewRenderer: overviewRenderer })) : undefined }));
}

export { Chart as C };
//# sourceMappingURL=Chart-4ec13697.js.map
