"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.RangeSliderControl = void 0;
var _lodash = require("lodash");
var _react = _interopRequireWildcard(require("react"));
var _eui = require("@elastic/eui");
var _range_slider_embeddable = require("../embeddable/range_slider_embeddable");
var _control_error_component = require("../../control_group/component/control_error_component");
require("./range_slider.scss");
var _constants = require("../../constants");
var _use_field_formatter = require("../../hooks/use_field_formatter");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
/*
 * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
 * or more contributor license agreements. Licensed under the Elastic License
 * 2.0 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

const RangeSliderControl = () => {
  /** Controls Services Context */
  const rangeSlider = (0, _range_slider_embeddable.useRangeSlider)();
  const rangeSliderRef = (0, _react.useRef)(null);

  // Embeddable explicit input
  const id = rangeSlider.select(state => state.explicitInput.id);
  const value = rangeSlider.select(state => state.explicitInput.value);

  // Embeddable cmponent state
  const min = rangeSlider.select(state => state.componentState.min);
  const max = rangeSlider.select(state => state.componentState.max);
  const error = rangeSlider.select(state => state.componentState.error);
  const fieldSpec = rangeSlider.select(state => state.componentState.field);
  const isInvalid = rangeSlider.select(state => state.componentState.isInvalid);

  // Embeddable output
  const isLoading = rangeSlider.select(state => state.output.loading);
  const dataViewId = rangeSlider.select(state => state.output.dataViewId);

  // React component state
  const [displayedValue, setDisplayedValue] = (0, _react.useState)(value !== null && value !== void 0 ? value : ['', '']);
  const fieldFormatter = (0, _use_field_formatter.useFieldFormatter)({
    dataViewId,
    fieldSpec
  });
  const debouncedOnChange = (0, _react.useMemo)(() => (0, _lodash.debounce)(newRange => {
    rangeSlider.dispatch.setSelectedRange(newRange);
  }, 750), [rangeSlider.dispatch]);

  /**
   * This will recalculate the displayed min/max of the range slider to allow for selections smaller
   * than the `min` and larger than the `max`
   */
  const [displayedMin, displayedMax] = (0, _react.useMemo)(() => {
    if (min === undefined || max === undefined) return [-Infinity, Infinity];
    const selectedValue = value !== null && value !== void 0 ? value : ['', ''];
    const [selectedMin, selectedMax] = [selectedValue[0] === '' ? min : parseFloat(selectedValue[0]), selectedValue[1] === '' ? max : parseFloat(selectedValue[1])];
    return [Math.min(selectedMin, min), Math.max(selectedMax, max !== null && max !== void 0 ? max : Infinity)];
  }, [min, max, value]);

  /**
   * The following `useEffect` ensures that the changes to the value that come from the embeddable (for example,
   * from the `reset` button on the dashboard or via chaining) are reflected in the displayed value
   */
  (0, _react.useEffect)(() => {
    setDisplayedValue(value !== null && value !== void 0 ? value : ['', '']);
  }, [value]);
  const ticks = (0, _react.useMemo)(() => {
    return [{
      value: min !== null && min !== void 0 ? min : -Infinity,
      label: fieldFormatter(String(min))
    }, {
      value: max !== null && max !== void 0 ? max : Infinity,
      label: fieldFormatter(String(max))
    }];
  }, [min, max, fieldFormatter]);
  const levels = (0, _react.useMemo)(() => {
    return [{
      min: min !== null && min !== void 0 ? min : -Infinity,
      max: max !== null && max !== void 0 ? max : Infinity,
      color: 'success'
    }];
  }, [min, max]);
  const disablePopover = (0, _react.useMemo)(() => isLoading || displayedMin === -Infinity || displayedMax === Infinity || displayedMin === displayedMax, [isLoading, displayedMin, displayedMax]);
  const getCommonInputProps = (0, _react.useCallback)(({
    inputValue,
    testSubj,
    placeholder
  }) => {
    return {
      isInvalid,
      placeholder,
      readOnly: false,
      // overwrites `canOpenPopover` to ensure that the inputs are always clickable
      className: 'rangeSliderAnchor__fieldNumber',
      'data-test-subj': `rangeSlider__${testSubj}`,
      value: inputValue === placeholder ? '' : inputValue
    };
  }, [isInvalid]);
  return error ? /*#__PURE__*/_react.default.createElement(_control_error_component.ControlError, {
    error: error
  }) : /*#__PURE__*/_react.default.createElement("span", {
    className: "rangeSliderAnchor__button",
    "data-test-subj": `range-slider-control-${id}`
  }, /*#__PURE__*/_react.default.createElement(_eui.EuiDualRange, {
    ref: rangeSliderRef,
    id: id,
    fullWidth: true,
    showTicks: true,
    ticks: ticks,
    levels: levels,
    min: displayedMin,
    max: displayedMax,
    isLoading: isLoading,
    inputPopoverProps: {
      panelMinWidth: _constants.MIN_POPOVER_WIDTH
    },
    onMouseUp: () => {
      // when the pin is dropped (on mouse up), cancel any pending debounced changes and force the change
      // in value to happen instantly (which, in turn, will re-calculate the min/max for the slider due to
      // the `useEffect` above.
      debouncedOnChange.cancel();
      rangeSlider.dispatch.setSelectedRange(displayedValue);
    },
    readOnly: disablePopover,
    showInput: 'inputWithPopover',
    "data-test-subj": "rangeSlider__slider",
    minInputProps: getCommonInputProps({
      inputValue: displayedValue[0],
      testSubj: 'lowerBoundFieldNumber',
      placeholder: String(min !== null && min !== void 0 ? min : -Infinity)
    }),
    maxInputProps: getCommonInputProps({
      inputValue: displayedValue[1],
      testSubj: 'upperBoundFieldNumber',
      placeholder: String(max !== null && max !== void 0 ? max : Infinity)
    }),
    value: [displayedValue[0] || displayedMin, displayedValue[1] || displayedMax],
    onChange: ([minSelection, maxSelection]) => {
      setDisplayedValue([String(minSelection), String(maxSelection)]);
      debouncedOnChange([String(minSelection), String(maxSelection)]);
    }
  }));
};
exports.RangeSliderControl = RangeSliderControl;