Commit 145551ba authored by Дмитрий Малюгин's avatar Дмитрий Малюгин 🕓
Browse files

feat: 'Carousel' in process ("size", "buttonsBelow" and "theme" are remaining)

parent d20aa819
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import Knob from '@components/Knob/Knob.vue';
import Rating from '@components/Rating/Rating.vue';
import HomeIcon from '@icons/Mono/HomeIcon.vue';
import ProgressBar from '@components/ProgressBar/ProgressBar.vue';
import Carousel from '@components/Carousel/Carousel.vue';

const visibleDrawer = ref(false);
const sliderOptions: ISliderOptions[] = [
@@ -201,6 +202,31 @@ const openDrawer = () => (visibleDrawer.value = true);
  <Checkbox v-model="activeCheckbox" size="large" />
  <Checkbox v-model="activeCheckbox" size="huge" />
  <ProgressBar v-model="pbValue" />
  <Carousel
    style="margin: 20px"
    :itemsProps="[
      {
        index: 1,
        text: 'This is SPARTA!',
      },
      {
        index: 2,
        text: 'This is the second item!',
      },
      {
        index: 3,
        text:
          'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi atque blanditiis debitis distinctio, doloribus,\n' +
          '        eius est eveniet excepturi facere id iure laboriosam laborum libero, minus nesciunt nostrum nulla repellat\n' +
          '        veritatis.',
      },
    ]"
  >
    <template v-slot="item: unknown">
      <h2 style="text-align: center; margin-bottom: 20px">Element {{ item?.index }}</h2>
      <p>{{ item?.text }}</p></template
    >
  </Carousel>
  {{ tableData[1] }}
  <Table
    center
@@ -211,6 +237,7 @@ const openDrawer = () => (visibleDrawer.value = true);
    theme="black"
    stripedRows
    paginator
    editable
    :no-editing-settings="{
      cells: [[0, 0]],
    }"
+3 −1
Original line number Diff line number Diff line
@@ -81,10 +81,12 @@ export interface IPaginatorProps {

export interface ICarouselProps {
  itemsProps: unknown[];
  width?: string;
  innerWidth?: string;
  size?: TSize;
  perView?: number;
  perScroll?: number;
  circular?: boolean;
  buttonsBelow?: boolean;
  theme?: TThemeColor;
  darknessTheme?: TDarkness;
}
+65 −57
Original line number Diff line number Diff line
@@ -14,25 +14,14 @@ const meta: Meta = {
    },
  },
  argTypes: {
    buttons: { control: 'boolean' },
    showLabel: { control: 'boolean' },
    colorAsTheme: { control: 'boolean' },
    textBold: { control: 'boolean' },
    min: { control: 'number' },
    max: { control: 'number' },
    step: { control: 'number' },
    fontSize: { control: 'text' },
    textBefore: { control: 'text' },
    textAfter: { control: 'text' },
    colorGaps: { control: 'object' },
    itemsProps: { control: 'object' },
    innerWidth: { control: 'text' },
    perView: { control: 'number' },
    perScroll: { control: 'number' },
    circular: { control: 'boolean' },
    buttonsBelow: { control: 'boolean' },
    size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] },
    background: { control: 'color' },
    darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] },
    darknessNegativeTheme: {
      control: 'select',
      options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'],
    },
    darknessColor: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] },
    theme: {
      control: 'select',
      options: [
@@ -53,46 +42,6 @@ const meta: Meta = {
        'black',
      ],
    },
    negativeTheme: {
      control: 'select',
      options: [
        'white',
        'blue',
        'sky',
        'cyan',
        'teal',
        'green',
        'yellow',
        'orange',
        'pink',
        'fuchsia',
        'purple',
        'indigo',
        'rose',
        'red',
        'black',
      ],
    },
    color: {
      control: 'select',
      options: [
        'white',
        'blue',
        'sky',
        'cyan',
        'teal',
        'green',
        'yellow',
        'orange',
        'pink',
        'fuchsia',
        'purple',
        'indigo',
        'rose',
        'red',
        'black',
      ],
    },
  },
} satisfies Meta<typeof Carousel>;

@@ -103,3 +52,62 @@ type Story = StoryObj<typeof meta>;
export const Simple: Story = {
  args: {},
};

export const Half: Story = {
  args: {
    circular: true,
    perView: 2,
    perScroll: 1,
    itemsProps: [
      {
        header: 'First',
        text: 'Some text',
      },
      {
        header: 'Second',
        text: 'Some text',
      },
      {
        header: 'Third',
        text: 'Some text',
      },
      {
        header: 'Forth',
        text: 'Some text',
      },
    ],
  },
};

export const Full: Story = {
  args: {
    circular: true,
    perView: 2,
    perScroll: 2,

    itemsProps: [
      {
        header: 'First',
        text: 'Some text',
      },
      {
        header: 'Second',
        text: 'Some text',
      },
      {
        header: 'Third',
        text: 'Some text',
      },
      {
        header: 'Forth',
        text: 'Some text',
      },
      {
        header: 'Fifth',
        text: 'Some text',
      },
    ],

    buttonsBelow: true,
  },
};
+76 −8
Original line number Diff line number Diff line
@@ -5,19 +5,26 @@ import { computed, ref } from 'vue';
import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common';
import ArrowLeftShortIcon from '@icons/Mono/ArrowLeftShortIcon.vue';
import ArrowRightShortIcon from '@icons/Mono/ArrowRightShortIcon.vue';
import { defaultProps, getNewValue } from './helpers';

const props = withDefaults(defineProps<ICarouselProps>(), {
  itemsProps: () => [],
  size: 'normal',
  innerWidth: '300px',
  perView: 1,
  perScroll: 1,
  theme: 'white',
  darknessTheme: '500',
});

const current = ref(1);

const itemsLength = computed(() => Math.ceil(props.itemsProps.length / props.perView));
const itemsLength = computed(() => props.itemsProps?.length ?? 3);
const color = computed(() => convertThemeToColor(props.theme, props.darknessTheme));
const textColor = computed(() => convertThemeToTextColor(props.theme, props.darknessTheme));
const isStartDisabled = computed(() => current.value === 1);
const isEndDisabled = computed(() => current.value === itemsLength.value);
const isStartDisabled = computed(() => (props.circular ? false : current.value === 1 || itemsLength.value <= 1));
const isEndDisabled = computed(() =>
  props.circular ? false : current.value === Math.ceil(itemsLength.value / props.perView) || !itemsLength.value,
);
const iconSize = computed(() => {
  const size = props.size;
  if (size === 'normal') return '10';
@@ -25,22 +32,83 @@ const iconSize = computed(() => {
  if (size === 'huge') return '18';
  return '7';
});
const itemWidth = computed(() => `calc(${props.innerWidth} / ${props.perView}`);
const translate = computed(() => `translateX(calc(-${props.innerWidth} / ${props.perView} * ${current.value - 1}))`);
</script>

<template>
  <section :style="`width: ${width}; min-height: 100px`" class="carouselContainer">
    <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isStartDisabled">
  <section class="carouselContainer">
    <CarouselArrowContainer
      @click="!isStartDisabled ? (current = getNewValue('-', current, itemsLength, perScroll, perView)) : null"
      :textColor="textColor"
      :color="color"
      :disable="isStartDisabled"
    >
      <ArrowLeftShortIcon :color="isStartDisabled ? '#aaa' : textColor" :size="iconSize" />
    </CarouselArrowContainer>
    <slot />
    <CarouselArrowContainer :textColor="textColor" :color="color" :disable="isEndDisabled">
    <div class="content">
      <ul class="list">
        <li v-for="item of Array(itemsLength).keys()" :key="item" class="item">
          <slot v-bind="itemsProps?.[item]" :key="current - 1" />
          <div v-if="!$slots.default && !itemsProps">
            <h2 style="text-align: center; margin-bottom: 10px">{{ defaultProps[item].header }}</h2>
            <p>
              {{ defaultProps[item].text }}
            </p>
          </div>
          <div v-else-if="!$slots.default">
            <h2 style="text-align: center; margin-bottom: 10px">{{ itemsProps[item].header }}</h2>
            <p>
              {{ itemsProps[item].text }}
            </p>
          </div>
        </li>
      </ul>
    </div>
    <CarouselArrowContainer
      @click="!isEndDisabled ? (current = getNewValue('+', current, itemsLength, perScroll, perView)) : null"
      :textColor="textColor"
      :color="color"
      :disable="isEndDisabled"
    >
      <ArrowRightShortIcon :color="isEndDisabled ? '#aaa' : textColor" :size="iconSize" />
    </CarouselArrowContainer>
    <ul class="buttons">
      <li
        v-for="item of Array(itemsLength).keys()"
        :key="item"
        class="button"
        :style="`width: ${iconSize}px; height: ${iconSize}px`"
      ></li>
    </ul>
  </section>
</template>

<style scoped>
.carouselContainer {
  display: flex;
  min-height: 100px;
  position: relative;
}
.content {
  max-width: v-bind(innerWidth);
  overflow: hidden;
}
.list {
  display: flex;
  transform: v-bind(translate);
  transition: transform 0.3s ease-out;
}
.item {
  min-width: v-bind(itemWidth);
}
.buttons {
  position: absolute;
  bottom: 0;
  left: 0;
  transform: translateX(-50%);
}
.button {
  background-color: v-bind(color);
}
</style>
+19 −31
Original line number Diff line number Diff line
@@ -7,10 +7,9 @@ defineProps<{
</script>

<template>
  <div class="arrowContainer">
  <div
    :class="[
        'icon',
      'arrowContainer',
      {
        disable,
      },
@@ -24,6 +23,7 @@ defineProps<{
        },
      ]"
    ></div>
    <div class="icon">
      <slot />
    </div>
  </div>
@@ -31,49 +31,37 @@ defineProps<{

<style scoped>
.arrowContainer {
  width: 50px;
  position: relative;
  min-width: 50px;
  min-height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}
.icon {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  line-height: 1.2;
  color: v-bind(textColor);
}
.icon::before {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  z-index: -1;
  background-color: v-bind(color);
}
.icon:hover > .bg {
.arrowContainer:hover > .bg {
  background-color: v-bind(textColor);
  opacity: 0.1;
}
.icon:active > .bg {
.arrowContainer:active > .bg {
  opacity: 0.2;
}
.bg {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 10px;
  z-index: 5;
  border-radius: 50%;
  background-color: transparent;
  opacity: 0;
  border-radius: 5px;
  background-color: transparent;
  transition: all 0.2s ease;
}
.disable {
Loading