// Based on React UI ScrollView ❤️:
// https://react-ui.io/components/scroll-view

// 1. Overflow decorators are implemented as pseudo elements. This way we can transition their visibility easily.
//
// 2. Stack overflow decorators over viewport content while keeping the content interactive.
//
//    - Overflow decorators are positioned absolutely over the `.ScrollView`, with auto `z-index` (this is
//      important!), and with `overflow: hidden` to clip the shadows (ie. its pseudo elements) when offset is applied.
//    - The `.ScrollView__viewport` remains interactive thanks to `pointer-events: none` on overflow decorators.
//
// 3. Make the `.ScrollView__content`'s bounding rectangle spread beyond the part visible through `.ScrollView__viewport`.
//
// 4. Prevent undesired vertical scrolling that may occur with tables inside.
//
// 5. Make `.ScrollView` adjust to flexible layouts.
//
// 6. Hide content overflowing in the other direction because scrollbars would be unreachable under scrolling shadows.
//
// 7. Make the height of vertical ScrollView modifiable by a CSS variable. This backdoor is necessary for the composition
//    of ScrollView and ModalDialog. In Safari, as long as the dialog uses flex layout along with other min/max height
//    calculations, the ScrollView can't be set to `height: 100%` because it would cause the ScrollView to collapse.
//
//    Recommended solution for ModalDialog:
//
//    - set `--scroll-view-vertical-height: auto` on the ScrollView's parent.
//
//    Other possible (yet more complicated and less DX friendly) solutions:
//
//    - require `display: flex` on the ScrollView's parent,
//    - wrap the ScrollView inside ModalDialog with another element (see https://react-ui.io/components/modal),
//    - rewrite ModalDialog to use `display: grid` instead of `display: flex` 🎉.

@use '../../settings/transitions';
@use 'theme';

.ScrollView {
    position: relative; // 2.
    display: flex;
    flex-direction: column;
    width: 100%;
}

// 1.
.ScrollView__overflowDecorators {
    position: absolute; // 2.
    width: 100%; // 2.
    height: 100%; // 2.
    overflow: hidden; // 2.
    pointer-events: none; // 2.

    &::before,
    &::after {
        content: '';
        position: absolute;
        z-index: 2; // 2.
        display: block;
        visibility: hidden;
        opacity: 0;
        transition-property: visibility, opacity, transform;
        transition-duration: transitions.$duration-200;
    }
}

.ScrollView__overflowDecorators--shadows {
    &::before {
        background: var(--scroll-view-start-shadow-background, theme.$start-shadow-background);
    }

    &::after {
        background: var(--scroll-view-end-shadow-background, theme.$end-shadow-background);
    }
}

.ScrollView__viewport {
    z-index: 1; // 2.
    width: 100%;
    scroll-behavior: smooth;
}

.ScrollView--vertical {
    height: var(--scroll-view-vertical-height, 100%); // 7.
    min-height: 0; // 5.
}

.ScrollView--vertical > .ScrollView__viewport {
    height: 100%;
    overflow-x: hidden; // 6.
    overflow-y: auto; // 2.
}

.ScrollView--horizontal {
    min-width: 0; // 5.
}

.ScrollView--horizontal > .ScrollView__viewport {
    overflow-x: auto; // 2.
    overflow-y: hidden; // 4., 6.
}

// stylelint-disable-next-line selector-max-class -- We need to be specific here.
.ScrollView--horizontal > .ScrollView__viewport > .ScrollView__content {
    display: inline-flex; // 3.
    min-width: 100%;
    vertical-align: top;
}

.ScrollView--vertical > .ScrollView__overflowDecorators::before,
.ScrollView--vertical > .ScrollView__overflowDecorators::after {
    right: 0;
    left: 0;
    width: auto;
}

.ScrollView--vertical > .ScrollView__overflowDecorators::before {
    top: 0;
}

.ScrollView--vertical > .ScrollView__overflowDecorators::after {
    bottom: 0;
}

.ScrollView--vertical > .ScrollView__overflowDecorators--borders::before {
    border-top: theme.$border-width theme.$border-style theme.$border-color;
}

.ScrollView--vertical > .ScrollView__overflowDecorators--borders::after {
    border-bottom: theme.$border-width theme.$border-style theme.$border-color;
}

.ScrollView--vertical > .ScrollView__overflowDecorators--shadows::before {
    --gradient-angle: 180deg;

    height: theme.$start-shadow-size;
    transform: translateY(#{theme.$start-shadow-initial-offset});
}

.ScrollView--vertical > .ScrollView__overflowDecorators--shadows::after {
    --gradient-angle: 0;

    height: theme.$end-shadow-size;
    transform: translateY(#{-1 * theme.$end-shadow-initial-offset});
}

.ScrollView--horizontal > .ScrollView__overflowDecorators::before,
.ScrollView--horizontal > .ScrollView__overflowDecorators::after {
    top: 0;
    bottom: 0;
    height: auto;
}

.ScrollView--horizontal > .ScrollView__overflowDecorators::before {
    left: 0;
}

.ScrollView--horizontal > .ScrollView__overflowDecorators::after {
    right: 0;
}

.ScrollView--horizontal > .ScrollView__overflowDecorators--borders::before {
    border-left: theme.$border-width theme.$border-style theme.$border-color;
}

.ScrollView--horizontal > .ScrollView__overflowDecorators--borders::after {
    border-right: theme.$border-width theme.$border-style theme.$border-color;
}

.ScrollView--horizontal > .ScrollView__overflowDecorators--shadows::before {
    --gradient-angle: 90deg;

    width: theme.$start-shadow-size;
    transform: translateX(#{theme.$start-shadow-initial-offset});
}

.ScrollView--horizontal > .ScrollView__overflowDecorators--shadows::after {
    --gradient-angle: 270deg;

    width: theme.$end-shadow-size;
    transform: translateX(#{-1 * theme.$end-shadow-initial-offset});
}

.is-scrolled-at-start > .ScrollView__overflowDecorators::before {
    visibility: visible;
    opacity: 1;
    transform: translate(0, 0);
}

.is-scrolled-at-end > .ScrollView__overflowDecorators::after {
    visibility: visible;
    opacity: 1;
    transform: translate(0, 0);
}

.ScrollView--scrollbarDisabled > .ScrollView__viewport {
    scrollbar-width: none;

    &::-webkit-scrollbar {
        display: none;
    }
}
