From 209112d09ec612fca3f4f6e1376ed1beac558922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=BB=D1=8E=D0=B3=D0=B8=D0=BD?= <d.malygin@iqdev.digital> Date: Wed, 8 Jan 2025 20:53:35 +0500 Subject: [PATCH] feat: almost ended with Table filter but with bugs and add Popup logics for buttons --- package.json | 17 +- src/App.vue | 200 +---------- src/Playground.vue | 318 ++++++++++++++++++ src/common/constants/icons.ts | 4 +- src/common/interfaces/componentsProps.ts | 3 + src/stories/components/Popup/Popup.vue | 61 ++-- src/stories/components/Table/Table.stories.ts | 4 - src/stories/components/Table/Table.vue | 165 +++++---- src/stories/components/Table/helpers.ts | 46 +++ .../{CheckmarkIcon.vue => CheckMarkIcon.vue} | 0 yarn.lock | 263 +++++++-------- 11 files changed, 651 insertions(+), 430 deletions(-) create mode 100644 src/Playground.vue create mode 100644 src/stories/components/Table/helpers.ts rename src/stories/icons/Mono/{CheckmarkIcon.vue => CheckMarkIcon.vue} (100%) diff --git a/package.json b/package.json index 5c66f1f..d29dba7 100644 --- a/package.json +++ b/package.json @@ -19,14 +19,13 @@ "vue": "^3.5.12" }, "devDependencies": { - "@chromatic-com/storybook": "3.2.2", - "@storybook/addon-essentials": "8.4.5", - "@storybook/addon-interactions": "8.4.5", - "@storybook/addon-onboarding": "8.4.5", - "@storybook/blocks": "8.4.5", - "@storybook/test": "8.4.5", - "@storybook/vue3": "8.4.5", - "@storybook/vue3-vite": "8.4.5", + "@chromatic-com/storybook": "^3.2.3", + "@storybook/addon-essentials": "^8.4.7", + "@storybook/addon-interactions": "^8.4.7", + "@storybook/blocks": "^8.4.7", + "@storybook/test": "^8.4.7", + "@storybook/vue3": "^8.4.7", + "@storybook/vue3-vite": "^8.4.7", "@tsconfig/node22": "^22.0.0", "@types/jsdom": "^21.1.7", "@types/node": "^22.10.1", @@ -42,7 +41,7 @@ "jsdom": "^25.0.1", "npm-run-all2": "^7.0.1", "prettier": "^3.3.3", - "storybook": "8.4.5", + "storybook": "^8.4.7", "typescript": "~5.6.3", "vite": "^5.4.10", "vite-plugin-vue-devtools": "^7.5.4", diff --git a/src/App.vue b/src/App.vue index 12b543a..8d91ab7 100644 --- a/src/App.vue +++ b/src/App.vue @@ -34,7 +34,7 @@ import ChartLineIcon from '@stories/icons/Mono/ChartLineIcon.vue'; import ChartPieIcon from '@stories/icons/Mono/ChartPieIcon.vue'; import ChatIcon from '@stories/icons/Mono/ChatIcon.vue'; import ChatWritingIcon from '@stories/icons/Mono/ChatWritingIcon.vue'; -import CheckmarkIcon from '@stories/icons/Mono/CheckmarkIcon.vue'; +import CheckMarkIcon from '@stories/icons/Mono/CheckMarkIcon.vue'; import ChemistryFlaskIcon from '@stories/icons/Mono/ChemistryFlaskIcon.vue'; import CodeIcon from '@stories/icons/Mono/CodeIcon.vue'; import CoinsIcon from '@stories/icons/Mono/CoinsIcon.vue'; @@ -107,15 +107,8 @@ import TableIcon from '@stories/icons/Mono/TableIcon.vue'; import TrashIcon from '@stories/icons/Mono/TrashIcon.vue'; import UserIcon from '@stories/icons/Mono/UserIcon.vue'; import ArrowsVerticalIcon from '@stories/icons/Mono/ArrowsVerticalIcon.vue'; -import SelectButton from '@stories/components/SelectButton/SelectButton.vue'; -import ToggleSwitch from '@stories/components/ToggleSwitch/ToggleSwitch.vue'; import TriangleIcon from '@stories/icons/Mono/TriangleIcon.vue'; -import Button from '@stories/components/Button/Button.vue'; -import Slider from '@stories/components/Slider/Slider.vue'; -import type { ISBOption, ISliderOptions } from '@interfaces/componentsProp'; -import Modal from '@stories/components/Modal/Modal.vue'; -import MenuDial from '@stories/components/MenuDial/MenuDial.vue'; -import Popup from '@stories/components/Popup/Popup.vue'; +import Playground from '@/Playground.vue'; const gentleIcons = { Age18Icon, @@ -152,7 +145,7 @@ const gentleIcons = { ChartPieIcon, ChatIcon, ChatWritingIcon, - CheckmarkIcon, + CheckMarkIcon, ChemistryFlaskIcon, CodeIcon, CoinsIcon, @@ -226,74 +219,6 @@ const gentleIcons = { TriangleIcon, UserIcon, }; -const visibleDrawer = ref(false); -const sliderOptions: ISliderOptions[] = [ - { - label: 0, - value: 0, - color: 'red', - }, - { - label: 2, - value: 2, - color: 'orange', - }, - { - label: 4, - value: 4, - color: 'yellow', - }, - { - label: 6, - value: 6, - color: 'green', - }, - { - label: 8, - value: 8, - color: 'sky', - }, - { - label: 10, - value: 10, - color: 'purple', - }, - { - label: 12, - value: 12, - color: 'purple', - }, - { - label: 14, - value: 14, - color: 'purple', - }, - { - label: 16, - value: 16, - color: 'purple', - }, - { - label: 18, - }, -]; -const options: ISBOption[] = [ - { - label: 'First', - textStyle: 'bold', - iconPosition: 'top', - }, - { - label: 'Second', - }, -]; -const visible = ref(false); -const onClose = () => console.log('close!'); -const value = ref(); -const active = ref(false); -const popupActive = ref(false); -const popupActive2 = ref(false); -const sliderValue = ref(1); </script> <template> @@ -305,112 +230,7 @@ const sliderValue = ref(1); <span class="iconName">{{ icon[0].slice(0, -4) }}</span> </li> </ul> - <h2 class="title gradient-text">Playground</h2> - <button class="testButton" @click="visibleDrawer = !visibleDrawer">Ðажми менÑ</button> - <div class="hui" style="width: 500px; height: 500px; background-color: gray"></div> - <Popup v-model:active="popupActive" parentSelector=".hui" theme="sky"> - <Button - @click=" - () => { - popupActive = false; - visible = true; - } - " - label="Открыть модальное окно" - /> - </Popup> - <Popup v-model:active="popupActive2" theme="sky" - >Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet fugiat harum maiores placeat soluta, vel velit - voluptas. Accusamus aut, error et minima neque praesentium, ratione, reprehenderit repudiandae saepe ut vero! - Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet fugiat harum maiores placeat soluta, vel velit - voluptas. Accusamus aut, error et minima neque praesentium, ratione, reprehenderit repudiandae saepe ut - vero!</Popup - > - - <Modal v-model:visible="visible" theme="red" @onClose="onClose" - ><template #header>huuuuuuuuuuui</template>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque - explicabo, facere fuga hic id impedit magnam maiores minima necessitatibus, nemo nesciunt nihil officia, pariatu - nemo nesciunt nihil officia, pariatur praesentium quas quisquam repellat saepe temporibus? Lorem ipsum dolor sit - amet, consectetur adipisicing elit. Eaque explicabo, facere fuga hic id impedit magnam maiores minima - necessitatibus, nemo nesciunt nihil officia, pariatu nemo nesciunt nihil officia, pariatur praesentium quas - quisquam repellat saepe temporibus?</Modal - > - <MenuDial - v-model:active="active" - theme="sky" - direction="right" - darknessTheme="600" - :items="[ - { - label: 'font-family', - theme: 'green', - color: 'red', - darknessColor: '500', - link: 'https://developer.mozilla.org/en-US/docs/Web/CSS/font-family', - linkBlank: true, - textStyle: 'bold', - }, - { - label: 'Second', - theme: 'red', - color: 'sky', - darknessColor: '500', - darknessTheme: '600', - textStyle: 'italic', - }, - ]" - > - <template #1IconBefore> - <AnchorLinkIcon size="20" color="white" /> - </template> - <template #2IconBefore> - <CrossIcon color="white" /> - </template> - <template #2IconAfter> - <CrossIcon color="white" /> - </template> - </MenuDial> - <Slider - v-model:value="sliderValue" - :options="sliderOptions" - width="400" - min="0" - max="18" - step="2" - backgroundColor="black" - theme="blue" - isSmooth - /> - <Button @click="visible = true" textColor="white" theme="sky" label="I'm a button"></Button> - <SelectButton :options="options" size="large" v-model:value="value"> - <template #1Icon> - <TrashIcon /> - </template> - </SelectButton> - <ToggleSwitch /> - <Drawer v-model:visible="visibleDrawer" theme="sky" :dismissible="false" closeIcon="CropIcon"> - <template #header>Ðто - Drawer</template> - <p> - pizdwertyuki lokl,kmjhgfwewesrdty ukilo,kmjngeartyukikdhgfgjhklj.,kga Lorem ipsum dolor sit amet, consectetur - adipisicing elit. Amet deleniti, esse in ipsam quis sapiente tempore voluptas. Aperiam dignissimos enim, fuga - fugit, modi, nam necessitatibus numquam obcaecati omnis recusandae voluptatibus! Lorem ipsum dolor sit amet, - consectetur adipisicing elit. Atque blanditiis consectetur cum delectus ducimus eius est hic incidunt iusto - molestiae odio optio reiciendis reprehenderit saepe tempora vel, veniam veritatis voluptates. Lorem ipsum dolor - sit amet, consectetur adipisicing elit. Ducimus expedita laboriosam nesciunt voluptatum! Ab animi illum impedit - iusto libero magni maxime molestias nisi nobis possimus provident quia repellat, rerum suscipit. Lorem ipsum - dolor sit amet, consectetur adipisicing elit. Autem modi ratione reiciendis. Cupiditate deserunt eaque eum - labore qui rem? Consequatur corporis, dolorem doloremque eveniet facilis obcaecati quasi repellat vel velit. - pizdwertyuki lokl,kmjhgfwewesrdty ukilo,kmjngeartyukikdhgfgjhklj.,kga Lorem ipsum dolor sit amet, consectetur - adipisicing elit. Amet deleniti, esse in ipsam quis sapiente tempore voluptas. Aperiam dignissimos enim, fuga - fugit, modi, nam necessitatibus numquam obcaecati omnis recusandae voluptatibus! Lorem ipsum dolor sit amet, - consectetur adipisicing elit. Atque blanditiis consectetur cum delectus ducimus eius est hic incidunt iusto - molestiae odio optio reiciendis reprehenderit saepe tempora vel, veniam veritatis voluptates. Lorem ipsum dolor - sit amet, consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque - explicabo, facere fuga hic id impedit magnam maiores minima necessitatibus, nemo nesciunt nihil officia, pariatu - nemo nesciunt nihil officia, pariatur praesentium quas quisquam repellat saepe temporibus? - </p> - <template #footer> pizdwertyukilokl,kmjhgfw ewesrdtyukilo,kmjng eartyukikdhgfgjhklj.,kga</template></Drawer - > + <Playground /> </main> </template> @@ -448,16 +268,4 @@ const sliderValue = ref(1); color: green; font-style: italic; } -.testButton { - background-color: red; - margin-bottom: 30px; - color: white; - padding: 10px; - border-radius: 5px; -} -.gradient-text { - background: linear-gradient(to right, hotpink, yellow, dodgerblue); - background-clip: text; - color: transparent; -} </style> diff --git a/src/Playground.vue b/src/Playground.vue new file mode 100644 index 0000000..d00a069 --- /dev/null +++ b/src/Playground.vue @@ -0,0 +1,318 @@ +<script setup lang="ts"> +import Modal from '@stories/components/Modal/Modal.vue'; +import ToggleSwitch from '@stories/components/ToggleSwitch/ToggleSwitch.vue'; +import AnchorLinkIcon from '@stories/icons/Mono/AnchorLinkIcon.vue'; +import SelectButton from '@stories/components/SelectButton/SelectButton.vue'; +import Drawer from '@stories/components/Drawer/Drawer.vue'; +import Slider from '@stories/components/Slider/Slider.vue'; +import TrashIcon from '@stories/icons/Mono/TrashIcon.vue'; +import CrossIcon from '@stories/icons/Mono/CrossIcon.vue'; +import Button from '@stories/components/Button/Button.vue'; +import MenuDial from '@stories/components/MenuDial/MenuDial.vue'; +import Popup from '@stories/components/Popup/Popup.vue'; +import Table from '@stories/components/Table/Table.vue'; +import { ref } from 'vue'; +import type { ISBOption, ISliderOptions, ITableColumn } from '@interfaces/componentsProp'; + +const visibleDrawer = ref(false); +const sliderOptions: ISliderOptions[] = [ + { + label: 0, + value: 0, + color: 'red', + }, + { + label: 2, + value: 2, + color: 'orange', + }, + { + label: 4, + value: 4, + color: 'yellow', + }, + { + label: 6, + value: 6, + color: 'green', + }, + { + label: 8, + value: 8, + color: 'sky', + }, + { + label: 10, + value: 10, + color: 'purple', + }, + { + label: 12, + value: 12, + color: 'purple', + }, + { + label: 14, + value: 14, + color: 'purple', + }, + { + label: 16, + value: 16, + color: 'purple', + }, + { + label: 18, + }, +]; +const options: ISBOption[] = [ + { + label: 'First', + textStyle: 'bold', + iconPosition: 'top', + }, + { + label: 'Second', + }, +]; +const visible = ref(false); +const onClose = () => console.log('close!'); +const value = ref(); +const active = ref(false); +const popupActive = ref(false); +const popupActive2 = ref(false); +const sliderValue = ref(1); + +const tableColumns: ITableColumn[] = [ + { + name: 'Name', + type: 'text', + sortable: true, + }, + { + name: 'Age', + type: 'text', + filterable: true, + }, + { + name: 'Hobbies', + type: 'text', + padding: '30px', + filterable: true, + sortable: true, + }, + { + name: 'Country', + type: 'text', + }, +]; +const tableData = [ + [ + { + value: 'Pete', + }, + { + value: '30', + }, + { + value: 'Chess', + }, + { + value: 'USA', + }, + ], + [ + { + value: 'John', + }, + { + value: '25', + }, + { + value: 'Football', + }, + { + value: 'Canada', + }, + ], + [ + { + value: 'Дима', + }, + { + value: '22', + }, + { + value: 'Frontend', + }, + { + value: 'Russia', + }, + ], + [ + { + value: 'КÑюша', + }, + { + value: '32', + }, + { + value: 'Frontend', + }, + { + value: 'Russia', + }, + ], + [ + { + value: 'КÑюша', + }, + { + value: '32', + }, + { + value: 'Backend', + }, + { + value: 'Russia', + }, + ], +]; +</script> + +<template> + <h2 class="title gradient-text">Playground</h2> + <Table + show-all-lines + :columns="tableColumns" + darknessTextColor="500" + :data="tableData" + fontSize="20px" + theme="black" + stripedRows + ></Table> + <button class="testButton" @click="visibleDrawer = !visibleDrawer">Ðажми менÑ</button> + <div class="hui" style="width: 500px; height: 500px; background-color: gray"></div> + <Popup v-model:active="popupActive" parentSelector=".hui" theme="sky"> + <Button + @click=" + () => { + popupActive = false; + visible = true; + } + " + label="Открыть модальное окно" + /> + </Popup> + <Popup v-model:active="popupActive2" theme="sky" + >Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet fugiat harum maiores placeat soluta, vel velit + voluptas. Accusamus aut, error et minima neque praesentium, ratione, reprehenderit repudiandae saepe ut vero! Lorem + ipsum dolor sit amet, consectetur adipisicing elit. Amet fugiat harum maiores placeat soluta, vel velit voluptas. + Accusamus aut, error et minima neque praesentium, ratione, reprehenderit repudiandae saepe ut vero!</Popup + > + + <Modal v-model:visible="visible" theme="red" @onClose="onClose" + ><template #header>huuuuuuuuuuui</template>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque + explicabo, facere fuga hic id impedit magnam maiores minima necessitatibus, nemo nesciunt nihil officia, pariatu + nemo nesciunt nihil officia, pariatur praesentium quas quisquam repellat saepe temporibus? Lorem ipsum dolor sit + amet, consectetur adipisicing elit. Eaque explicabo, facere fuga hic id impedit magnam maiores minima + necessitatibus, nemo nesciunt nihil officia, pariatu nemo nesciunt nihil officia, pariatur praesentium quas quisquam + repellat saepe temporibus?</Modal + > + <MenuDial + v-model:active="active" + theme="sky" + direction="right" + darknessTheme="600" + :items="[ + { + label: 'font-family', + theme: 'green', + color: 'red', + darknessColor: '500', + link: 'https://developer.mozilla.org/en-US/docs/Web/CSS/font-family', + linkBlank: true, + textStyle: 'bold', + }, + { + label: 'Second', + theme: 'red', + color: 'sky', + darknessColor: '500', + darknessTheme: '600', + textStyle: 'italic', + }, + ]" + > + <template #1IconBefore> + <AnchorLinkIcon size="20" color="white" /> + </template> + <template #2IconBefore> + <CrossIcon color="white" /> + </template> + <template #2IconAfter> + <CrossIcon color="white" /> + </template> + </MenuDial> + <Slider + v-model:value="sliderValue" + :options="sliderOptions" + width="400" + min="0" + max="18" + step="2" + backgroundColor="black" + theme="blue" + isSmooth + /> + <Button @click="visible = true" textColor="white" theme="sky" label="I'm a button"></Button> + <SelectButton :options="options" size="large" v-model:value="value"> + <template #1Icon> + <TrashIcon /> + </template> + </SelectButton> + <ToggleSwitch /> + <Drawer v-model:visible="visibleDrawer" theme="sky" :dismissible="false" closeIcon="CropIcon"> + <template #header>Ðто - Drawer</template> + <p> + pizdwertyuki lokl,kmjhgfwewesrdty ukilo,kmjngeartyukikdhgfgjhklj.,kga Lorem ipsum dolor sit amet, consectetur + adipisicing elit. Amet deleniti, esse in ipsam quis sapiente tempore voluptas. Aperiam dignissimos enim, fuga + fugit, modi, nam necessitatibus numquam obcaecati omnis recusandae voluptatibus! Lorem ipsum dolor sit amet, + consectetur adipisicing elit. Atque blanditiis consectetur cum delectus ducimus eius est hic incidunt iusto + molestiae odio optio reiciendis reprehenderit saepe tempora vel, veniam veritatis voluptates. Lorem ipsum dolor + sit amet, consectetur adipisicing elit. Ducimus expedita laboriosam nesciunt voluptatum! Ab animi illum impedit + iusto libero magni maxime molestias nisi nobis possimus provident quia repellat, rerum suscipit. Lorem ipsum dolor + sit amet, consectetur adipisicing elit. Autem modi ratione reiciendis. Cupiditate deserunt eaque eum labore qui + rem? Consequatur corporis, dolorem doloremque eveniet facilis obcaecati quasi repellat vel velit. pizdwertyuki + lokl,kmjhgfwewesrdty ukilo,kmjngeartyukikdhgfgjhklj.,kga Lorem ipsum dolor sit amet, consectetur adipisicing elit. + Amet deleniti, esse in ipsam quis sapiente tempore voluptas. Aperiam dignissimos enim, fuga fugit, modi, nam + necessitatibus numquam obcaecati omnis recusandae voluptatibus! Lorem ipsum dolor sit amet, consectetur + adipisicing elit. Atque blanditiis consectetur cum delectus ducimus eius est hic incidunt iusto molestiae odio + optio reiciendis reprehenderit saepe tempora vel, veniam veritatis voluptates. Lorem ipsum dolor sit amet, + consectetur adipisicing elit. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque explicabo, facere + fuga hic id impedit magnam maiores minima necessitatibus, nemo nesciunt nihil officia, pariatu nemo nesciunt nihil + officia, pariatur praesentium quas quisquam repellat saepe temporibus? + </p> + <template #footer> pizdwertyukilokl,kmjhgfw ewesrdtyukilo,kmjng eartyukikdhgfgjhklj.,kga</template></Drawer + > +</template> + +<style scoped> +.title { + font-size: 48px; + width: max-content; + margin: 0 auto 40px auto; +} +.testButton { + background-color: red; + margin-bottom: 30px; + color: white; + padding: 10px; + border-radius: 5px; +} +.gradient-text { + background: linear-gradient(to right, hotpink, yellow, dodgerblue); + background-clip: text; + color: transparent; +} +</style> diff --git a/src/common/constants/icons.ts b/src/common/constants/icons.ts index 83bd219..250f8fe 100644 --- a/src/common/constants/icons.ts +++ b/src/common/constants/icons.ts @@ -36,7 +36,7 @@ import ChatIcon from '@stories/icons/Mono/ChatIcon.vue'; import CrossCircleIcon from '@stories/icons/Mono/CrossCircleIcon.vue'; import CropIcon from '@stories/icons/Mono/CropIcon.vue'; import ChatWritingIcon from '@stories/icons/Mono/ChatWritingIcon.vue'; -import CheckmarkIcon from '@stories/icons/Mono/CheckmarkIcon.vue'; +import CheckMarkIcon from '@stories/icons/Mono/CheckMarkIcon.vue'; import ChemistryFlaskIcon from '@stories/icons/Mono/ChemistryFlaskIcon.vue'; import CodeIcon from '@stories/icons/Mono/CodeIcon.vue'; import CoinsIcon from '@stories/icons/Mono/CoinsIcon.vue'; @@ -143,7 +143,7 @@ export const iconsSet: Record<string, Component> = { ChartPieIcon: ChartPieIcon, ChatIcon: ChatIcon, ChatWritingIcon: ChatWritingIcon, - CheckmarkIcon: CheckmarkIcon, + CheckMarkIcon: CheckMarkIcon, ChemistryFlaskIcon: ChemistryFlaskIcon, CodeIcon: CodeIcon, CoinsIcon: CoinsIcon, diff --git a/src/common/interfaces/componentsProps.ts b/src/common/interfaces/componentsProps.ts index d85c97f..e509e0d 100644 --- a/src/common/interfaces/componentsProps.ts +++ b/src/common/interfaces/componentsProps.ts @@ -116,6 +116,9 @@ export interface IPopupProps { maxWidth?: string; maxHeight?: string; padding?: string; + buttonMenu?: boolean; + top?: number; + left?: number; } export interface ISBProps { diff --git a/src/stories/components/Popup/Popup.vue b/src/stories/components/Popup/Popup.vue index e1e154d..839e362 100644 --- a/src/stories/components/Popup/Popup.vue +++ b/src/stories/components/Popup/Popup.vue @@ -1,6 +1,6 @@ <script setup lang="ts"> import type { IPopupProps } from '@interfaces/componentsProps'; -import { computed, type Ref, ref } from 'vue'; +import { computed, type Ref, ref, watch } from 'vue'; import { convertThemeToColor, convertThemeToSecondaryColor } from '@helpers/common'; import type { CustomWindow } from '@interfaces/common'; @@ -21,26 +21,48 @@ const top = ref(); const left = ref(); const isOnContainerClick = ref(); -const container = document.querySelector(props.parentSelector); -if (container) { - container.addEventListener('pointerdown', (event: Event) => { - const e = event as PointerEvent; - if (e.button === 2) { - isOnContainerClick.value = true; - if (!active.value && !(window as CustomWindow).blockPopupActions) active.value = true; - top.value = e.pageY; - left.value = e.pageX; - e.stopPropagation(); - } - }); - container.addEventListener('contextmenu', (e) => { - if (isOnContainerClick.value) e.preventDefault(); - }); +const parent = computed(() => props.parentSelector); +const container = ref(document.querySelector(props.parentSelector)); +if (!container.value) { + setTimeout(() => { + container.value = document.querySelector(props.parentSelector); + }, 0); } +watch(parent, () => (container.value = document.querySelector(props.parentSelector))); +watch( + container, + () => { + if (container.value) { + if (props.buttonMenu) { + const clientRect = container.value?.getBoundingClientRect(); + top.value = props.top ?? clientRect.top; + left.value = props.left ?? clientRect.left; + console.log('left: ', left.value); + } -document.addEventListener('pointerdown', (e) => { - if (e.button === 0 && !(window as CustomWindow).blockPopupActions) active.value = false; -}); + container.value.addEventListener('pointerdown', (event: Event) => { + const e = event as PointerEvent; + if (e.button === 2 || (props.buttonMenu && e.button === 0)) { + isOnContainerClick.value = true; + if (!props.buttonMenu) { + top.value = e.pageY; + left.value = e.pageX; + } + if (!active.value && !props.buttonMenu && !(window as CustomWindow).blockPopupActions) active.value = true; + e.stopPropagation(); + } + }); + container.value.addEventListener('contextmenu', (e) => { + if (isOnContainerClick.value) e.preventDefault(); + }); + } + + document.addEventListener('pointerdown', (e) => { + if (!props.buttonMenu && e.button === 0 && !(window as CustomWindow).blockPopupActions) active.value = false; + }); + }, + { immediate: true }, +); </script> <template> @@ -60,6 +82,7 @@ document.addEventListener('pointerdown', (e) => { <style scoped> #popup { position: absolute; + z-index: 9999; transition: opacity 0.2s ease-in-out; background-color: v-bind(themeColor); border: 1px solid v-bind(secondaryColor); diff --git a/src/stories/components/Table/Table.stories.ts b/src/stories/components/Table/Table.stories.ts index 1bca7e8..88f4170 100644 --- a/src/stories/components/Table/Table.stories.ts +++ b/src/stories/components/Table/Table.stories.ts @@ -143,7 +143,6 @@ export const Full: Story = { type: 'text', }, ], - data: [ [ { @@ -216,14 +215,11 @@ export const Full: Story = { }, ], ], - fontSize: '20px', showAllLines: true, - gap: '20px', border: 'fuchsia', theme: 'black', stripedRows: true, - textColor: 'white', darknessTextColor: '500', center: true, }, diff --git a/src/stories/components/Table/Table.vue b/src/stories/components/Table/Table.vue index 2637655..4669770 100644 --- a/src/stories/components/Table/Table.vue +++ b/src/stories/components/Table/Table.vue @@ -7,17 +7,43 @@ import FilterIcon from '@stories/icons/Mono/FilterIcon.vue'; import SortDownIcon from '@stories/icons/Mono/SortDownIcon.vue'; import SortUpIcon from '@stories/icons/Mono/SortUpIcon.vue'; import SortVerticalIcon from '@stories/icons/Mono/SortVerticalIcon.vue'; +import { calcColumnPadding, calcRows } from '@stories/components/Table/helpers'; +import Popup from '@stories/components/Popup/Popup.vue'; +import Button from '@stories/components/Button/Button.vue'; +import CheckMarkIcon from '@stories/icons/Mono/CheckMarkIcon.vue'; +import CrossIcon from '@stories/icons/Mono/CrossIcon.vue'; const props = withDefaults(defineProps<ITableProps>(), { - gap: '5px', theme: 'white', darknessTheme: '500', fontSize: '16px', }); +const data = defineModel<ITableItem[][]>('data'); + const columns = ref(props.columns); +const sortStateActive = ref<[number, string] | []>([]); +const isFilterPopup = ref<boolean>(false); +const columnToFilter = ref<number>(0); +const filterValue = ref<string>(''); + watch(props.columns, () => (columns.value = props.columns)); -const gap = computed(() => props.gap); -const data = defineModel<ITableItem[][]>('data'); + +const initGap = computed( + () => + props.gap ?? + (!props.fontSize || isNaN(+props.fontSize.slice(0, -3)) + ? '5px' + : parseInt(props.fontSize) < 20 + ? '5px' + : parseInt(props.fontSize) < 36 + ? '10px' + : '15px'), +); +const iconSize = computed(() => { + const twoLetters = props.fontSize.slice(0, -2); + const threeLetters = props.fontSize.slice(0, -3); + return !twoLetters || isNaN(+twoLetters) ? (!threeLetters || isNaN(+threeLetters) ? '16' : threeLetters) : twoLetters; +}); const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const color = computed(() => props.textColor @@ -36,36 +62,9 @@ const sortState = computed<string[]>(() => { return result; }); -const sortStateActive = ref([]); -const rows = computed<ITableItem[][]>(() => { - // ['up', 'down', ...] - const rows = [...data.value]; - if (!sortStateActive.value.length) return rows; - - if (props.multipleSort) { - // let indexColumn = sortState.value.findIndex((state) => state && state !== 'none'); - // let lastColumnIndexSorted = indexColumn; - // console.log('indexColumn: ', indexColumn); - // for (const sortItem of sortStateActive.value) { - // rows.sort((a, b) => - // sortItem.split('$')[1] === 'down' - // ? a[indexColumn].value.localeCompare(b[indexColumn].value) - // : b[indexColumn].value.localeCompare(a[indexColumn].value), - // ); - // indexColumn = sortState.value.findIndex( - // (state, index) => state && state !== 'none' && index !== lastColumnIndexSorted, - // ); - // lastColumnIndexSorted = indexColumn; - // } - // return rows; - } else { - const index = sortStateActive.value[0]; - const value = sortStateActive.value[1]; - return rows.sort((a, b) => - value === 'down' ? a[index].value.localeCompare(b[index].value) : b[index].value.localeCompare(a[index].value), - ); - } -}); +const rows = computed<ITableItem[][]>(() => + calcRows(data.value!, sortStateActive.value, props.multipleSort, columnToFilter.value, filterValue.value), +); const changeColumnSortMode = (index: number) => { const cur = sortState.value[index]; @@ -79,6 +78,24 @@ const changeColumnSortMode = (index: number) => { if (!props.multipleSort) columns.value.forEach((column) => (column.initSort = 'none')); columns.value[index].initSort = newValue; }; +const setFilter = (column: number) => { + if (columnToFilter.value === column || !isFilterPopup.value) { + isFilterPopup.value = !isFilterPopup.value; + } + if (columnToFilter.value !== column) { + columnToFilter.value = column; + } +}; +const calcLeft = (selector: string) => { + const el = document.querySelector(selector); + const table = document.querySelector('#table')!; + if (!el) return 0; + return el.getBoundingClientRect().left - table.getBoundingClientRect().left + +iconSize.value; +}; +const cancelFilter = () => { + filterValue.value = ''; + isFilterPopup.value = false; +}; </script> <template> @@ -88,6 +105,7 @@ const changeColumnSortMode = (index: number) => { tableLines: showAllLines, }" :style="`background-color: ${themeColor}; color: ${color}`" + id="table" > <thead> <tr> @@ -98,16 +116,11 @@ const changeColumnSortMode = (index: number) => { v-for="(column, index) of columns" :key="column.name" class="columnHeader" - style="padding: 5px 0 5px 5px" + :style="`padding: calc(${initGap} / 2) ${initGap}`" > <div - :style="`justify-content: ${center ? 'center' : 'start'}; padding: ${center ? `0px calc(${gap} / 2 + ${column.padding ?? '0px'} / 2)` : `0 ${column.padding ?? '0px'} 0 0`}`" - :class="[ - 'columnFlex', - { - columnGap: !center, - }, - ]" + :style="`justify-content: ${center ? 'center' : 'start'}; gap: ${center ? '0' : initGap}; padding: ${calcColumnPadding(column, props.center, initGap)}`" + class="columnFlex" > <div class="columnHeader-container"> <h3> @@ -118,32 +131,45 @@ const changeColumnSortMode = (index: number) => { @click.prevent="changeColumnSortMode(index)" style="min-width: 20px; min-height: 20px" > - <SortVerticalIcon - v-show="sortState[index] === 'none'" - :color="textColor" - :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" - /> - <SortDownIcon - v-show="sortState[index] === 'down'" - :color="textColor" - :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" - /> - <SortUpIcon - v-show="sortState[index] === 'up'" - :color="textColor" - :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" - /> + <SortVerticalIcon v-show="sortState[index] === 'none'" :color="color" :size="iconSize" /> + <SortDownIcon v-show="sortState[index] === 'down'" :color="color" :size="iconSize" /> + <SortUpIcon v-show="sortState[index] === 'up'" :color="color" :size="iconSize" /> </button> - <button v-if="column.filterable" @click.prevent=""> - <FilterIcon - :color="textColor" - :size="isNaN(+fontSize.slice(0, -2)) ? fontSize.slice(0, -3) : fontSize.slice(0, -2)" - /> + <button + v-if="column.filterable" + @pointerdown="setFilter(index)" + :id="`filter${column.name}`" + style="position: relative" + > + <FilterIcon :color="color" :size="iconSize" /> </button> </div> <div v-if="!center"></div> </div> </th> + <Popup + v-model:active="isFilterPopup" + :parentSelector="`#filter${columnToFilter}`" + buttonMenu + :theme="theme" + :top="+iconSize + 10" + :left="calcLeft(`#filter${columnToFilter}`)" + > + <input + v-model="filterValue" + type="text" + class="filterInput" + :style="`background-color: ${themeColor}; color: ${color}`" + /> + <section class="filterButtons"> + <Button iconOnly size="small" theme="green" @click.prevent="isFilterPopup = false"> + <CheckMarkIcon color="white" size="20" /> + </Button> + <Button iconOnly size="small" theme="red" @click.prevent="cancelFilter"> + <CrossIcon color="white" size="20" /> + </Button> + </section> + </Popup> </tr> </thead> <tbody> @@ -155,7 +181,7 @@ const changeColumnSortMode = (index: number) => { }" v-for="item of row" :key="item.value" - :style="`padding: 5px; text-align: ${center ? 'center' : 'start'}`" + :style="`padding: calc(${initGap} / 2) ${initGap}; text-align: ${center ? 'center' : 'start'}`" > {{ item.value }} </td> @@ -188,11 +214,9 @@ tr::after { display: flex; font-weight: bold; } -.columnGap { - gap: v-bind(gap); -} .columnHeader-container { display: flex; + align-items: center; gap: 10px; } .tableLines { @@ -205,4 +229,15 @@ tr::after { .darkRow { background-color: v-bind(darkCellColor); } +.filterInput { + width: 150px; + padding: 5px; + margin-bottom: 5px; + border: 2px solid #64748b; + border-radius: 5px; +} +.filterButtons { + display: flex; + justify-content: space-between; +} </style> diff --git a/src/stories/components/Table/helpers.ts b/src/stories/components/Table/helpers.ts new file mode 100644 index 0000000..4e5e9c1 --- /dev/null +++ b/src/stories/components/Table/helpers.ts @@ -0,0 +1,46 @@ +import type { ITableColumn, ITableItem } from '@interfaces/componentsProp'; + +export const calcRows = ( + initRows: ITableItem[][], + sortStateActive: [number, string] | [], + multipleSort: boolean, + columnToFilter: number, + filterValue: string, +) => { + // ['up', 'down', ...] + let rows = [...initRows]; + + if (filterValue) { + rows = rows.filter((row) => row[columnToFilter].value.startsWith(filterValue)); + } + + if (!sortStateActive.length) return rows; + + if (multipleSort) { + // TODO: multiple sort logic + // let indexColumn = sortState.value.findIndex((state) => state && state !== 'none'); + // let lastColumnIndexSorted = indexColumn; + // console.log('indexColumn: ', indexColumn); + // for (const sortItem of sortStateActive.value) { + // rows.sort((a, b) => + // sortItem.split('$')[1] === 'down' + // ? a[indexColumn].value.localeCompare(b[indexColumn].value) + // : b[indexColumn].value.localeCompare(a[indexColumn].value), + // ); + // indexColumn = sortState.value.findIndex( + // (state, index) => state && state !== 'none' && index !== lastColumnIndexSorted, + // ); + // lastColumnIndexSorted = indexColumn; + // } + return rows; + } else { + const index = sortStateActive[0]; + const value = sortStateActive[1]; + return rows.sort((a, b) => + value === 'down' ? a[index].value.localeCompare(b[index].value) : b[index].value.localeCompare(a[index].value), + ); + } +}; + +export const calcColumnPadding = (column: ITableColumn, center: boolean, gap: string) => + center ? `0px calc(${gap} / 2 + ${column.padding ?? '0px'} / 2)` : `0 ${column.padding ?? '0px'} 0 0`; diff --git a/src/stories/icons/Mono/CheckmarkIcon.vue b/src/stories/icons/Mono/CheckMarkIcon.vue similarity index 100% rename from src/stories/icons/Mono/CheckmarkIcon.vue rename to src/stories/icons/Mono/CheckMarkIcon.vue diff --git a/yarn.lock b/yarn.lock index c78b8cb..3c4beea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -273,10 +273,10 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" -"@chromatic-com/storybook@3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@chromatic-com/storybook/-/storybook-3.2.2.tgz#08754443de55618f802f88450c35266fd6d25db5" - integrity sha512-xmXt/GW0hAPbzNTrxYuVo43Adrtjue4DeVrsoIIEeJdGaPNNeNf+DHMlJKOBdlHmCnFUoe9R/0mLM9zUp5bKWw== +"@chromatic-com/storybook@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@chromatic-com/storybook/-/storybook-3.2.3.tgz#0f4d167ac80fcb38293a92c230c43446049b6758" + integrity sha512-3+hfANx79kIjP1qrOSLxpoAXOiYUA0S7A0WI0A24kASrv7USFNNW8etR5TjUilMb0LmqKUn3wDwUK2h6aceQ9g== dependencies: chromatic "^11.15.0" filesize "^10.0.12" @@ -796,10 +796,10 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz#67d516613c9f2fe42e2d8b78e252d0003179d92c" integrity sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug== -"@storybook/addon-actions@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.4.5.tgz#9224f635c78240f611eb340ba9b4248986b4763c" - integrity sha512-rbB19uiGJ61XHbKIbS1a9bUS6re5L8rT5NMNeEJhCxXRpFUPrlTXMSoD/Pgcn3ENeEMVZsm8/eCzxAVgAP3Mgg== +"@storybook/addon-actions@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.4.7.tgz#210c6bb5a7e17c3664c300b4b69b6243ec34b9cd" + integrity sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA== dependencies: "@storybook/global" "^5.0.0" "@types/uuid" "^9.0.1" @@ -807,133 +807,126 @@ polished "^4.2.2" uuid "^9.0.0" -"@storybook/addon-backgrounds@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.5.tgz#3d93d24d0b8e77d6d5bad78bae4c8621ee27c5d1" - integrity sha512-FeMt4qHCMYDQiLGGDKiRuSPXFup2WXOaZSdL137v1W36wEL/vGkK1A5iQt1qJ8MZzL5WZQuedox8rSybFy7eow== +"@storybook/addon-backgrounds@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.7.tgz#56856bdafc5a2ba18cc19422320883c9e8f66c1c" + integrity sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ== dependencies: "@storybook/global" "^5.0.0" memoizerific "^1.11.3" ts-dedent "^2.0.0" -"@storybook/addon-controls@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-8.4.5.tgz#1f6ce4044ab093aabb79fcd6537a996f2d12597f" - integrity sha512-RVTtDDuESLYc1+SJQv2kI7wzBddzAS9uoEe8P75quN6S4pC0GxAB6xirWZ2+WOcba4eHosY+PxMwuBXQfH78Ew== +"@storybook/addon-controls@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-8.4.7.tgz#0c2ace0c7056248577f08f90471f29e861b485be" + integrity sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA== dependencies: "@storybook/global" "^5.0.0" dequal "^2.0.2" ts-dedent "^2.0.0" -"@storybook/addon-docs@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-8.4.5.tgz#fa38b6c6c0ef1c8fc588b6913ddb55b67be55666" - integrity sha512-zPELIl7wXormOylVaaSpkUIuuCCxrO+OFPMKZnlENt6zSReyy0dJu4V0tzfV8FCw+V4D6Y4wrLRk/TIG951Ojw== +"@storybook/addon-docs@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-8.4.7.tgz#556515da1049f97023427301e11ecb52d0b9dbe7" + integrity sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w== dependencies: "@mdx-js/react" "^3.0.0" - "@storybook/blocks" "8.4.5" - "@storybook/csf-plugin" "8.4.5" - "@storybook/react-dom-shim" "8.4.5" + "@storybook/blocks" "8.4.7" + "@storybook/csf-plugin" "8.4.7" + "@storybook/react-dom-shim" "8.4.7" react "^16.8.0 || ^17.0.0 || ^18.0.0" react-dom "^16.8.0 || ^17.0.0 || ^18.0.0" ts-dedent "^2.0.0" -"@storybook/addon-essentials@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-8.4.5.tgz#7ff4f71b4435f734936272a691a830a34eaaef49" - integrity sha512-AxetQo/zSPIu3RZqWG2opwAz22Bb+jpf1nWbHp0kEpCrBemcWd8X2gonVmXNOC1PDKNl3jcWyc3lmg/+3mxjYg== - dependencies: - "@storybook/addon-actions" "8.4.5" - "@storybook/addon-backgrounds" "8.4.5" - "@storybook/addon-controls" "8.4.5" - "@storybook/addon-docs" "8.4.5" - "@storybook/addon-highlight" "8.4.5" - "@storybook/addon-measure" "8.4.5" - "@storybook/addon-outline" "8.4.5" - "@storybook/addon-toolbars" "8.4.5" - "@storybook/addon-viewport" "8.4.5" +"@storybook/addon-essentials@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-8.4.7.tgz#381c74230d1b1a209d5fdc017d241c016b98affe" + integrity sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw== + dependencies: + "@storybook/addon-actions" "8.4.7" + "@storybook/addon-backgrounds" "8.4.7" + "@storybook/addon-controls" "8.4.7" + "@storybook/addon-docs" "8.4.7" + "@storybook/addon-highlight" "8.4.7" + "@storybook/addon-measure" "8.4.7" + "@storybook/addon-outline" "8.4.7" + "@storybook/addon-toolbars" "8.4.7" + "@storybook/addon-viewport" "8.4.7" ts-dedent "^2.0.0" -"@storybook/addon-highlight@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-8.4.5.tgz#44c194f88395a6e221744867a11f39ea8910d290" - integrity sha512-sMA7v+4unaKY+5RDhow6lLncJqNX9ZLUnBIt3vzY1ntUsOYVwykAY1Hq4Ysj0luCBXjJJdJ6223ylrycnb7Ilw== +"@storybook/addon-highlight@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-highlight/-/addon-highlight-8.4.7.tgz#06b9752977e38884007e9446f9a2b0c04c873229" + integrity sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw== dependencies: "@storybook/global" "^5.0.0" -"@storybook/addon-interactions@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-interactions/-/addon-interactions-8.4.5.tgz#0053207da50a4cefc9dce46b7980cd54a828c2ff" - integrity sha512-s6R8XVD8LTp+LQTDbhtDjDLE6S44I7FtMLxPdMNwN9VEJjBk01NONLDuGDpNq5o/0bnybA3rMHk9+3afsgzidQ== +"@storybook/addon-interactions@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-interactions/-/addon-interactions-8.4.7.tgz#d34545db5ea6f03a5499ad6742c3317fb9e02d55" + integrity sha512-fnufT3ym8ht3HHUIRVXAH47iOJW/QOb0VSM+j269gDuvyDcY03D1civCu1v+eZLGaXPKJ8vtjr0L8zKQ/4P0JQ== dependencies: "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.4.5" - "@storybook/test" "8.4.5" + "@storybook/instrumenter" "8.4.7" + "@storybook/test" "8.4.7" polished "^4.2.2" ts-dedent "^2.2.0" -"@storybook/addon-measure@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-8.4.5.tgz#9b22ea0f28740f0c9c1edee2642de2b75415abdd" - integrity sha512-+sNjew991YaoXQyWWloFybjEGrDO40Jk6w8BgZs2X7oc3D5t/6oFzvyC862U++LGqKFA3quXDeBjEb92CI9cRA== +"@storybook/addon-measure@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-8.4.7.tgz#9d556ba34b57c13ad8d00bd953b27ec405a64d23" + integrity sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw== dependencies: "@storybook/global" "^5.0.0" tiny-invariant "^1.3.1" -"@storybook/addon-onboarding@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-onboarding/-/addon-onboarding-8.4.5.tgz#731ac4a27711dff565dec9b4090fb49ab752d7b9" - integrity sha512-+FW50yVw2NMxYvk3uMpIberfkG4Sn0qRpiMse7MGHgTimtaJ0Mo1AUIrSfyIJCVTuxiWZud1a5DAnH0ybbWjjA== - dependencies: - react-confetti "^6.1.0" - -"@storybook/addon-outline@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-8.4.5.tgz#32d0a798b7c5abacbe2576125f589c8d4bcd5bcc" - integrity sha512-XlpN98AUDnWQWNFSFVm+HkRUzm3xIUMjBGTkv6HsL6zt6XoJ+LsQMca+PPtYqlBJA+5CU41xMDaG8HC/p+sd3A== +"@storybook/addon-outline@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-8.4.7.tgz#8a35fe519dd639bb287a370da2222e6ffdce4020" + integrity sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA== dependencies: "@storybook/global" "^5.0.0" ts-dedent "^2.0.0" -"@storybook/addon-toolbars@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-8.4.5.tgz#ebe20f0577a3e399858ba591066dbc8ac9636a5c" - integrity sha512-hOq5560ONOU/qrslrwosWzxnC4nrF8HZWD43ciKwtethm8HuptU2M+Jrui1CRsMScEZLopWWVE9o0vJMdKpIFQ== +"@storybook/addon-toolbars@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-8.4.7.tgz#b898d4deaf6f5a58f3b70bd8d136cd4ec2844b79" + integrity sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw== -"@storybook/addon-viewport@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-8.4.5.tgz#21a8b6d49f31cdca72018e9cd3adffbc435fa61a" - integrity sha512-l7Y41gIbJAsIN/QCg1QJ9sr61FLz1C/imUotcDej41tOHxUTSQOlXpNtVnfhUM1vGQc0yNpP3pVxj8BpXi0cAw== +"@storybook/addon-viewport@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-8.4.7.tgz#e65c53608f52149c06347b395487960605fc4805" + integrity sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ== dependencies: memoizerific "^1.11.3" -"@storybook/blocks@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-8.4.5.tgz#9494d9ccddc04bacd6a7a6c67cf870b72bf4ce9d" - integrity sha512-Z+LHauSqm3A4HBR9pUEf9KQhD3/3xYMt0FXgA+GHCAyDa6lFeD1C6r9Y2nlT+9dt8gv9B9oygTZvV6GqFVyRSQ== +"@storybook/blocks@8.4.7", "@storybook/blocks@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/blocks/-/blocks-8.4.7.tgz#ee17f59dd52d11c97c39b0f6b03957085a80ad95" + integrity sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA== dependencies: "@storybook/csf" "^0.1.11" "@storybook/icons" "^1.2.12" ts-dedent "^2.0.0" -"@storybook/builder-vite@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/builder-vite/-/builder-vite-8.4.5.tgz#42309b24c75ed17d0e28fe90694157287a248fcd" - integrity sha512-fZXWQcG5ccHCAS8NbyUwu8/5aVlZr4zmWbvKxoyvcVeuxJIsWa9RUS8Mtu7hdi+r/Wk8AlpckqhHo6go0iaDcA== +"@storybook/builder-vite@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/builder-vite/-/builder-vite-8.4.7.tgz#3d6d542fa1f46fce5ee7a159dc8491cb4421254d" + integrity sha512-LovyXG5VM0w7CovI/k56ZZyWCveQFVDl0m7WwetpmMh2mmFJ+uPQ35BBsgTvTfc8RHi+9Q3F58qP1MQSByXi9g== dependencies: - "@storybook/csf-plugin" "8.4.5" + "@storybook/csf-plugin" "8.4.7" browser-assert "^1.2.1" ts-dedent "^2.0.0" -"@storybook/components@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-8.4.5.tgz#039e4cb5090c56c47fc10f0c5ecda77f4b015c7f" - integrity sha512-2PdnKfqNNv3sO7qILgWXiNvmLOi503oN9OMemNCQjTIvdvySc5JpS9/eClwcl/JfmE4qHdSHZr8dLLkBM9S7+Q== +"@storybook/components@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-8.4.7.tgz#09eeffa07aa672ad3966ca1764a43003731b1d30" + integrity sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g== -"@storybook/core@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-8.4.5.tgz#4133927a43834664777f0918caf32542630cbdd5" - integrity sha512-aB1sQNX5nRoUAqg5u1py0MuR/VPd6c6PhECa4rW6pmr7kZcfyP4PP6UFpXuN71ypTQlkRE3Vc5PQZ3gLhE9o3g== +"@storybook/core@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-8.4.7.tgz#af9cbb3f26f0b6c98c679a134ce776c202570d66" + integrity sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA== dependencies: "@storybook/csf" "^0.1.11" better-opn "^3.0.2" @@ -947,10 +940,10 @@ util "^0.12.5" ws "^8.2.3" -"@storybook/csf-plugin@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-8.4.5.tgz#7f9ae0176e36cb74b1f638aac04dfec4aa04222f" - integrity sha512-qd2rQTglOTS+phQmTbNTXNjNyxdGvolaqHqDNMw3Vf6h9o3U+mLkwnDWNVnQ9oqvOoUEAqpBthgwzU9FhkIk+A== +"@storybook/csf-plugin@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-8.4.7.tgz#0117c872b05bf033eec089ab0224e0fab01da810" + integrity sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g== dependencies: unplugin "^1.3.1" @@ -971,71 +964,71 @@ resolved "https://registry.yarnpkg.com/@storybook/icons/-/icons-1.2.12.tgz#3e4c939113b67df7ab17b78f805dbb57f4acf0db" integrity sha512-UxgyK5W3/UV4VrI3dl6ajGfHM4aOqMAkFLWe2KibeQudLf6NJpDrDMSHwZj+3iKC4jFU7dkKbbtH2h/al4sW3Q== -"@storybook/instrumenter@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-8.4.5.tgz#14983198b27dfbeedfef28992eef0d304b9f562b" - integrity sha512-8qM35FkueuRpJr0zA6ENvhQICbo+iKL1ln450DwV1kKJtc41KdbA3CuCvtZ/FnoPsFnwdtPjhhICFtRt8LRTSg== +"@storybook/instrumenter@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-8.4.7.tgz#5a37876fee8f828241a1e7fd76891c6effc1805a" + integrity sha512-k6NSD3jaRCCHAFtqXZ7tw8jAzD/yTEWXGya+REgZqq5RCkmJ+9S4Ytp/6OhQMPtPFX23gAuJJzTQVLcCr+gjRg== dependencies: "@storybook/global" "^5.0.0" "@vitest/utils" "^2.1.1" -"@storybook/manager-api@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-8.4.5.tgz#ce586cc5961297272f7228446161015464c65067" - integrity sha512-t39JaMy3UX4StbUH/tIDcaflBDxTcyIq853wQtBMhVL3e1+Dw3MIiiG/5bw79HU4R7kSmPVLXIIbV3FmXkq7KQ== +"@storybook/manager-api@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/manager-api/-/manager-api-8.4.7.tgz#4e13debf645c9300d7d6d49195e720d0c7ecd261" + integrity sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ== -"@storybook/preview-api@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-8.4.5.tgz#f8c046575c68062eda1de9494e7118571d20c72a" - integrity sha512-MKIZ2jQO/3cUdsT57eq8jRgB6inALo9BxrQ88f7mqzltOkMvADvTAY6y8JZqTUoDzWTH/ny/8SGGdtpqlxRuiQ== +"@storybook/preview-api@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/preview-api/-/preview-api-8.4.7.tgz#85e01a97f4182b974581765d725f6c7a7d190013" + integrity sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg== -"@storybook/react-dom-shim@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-8.4.5.tgz#cc874d008a1def4410c32a95bcf9aac8defdb6f5" - integrity sha512-YTWTfPagptEYXJsnxAl3zP97Ev0zebtaEV0WgjGaEeumr+zsfgKKwzzHxgrtumBmDzwkuKlzFwlQB5A8keOIGA== +"@storybook/react-dom-shim@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/react-dom-shim/-/react-dom-shim-8.4.7.tgz#f0dd5bbf2fc185def72d9d08a11c8de22f152c2a" + integrity sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg== -"@storybook/test@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.4.5.tgz#a22e8a4671c379f8ffc83a3997feb524bf5d9421" - integrity sha512-mHsRc6m60nfcEBsjvUkKz+Jnz0or4WH5jmJ1VL2pGKO4VzESCPqAwDnwDqP2YyeSQ0b/MAKUT5kdoLE2RE2eVw== +"@storybook/test@8.4.7", "@storybook/test@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.4.7.tgz#7f58f2cdf3a6d810bf3ff4e0e2fee634040c678f" + integrity sha512-AhvJsu5zl3uG40itSQVuSy5WByp3UVhS6xAnme4FWRwgSxhvZjATJ3AZkkHWOYjnnk+P2/sbz/XuPli1FVCWoQ== dependencies: "@storybook/csf" "^0.1.11" "@storybook/global" "^5.0.0" - "@storybook/instrumenter" "8.4.5" + "@storybook/instrumenter" "8.4.7" "@testing-library/dom" "10.4.0" "@testing-library/jest-dom" "6.5.0" "@testing-library/user-event" "14.5.2" "@vitest/expect" "2.0.5" "@vitest/spy" "2.0.5" -"@storybook/theming@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-8.4.5.tgz#d7c77215f09906c9bb124d530d4307fd1841fbb8" - integrity sha512-45e/jeG4iuqdZcHg3PbB6dwXQTwlnnEB7r/QcVExyC7ibrkTnjUfvxzyUw4mmU3CXETFGD5EcUobFkgK+/aPxQ== +"@storybook/theming@8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-8.4.7.tgz#c308f6a883999bd35e87826738ab8a76515932b5" + integrity sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw== -"@storybook/vue3-vite@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/vue3-vite/-/vue3-vite-8.4.5.tgz#04661fc02c754be58d13c41e85894f9f19c72c48" - integrity sha512-ngUR053rrD7lg9+gtBjgjqK82tUBXq3zE91pxwgkKBCYbfrKpGgjse+ds3xsdGChnnGIlUahiiHuLmdzxTkffg== +"@storybook/vue3-vite@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/vue3-vite/-/vue3-vite-8.4.7.tgz#036bee5652d7b9856d54510d5236d52678234631" + integrity sha512-MCU4GB6mKgeOy23eGL/yCxPWP1dBGuU4hRVoQYUzDyvNRNWD/0n7WOwIpKGeDHhmOW3J9PPX7C3k/N4ewFBmrQ== dependencies: - "@storybook/builder-vite" "8.4.5" - "@storybook/vue3" "8.4.5" + "@storybook/builder-vite" "8.4.7" + "@storybook/vue3" "8.4.7" find-package-json "^1.2.0" magic-string "^0.30.0" typescript "^5.0.0" vue-component-meta "^2.0.0" vue-docgen-api "^4.75.1" -"@storybook/vue3@8.4.5": - version "8.4.5" - resolved "https://registry.yarnpkg.com/@storybook/vue3/-/vue3-8.4.5.tgz#0eb9979f8ea6f574d7e38b5668e0146b97dbc5f2" - integrity sha512-HLOnHkP7geutPbuelmUurqFnpH8qGmrL7t9yx895EBSWM+1IIg3m6lD/ZwqqgGxbXJVpDNrF6168v8750D9wVQ== +"@storybook/vue3@8.4.7", "@storybook/vue3@^8.4.7": + version "8.4.7" + resolved "https://registry.yarnpkg.com/@storybook/vue3/-/vue3-8.4.7.tgz#c689b5fc3d68c9d9d094d6ce43c2ba3b275436d6" + integrity sha512-QvILEkgx7VyKBuLB4KiuQ0U8OLfQyLTwDuJ36wihQ75EEt86z29kYLNC2keHSbns/HUs3x3cjM9EkUT2xLgc/A== dependencies: - "@storybook/components" "8.4.5" + "@storybook/components" "8.4.7" "@storybook/global" "^5.0.0" - "@storybook/manager-api" "8.4.5" - "@storybook/preview-api" "8.4.5" - "@storybook/theming" "8.4.5" + "@storybook/manager-api" "8.4.7" + "@storybook/preview-api" "8.4.7" + "@storybook/theming" "8.4.7" "@vue/compiler-core" "^3.0.0" ts-dedent "^2.0.0" type-fest "~2.19" @@ -3679,12 +3672,12 @@ std-env@^3.8.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== -storybook@8.4.5: - version "8.4.5" - resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.4.5.tgz#ba9589e2887958d1353dbc1a2cb6142e80e36a2c" - integrity sha512-9tfgabXnMibYp3SvoaJXXMD63Pw0SA9Hnf5v6TxysCYZs4DZ/04fAkK+9RW+K4C5JkV83qXMMlrsPj766R47fg== +storybook@^8.4.7: + version "8.4.7" + resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.4.7.tgz#a3068787a58074cec1b4197eed1c4427ec644b3f" + integrity sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw== dependencies: - "@storybook/core" "8.4.5" + "@storybook/core" "8.4.7" "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" -- GitLab