import { h, createComponent, useSpinnerProps, useSpinner, ref, computed, debounce, watch, onDeactivated, onActivated, onBeforeUnmount, hMergeSlot, withDirectives, getCurrentInstance, setVerticalScrollPosition, setHorizontalScrollPosition } from './__federation_expose_Modules-a9c6a6fc.js';
import { useDarkProps, useDark } from './use-dark-b88930fe.js';
import { QResizeObserver } from './QResizeObserver-41bc340b.js';
import { QScrollObserver } from './QScrollObserver-8d9d49fa.js';
import { TouchPan } from './TouchPan-1bf8458c.js';
import { between } from './format-2fa4ccf2.js';

const svg = [
  h('g', [
    h('path', {
      fill: 'none',
      stroke: 'currentColor',
      'stroke-width': '5',
      'stroke-miterlimit': '10',
      d: 'M58.4,51.7c-0.9-0.9-1.4-2-1.4-2.3s0.5-0.4,1.4-1.4 C70.8,43.8,79.8,30.5,80,15.5H70H30H20c0.2,15,9.2,28.1,21.6,32.3c0.9,0.9,1.4,1.2,1.4,1.5s-0.5,1.6-1.4,2.5 C29.2,56.1,20.2,69.5,20,85.5h10h40h10C79.8,69.5,70.8,55.9,58.4,51.7z'
    }),
    h('clipPath', {
      id: 'uil-hourglass-clip1'
    }, [
      h('rect', {
        x: '15',
        y: '20',
        width: ' 70',
        height: '25'
      }, [
        h('animate', {
          attributeName: 'height',
          from: '25',
          to: '0',
          dur: '1s',
          repeatCount: 'indefinite',
          values: '25;0;0',
          keyTimes: '0;0.5;1'
        }),
        h('animate', {
          attributeName: 'y',
          from: '20',
          to: '45',
          dur: '1s',
          repeatCount: 'indefinite',
          values: '20;45;45',
          keyTimes: '0;0.5;1'
        })
      ])
    ]),
    h('clipPath', {
      id: 'uil-hourglass-clip2'
    }, [
      h('rect', {
        x: '15',
        y: '55',
        width: ' 70',
        height: '25'
      }, [
        h('animate', {
          attributeName: 'height',
          from: '0',
          to: '25',
          dur: '1s',
          repeatCount: 'indefinite',
          values: '0;25;25',
          keyTimes: '0;0.5;1'
        }),
        h('animate', {
          attributeName: 'y',
          from: '80',
          to: '55',
          dur: '1s',
          repeatCount: 'indefinite',
          values: '80;55;55',
          keyTimes: '0;0.5;1'
        })
      ])
    ]),
    h('path', {
      d: 'M29,23c3.1,11.4,11.3,19.5,21,19.5S67.9,34.4,71,23H29z',
      'clip-path': 'url(#uil-hourglass-clip1)',
      fill: 'currentColor'
    }),
    h('path', {
      d: 'M71.6,78c-3-11.6-11.5-20-21.5-20s-18.5,8.4-21.5,20H71.6z',
      'clip-path': 'url(#uil-hourglass-clip2)',
      fill: 'currentColor'
    }),
    h('animateTransform', {
      attributeName: 'transform',
      type: 'rotate',
      from: '0 50 50',
      to: '180 50 50',
      repeatCount: 'indefinite',
      dur: '1s',
      values: '0 50 50;0 50 50;180 50 50',
      keyTimes: '0;0.7;1'
    })
  ])
];

const QSpinnerHourglass = createComponent({
  name: 'QSpinnerHourglass',

  props: useSpinnerProps,

  setup (props) {
    const { cSize, classes } = useSpinner(props);

    return () => h('svg', {
      class: classes.value,
      width: cSize.value,
      height: cSize.value,
      viewBox: '0 0 100 100',
      preserveAspectRatio: 'xMidYMid',
      xmlns: 'http://www.w3.org/2000/svg'
    }, svg)
  }
});

const axisList = [ 'vertical', 'horizontal' ];
const dirProps = {
  vertical: { offset: 'offsetY', scroll: 'scrollTop', dir: 'down', dist: 'y' },
  horizontal: { offset: 'offsetX', scroll: 'scrollLeft', dir: 'right', dist: 'x' }
};
const panOpts = {
  prevent: true,
  mouse: true,
  mouseAllDir: true
};

const getMinThumbSize = size => (size >= 250 ? 50 : Math.ceil(size / 5));

const QScrollArea = createComponent({
  name: 'QScrollArea',

  props: {
    ...useDarkProps,

    thumbStyle: Object,
    verticalThumbStyle: Object,
    horizontalThumbStyle: Object,

    barStyle: [ Array, String, Object ],
    verticalBarStyle: [ Array, String, Object ],
    horizontalBarStyle: [ Array, String, Object ],

    contentStyle: [ Array, String, Object ],
    contentActiveStyle: [ Array, String, Object ],

    delay: {
      type: [ String, Number ],
      default: 1000
    },

    visible: {
      type: Boolean,
      default: null
    },

    tabindex: [ String, Number ],

    onScroll: Function
  },

  setup (props, { slots, emit }) {
    // state management
    const tempShowing = ref(false);
    const panning = ref(false);
    const hover = ref(false);

    // other...
    const container = {
      vertical: ref(0),
      horizontal: ref(0)
    };

    const scroll = {
      vertical: {
        ref: ref(null),
        position: ref(0),
        size: ref(0)
      },

      horizontal: {
        ref: ref(null),
        position: ref(0),
        size: ref(0)
      }
    };

    const { proxy } = getCurrentInstance();

    const isDark = useDark(props, proxy.$q);

    let timer = null, panRefPos;

    const targetRef = ref(null);

    const classes = computed(() =>
      'q-scrollarea'
      + (isDark.value === true ? ' q-scrollarea--dark' : '')
    );

    scroll.vertical.percentage = computed(() => {
      const diff = scroll.vertical.size.value - container.vertical.value;
      if (diff <= 0) { return 0 }
      const p = between(scroll.vertical.position.value / diff, 0, 1);
      return Math.round(p * 10000) / 10000
    });
    scroll.vertical.thumbHidden = computed(() =>
      (
        (props.visible === null ? hover.value : props.visible) !== true
        && tempShowing.value === false
        && panning.value === false
      ) || scroll.vertical.size.value <= container.vertical.value + 1
    );
    scroll.vertical.thumbStart = computed(() =>
      scroll.vertical.percentage.value * (container.vertical.value - scroll.vertical.thumbSize.value)
    );
    scroll.vertical.thumbSize = computed(() =>
      Math.round(
        between(
          container.vertical.value * container.vertical.value / scroll.vertical.size.value,
          getMinThumbSize(container.vertical.value),
          container.vertical.value
        )
      )
    );
    scroll.vertical.style = computed(() => {
      return {
        ...props.thumbStyle,
        ...props.verticalThumbStyle,
        top: `${ scroll.vertical.thumbStart.value }px`,
        height: `${ scroll.vertical.thumbSize.value }px`
      }
    });
    scroll.vertical.thumbClass = computed(() =>
      'q-scrollarea__thumb q-scrollarea__thumb--v absolute-right'
      + (scroll.vertical.thumbHidden.value === true ? ' q-scrollarea__thumb--invisible' : '')
    );
    scroll.vertical.barClass = computed(() =>
      'q-scrollarea__bar q-scrollarea__bar--v absolute-right'
      + (scroll.vertical.thumbHidden.value === true ? ' q-scrollarea__bar--invisible' : '')
    );

    scroll.horizontal.percentage = computed(() => {
      const diff = scroll.horizontal.size.value - container.horizontal.value;
      if (diff <= 0) { return 0 }
      const p = between(Math.abs(scroll.horizontal.position.value) / diff, 0, 1);
      return Math.round(p * 10000) / 10000
    });
    scroll.horizontal.thumbHidden = computed(() =>
      (
        (props.visible === null ? hover.value : props.visible) !== true
        && tempShowing.value === false
        && panning.value === false
      ) || scroll.horizontal.size.value <= container.horizontal.value + 1
    );
    scroll.horizontal.thumbStart = computed(() =>
      scroll.horizontal.percentage.value * (container.horizontal.value - scroll.horizontal.thumbSize.value)
    );
    scroll.horizontal.thumbSize = computed(() =>
      Math.round(
        between(
          container.horizontal.value * container.horizontal.value / scroll.horizontal.size.value,
          getMinThumbSize(container.horizontal.value),
          container.horizontal.value
        )
      )
    );
    scroll.horizontal.style = computed(() => {
      return {
        ...props.thumbStyle,
        ...props.horizontalThumbStyle,
        [ proxy.$q.lang.rtl === true ? 'right' : 'left' ]: `${ scroll.horizontal.thumbStart.value }px`,
        width: `${ scroll.horizontal.thumbSize.value }px`
      }
    });
    scroll.horizontal.thumbClass = computed(() =>
      'q-scrollarea__thumb q-scrollarea__thumb--h absolute-bottom'
      + (scroll.horizontal.thumbHidden.value === true ? ' q-scrollarea__thumb--invisible' : '')
    );
    scroll.horizontal.barClass = computed(() =>
      'q-scrollarea__bar q-scrollarea__bar--h absolute-bottom'
      + (scroll.horizontal.thumbHidden.value === true ? ' q-scrollarea__bar--invisible' : '')
    );

    const mainStyle = computed(() => (
      scroll.vertical.thumbHidden.value === true && scroll.horizontal.thumbHidden.value === true
        ? props.contentStyle
        : props.contentActiveStyle
    ));

    const thumbVertDir = [ [
      TouchPan,
      e => { onPanThumb(e, 'vertical'); },
      void 0,
      { vertical: true, ...panOpts }
    ] ];

    const thumbHorizDir = [ [
      TouchPan,
      e => { onPanThumb(e, 'horizontal'); },
      void 0,
      { horizontal: true, ...panOpts }
    ] ];

    function getScroll () {
      const info = {};

      axisList.forEach(axis => {
        const data = scroll[ axis ];

        info[ axis + 'Position' ] = data.position.value;
        info[ axis + 'Percentage' ] = data.percentage.value;
        info[ axis + 'Size' ] = data.size.value;
        info[ axis + 'ContainerSize' ] = container[ axis ].value;
      });

      return info
    }

    // we have lots of listeners, so
    // ensure we're not emitting same info
    // multiple times
    const emitScroll = debounce(() => {
      const info = getScroll();
      info.ref = proxy;
      emit('scroll', info);
    }, 0);

    function localSetScrollPosition (axis, offset, duration) {
      if (axisList.includes(axis) === false) {
        console.error('[QScrollArea]: wrong first param of setScrollPosition (vertical/horizontal)');
        return
      }

      const fn = axis === 'vertical'
        ? setVerticalScrollPosition
        : setHorizontalScrollPosition;

      fn(targetRef.value, offset, duration);
    }

    function updateContainer ({ height, width }) {
      let change = false;

      if (container.vertical.value !== height) {
        container.vertical.value = height;
        change = true;
      }

      if (container.horizontal.value !== width) {
        container.horizontal.value = width;
        change = true;
      }

      change === true && startTimer();
    }

    function updateScroll ({ position }) {
      let change = false;

      if (scroll.vertical.position.value !== position.top) {
        scroll.vertical.position.value = position.top;
        change = true;
      }

      if (scroll.horizontal.position.value !== position.left) {
        scroll.horizontal.position.value = position.left;
        change = true;
      }

      change === true && startTimer();
    }

    function updateScrollSize ({ height, width }) {
      if (scroll.horizontal.size.value !== width) {
        scroll.horizontal.size.value = width;
        startTimer();
      }

      if (scroll.vertical.size.value !== height) {
        scroll.vertical.size.value = height;
        startTimer();
      }
    }

    function onPanThumb (e, axis) {
      const data = scroll[ axis ];

      if (e.isFirst === true) {
        if (data.thumbHidden.value === true) {
          return
        }

        panRefPos = data.position.value;
        panning.value = true;
      }
      else if (panning.value !== true) {
        return
      }

      if (e.isFinal === true) {
        panning.value = false;
      }

      const dProp = dirProps[ axis ];
      const containerSize = container[ axis ].value;

      const multiplier = (data.size.value - containerSize) / (containerSize - data.thumbSize.value);
      const distance = e.distance[ dProp.dist ];
      const pos = panRefPos + (e.direction === dProp.dir ? 1 : -1) * distance * multiplier;

      setScroll(pos, axis);
    }

    function onMousedown (evt, axis) {
      const data = scroll[ axis ];

      if (data.thumbHidden.value !== true) {
        const offset = evt[ dirProps[ axis ].offset ];
        if (offset < data.thumbStart.value || offset > data.thumbStart.value + data.thumbSize.value) {
          const pos = offset - data.thumbSize.value / 2;
          setScroll(pos / container[ axis ].value * data.size.value, axis);
        }

        // activate thumb pan
        if (data.ref.value !== null) {
          data.ref.value.dispatchEvent(new MouseEvent(evt.type, evt));
        }
      }
    }

    function onVerticalMousedown (evt) {
      onMousedown(evt, 'vertical');
    }

    function onHorizontalMousedown (evt) {
      onMousedown(evt, 'horizontal');
    }

    function startTimer () {
      tempShowing.value = true;

      timer !== null && clearTimeout(timer);
      timer = setTimeout(() => {
        timer = null;
        tempShowing.value = false;
      }, props.delay);

      props.onScroll !== void 0 && emitScroll();
    }

    function setScroll (offset, axis) {
      targetRef.value[ dirProps[ axis ].scroll ] = offset;
    }

    function onMouseenter () {
      hover.value = true;
    }

    function onMouseleave () {
      hover.value = false;
    }

    let scrollPosition = null;

    watch(() => proxy.$q.lang.rtl, rtl => {
      if (targetRef.value !== null) {
        setHorizontalScrollPosition(
          targetRef.value,
          Math.abs(scroll.horizontal.position.value) * (rtl === true ? -1 : 1)
        );
      }
    });

    onDeactivated(() => {
      scrollPosition = {
        top: scroll.vertical.position.value,
        left: scroll.horizontal.position.value
      };
    });

    onActivated(() => {
      if (scrollPosition === null) { return }

      const scrollTarget = targetRef.value;

      if (scrollTarget !== null) {
        setHorizontalScrollPosition(scrollTarget, scrollPosition.left);
        setVerticalScrollPosition(scrollTarget, scrollPosition.top);
      }
    });

    onBeforeUnmount(emitScroll.cancel);

    // expose public methods
    Object.assign(proxy, {
      getScrollTarget: () => targetRef.value,
      getScroll,
      getScrollPosition: () => ({
        top: scroll.vertical.position.value,
        left: scroll.horizontal.position.value
      }),
      getScrollPercentage: () => ({
        top: scroll.vertical.percentage.value,
        left: scroll.horizontal.percentage.value
      }),
      setScrollPosition: localSetScrollPosition,
      setScrollPercentage (axis, percentage, duration) {
        localSetScrollPosition(
          axis,
          percentage
            * (scroll[ axis ].size.value - container[ axis ].value)
            * (axis === 'horizontal' && proxy.$q.lang.rtl === true ? -1 : 1),
          duration
        );
      }
    });

    return () => {
      return h('div', {
        class: classes.value,
        onMouseenter,
        onMouseleave
      }, [
        h('div', {
          ref: targetRef,
          class: 'q-scrollarea__container scroll relative-position fit hide-scrollbar',
          tabindex: props.tabindex !== void 0 ? props.tabindex : void 0
        }, [
          h('div', {
            class: 'q-scrollarea__content absolute',
            style: mainStyle.value
          }, hMergeSlot(slots.default, [
            h(QResizeObserver, {
              debounce: 0,
              onResize: updateScrollSize
            })
          ])),

          h(QScrollObserver, {
            axis: 'both',
            onScroll: updateScroll
          })
        ]),

        h(QResizeObserver, {
          debounce: 0,
          onResize: updateContainer
        }),

        h('div', {
          class: scroll.vertical.barClass.value,
          style: [ props.barStyle, props.verticalBarStyle ],
          'aria-hidden': 'true',
          onMousedown: onVerticalMousedown
        }),

        h('div', {
          class: scroll.horizontal.barClass.value,
          style: [ props.barStyle, props.horizontalBarStyle ],
          'aria-hidden': 'true',
          onMousedown: onHorizontalMousedown
        }),

        withDirectives(
          h('div', {
            ref: scroll.vertical.ref,
            class: scroll.vertical.thumbClass.value,
            style: scroll.vertical.style.value,
            'aria-hidden': 'true'
          }),
          thumbVertDir
        ),

        withDirectives(
          h('div', {
            ref: scroll.horizontal.ref,
            class: scroll.horizontal.thumbClass.value,
            style: scroll.horizontal.style.value,
            'aria-hidden': 'true'
          }),
          thumbHorizDir
        )
      ])
    }
  }
});

const tryoutServingAPI_vue_vue_type_style_index_0_scoped_bc29889c_lang = '';

export { QScrollArea, QSpinnerHourglass };
