Loading src/common/interfaces/componentsProp.ts +1 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ export interface IMDItemProps { onClick?: () => void; } export interface IKnobColorGap { export interface IColorGap { start: number; end: number; color: TThemeColor; Loading src/common/interfaces/componentsProps.ts +21 −3 Original line number Diff line number Diff line Loading @@ -11,14 +11,13 @@ import type { TThemeColorNoWhite, } from '@interfaces/common'; import type { IKnobColorGap, IColorGap, IMDItemProps, ISBOption, ISelectGroup, ISelectOption, ISliderOptions, ITableColumn, ITableItem, ITreeItem, } from '@interfaces/componentsProp'; Loading Loading @@ -74,7 +73,7 @@ export interface IKnobProps { step?: number; size?: TSize; theme?: TThemeColor; colorGaps?: IKnobColorGap[]; colorGaps?: IColorGap[]; negativeTheme?: TThemeColor; color?: TThemeColor; background?: string; Loading Loading @@ -192,6 +191,25 @@ export interface IButtonProps { darknessTextColor?: TDarkness; } export interface IProgressBarProps { value: number; max?: number; width?: string; height?: string; size?: TSize; fontSize?: string; colorGaps?: IColorGap[]; colorInactiveGaps?: IColorGap[]; theme?: TThemeColor; inactiveTheme?: TThemeColor; darknessTheme?: TDarkness; darknessInactiveTheme?: TDarkness; showLabel?: boolean; labelBefore?: string; labelAfter?: string; noBorder?: boolean; } export interface IRatingProps { count?: number; size?: TSize; Loading src/components/Knob/helpers.ts +2 −2 Original line number Diff line number Diff line import { convertThemeToColor } from '@helpers/common'; import { EThemeColor, type TDarkness, type TSize, type TThemeColor } from '@interfaces/common'; import type { IKnobColorGap } from '@interfaces/componentsProp'; import type { IColorGap } from '@interfaces/componentsProp'; export const calcNewValue = ( event: MouseEvent, Loading Loading @@ -40,7 +40,7 @@ export const calcStart = (container: Element) => { }; export const calcThemeColor = ( colorGaps: IKnobColorGap[] | undefined, colorGaps: IColorGap[] | undefined, theme: TThemeColor, darknessTheme: TDarkness, value: number, Loading src/components/ProgressBar/ProgressBar.stories.ts 0 → 100644 +140 −0 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import ProgressBar from './ProgressBar.vue'; const meta: Meta = { title: 'Components/ProgressBar', component: ProgressBar, tags: ['autodocs'], parameters: { docs: { description: { component: 'A component that is used as a ProgressBar.', }, }, }, argTypes: { value: { control: 'number' }, max: { control: 'number' }, width: { control: 'text' }, height: { control: 'text' }, labelBefore: { control: 'text' }, labelAfter: { control: 'text' }, showLabel: { control: 'boolean' }, noBorder: { control: 'boolean' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, fontSize: { control: 'text' }, colorGaps: { control: 'object' }, colorInactiveGaps: { control: 'object' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessInactiveTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, theme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, inactiveTheme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, args: {}, } satisfies Meta<typeof ProgressBar>; export default meta; type Story = StoryObj<typeof meta>; export const Simple: Story = { args: { value: 40, }, }; export const Small: Story = { args: { size: 'small', value: 40, theme: 'red', inactiveTheme: 'red', labelAfter: '/100', width: '500px', }, }; export const Full: Story = { args: { colorGaps: [ { start: 0, end: 10, color: 'purple', darknessColor: '700', }, { start: 10, end: 20, color: 'red', }, { start: 20, end: 30, color: 'orange', }, { start: 30, end: 40, color: 'yellow', }, { start: 40, end: 50, color: 'green', }, ], size: 'huge', value: 35, max: 50, labelAfter: '', showLabel: true, labelBefore: '$', inactiveTheme: 'white', darknessInactiveTheme: '400', noBorder: true, }, }; src/components/ProgressBar/ProgressBar.vue 0 → 100644 +84 −0 Original line number Diff line number Diff line <script setup lang="ts"> import type { IProgressBarProps } from '@interfaces/componentsProps'; import { computed } from 'vue'; import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common'; const props = withDefaults(defineProps<IProgressBarProps>(), { value: 0, max: 100, size: 'normal', theme: 'black', inactiveTheme: 'white', darknessTheme: '500', darknessInactiveTheme: '300', showLabel: true, labelAfter: '%', }); const active = computed(() => `${(props.value / props.max) * 100}%`); const activeColor = computed(() => { if (!props.colorGaps) return convertThemeToColor(props.theme, props.darknessTheme); const current = props.colorGaps.find((item) => item.start <= props.value && props.value <= item.end); if (!current) return convertThemeToColor(props.theme, props.darknessTheme); return convertThemeToColor(current.color, current.darknessColor); }); const inactiveColor = computed(() => { if (!props.colorInactiveGaps) return convertThemeToColor(props.inactiveTheme, props.darknessInactiveTheme); const current = props.colorInactiveGaps.find((item) => item.start <= props.value && props.value <= item.end); if (!current) return convertThemeToColor(props.inactiveTheme, props.darknessInactiveTheme); return convertThemeToColor(current.color, current.darknessColor); }); const textColor = computed(() => convertThemeToTextColor(props.theme, props.darknessTheme)); const fontSize = computed(() => { if (props.fontSize) return props.fontSize; const size = props.size; if (size === 'normal') return '16px'; if (size === 'large') return '20px'; if (size === 'huge') return '24px'; return '12px'; }); const defaultHeight = computed(() => { const size = props.size; if (size === 'normal') return '30px'; if (size === 'large') return '45px'; if (size === 'huge') return '60px'; return '15px'; }); </script> <template> <section class="container" :style="`width: ${width ?? '300px'}; height: ${height ?? defaultHeight}; border: ${noBorder ? '' : '2px solid black'}`" > <div class="active"> <span v-show="showLabel" class="value">{{ labelBefore }}{{ value }}{{ labelAfter }}</span> </div> </section> </template> <style scoped> .container { position: relative; overflow: hidden; border-radius: calc(v-bind(fontSize) / 2.5); background-color: v-bind(inactiveColor); } .active { width: v-bind(active); height: 100%; overflow: hidden; display: flex; justify-content: center; align-items: center; position: absolute; top: 0; left: 0; transition: width 0.4s ease-in-out; background-color: v-bind(activeColor); } .value { font-weight: bold; font-size: v-bind(fontSize); color: v-bind(textColor); } </style> Loading
src/common/interfaces/componentsProp.ts +1 −1 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ export interface IMDItemProps { onClick?: () => void; } export interface IKnobColorGap { export interface IColorGap { start: number; end: number; color: TThemeColor; Loading
src/common/interfaces/componentsProps.ts +21 −3 Original line number Diff line number Diff line Loading @@ -11,14 +11,13 @@ import type { TThemeColorNoWhite, } from '@interfaces/common'; import type { IKnobColorGap, IColorGap, IMDItemProps, ISBOption, ISelectGroup, ISelectOption, ISliderOptions, ITableColumn, ITableItem, ITreeItem, } from '@interfaces/componentsProp'; Loading Loading @@ -74,7 +73,7 @@ export interface IKnobProps { step?: number; size?: TSize; theme?: TThemeColor; colorGaps?: IKnobColorGap[]; colorGaps?: IColorGap[]; negativeTheme?: TThemeColor; color?: TThemeColor; background?: string; Loading Loading @@ -192,6 +191,25 @@ export interface IButtonProps { darknessTextColor?: TDarkness; } export interface IProgressBarProps { value: number; max?: number; width?: string; height?: string; size?: TSize; fontSize?: string; colorGaps?: IColorGap[]; colorInactiveGaps?: IColorGap[]; theme?: TThemeColor; inactiveTheme?: TThemeColor; darknessTheme?: TDarkness; darknessInactiveTheme?: TDarkness; showLabel?: boolean; labelBefore?: string; labelAfter?: string; noBorder?: boolean; } export interface IRatingProps { count?: number; size?: TSize; Loading
src/components/Knob/helpers.ts +2 −2 Original line number Diff line number Diff line import { convertThemeToColor } from '@helpers/common'; import { EThemeColor, type TDarkness, type TSize, type TThemeColor } from '@interfaces/common'; import type { IKnobColorGap } from '@interfaces/componentsProp'; import type { IColorGap } from '@interfaces/componentsProp'; export const calcNewValue = ( event: MouseEvent, Loading Loading @@ -40,7 +40,7 @@ export const calcStart = (container: Element) => { }; export const calcThemeColor = ( colorGaps: IKnobColorGap[] | undefined, colorGaps: IColorGap[] | undefined, theme: TThemeColor, darknessTheme: TDarkness, value: number, Loading
src/components/ProgressBar/ProgressBar.stories.ts 0 → 100644 +140 −0 Original line number Diff line number Diff line import type { Meta, StoryObj } from '@storybook/vue3'; import ProgressBar from './ProgressBar.vue'; const meta: Meta = { title: 'Components/ProgressBar', component: ProgressBar, tags: ['autodocs'], parameters: { docs: { description: { component: 'A component that is used as a ProgressBar.', }, }, }, argTypes: { value: { control: 'number' }, max: { control: 'number' }, width: { control: 'text' }, height: { control: 'text' }, labelBefore: { control: 'text' }, labelAfter: { control: 'text' }, showLabel: { control: 'boolean' }, noBorder: { control: 'boolean' }, size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, fontSize: { control: 'text' }, colorGaps: { control: 'object' }, colorInactiveGaps: { control: 'object' }, darknessTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'] }, darknessInactiveTheme: { control: 'select', options: ['100', '200', '300', '400', '500', '600', '700', '800', '900'], }, theme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, inactiveTheme: { control: 'select', options: [ 'white', 'blue', 'sky', 'cyan', 'teal', 'green', 'yellow', 'orange', 'pink', 'fuchsia', 'purple', 'indigo', 'rose', 'red', 'black', ], }, }, args: {}, } satisfies Meta<typeof ProgressBar>; export default meta; type Story = StoryObj<typeof meta>; export const Simple: Story = { args: { value: 40, }, }; export const Small: Story = { args: { size: 'small', value: 40, theme: 'red', inactiveTheme: 'red', labelAfter: '/100', width: '500px', }, }; export const Full: Story = { args: { colorGaps: [ { start: 0, end: 10, color: 'purple', darknessColor: '700', }, { start: 10, end: 20, color: 'red', }, { start: 20, end: 30, color: 'orange', }, { start: 30, end: 40, color: 'yellow', }, { start: 40, end: 50, color: 'green', }, ], size: 'huge', value: 35, max: 50, labelAfter: '', showLabel: true, labelBefore: '$', inactiveTheme: 'white', darknessInactiveTheme: '400', noBorder: true, }, };
src/components/ProgressBar/ProgressBar.vue 0 → 100644 +84 −0 Original line number Diff line number Diff line <script setup lang="ts"> import type { IProgressBarProps } from '@interfaces/componentsProps'; import { computed } from 'vue'; import { convertThemeToColor, convertThemeToTextColor } from '@helpers/common'; const props = withDefaults(defineProps<IProgressBarProps>(), { value: 0, max: 100, size: 'normal', theme: 'black', inactiveTheme: 'white', darknessTheme: '500', darknessInactiveTheme: '300', showLabel: true, labelAfter: '%', }); const active = computed(() => `${(props.value / props.max) * 100}%`); const activeColor = computed(() => { if (!props.colorGaps) return convertThemeToColor(props.theme, props.darknessTheme); const current = props.colorGaps.find((item) => item.start <= props.value && props.value <= item.end); if (!current) return convertThemeToColor(props.theme, props.darknessTheme); return convertThemeToColor(current.color, current.darknessColor); }); const inactiveColor = computed(() => { if (!props.colorInactiveGaps) return convertThemeToColor(props.inactiveTheme, props.darknessInactiveTheme); const current = props.colorInactiveGaps.find((item) => item.start <= props.value && props.value <= item.end); if (!current) return convertThemeToColor(props.inactiveTheme, props.darknessInactiveTheme); return convertThemeToColor(current.color, current.darknessColor); }); const textColor = computed(() => convertThemeToTextColor(props.theme, props.darknessTheme)); const fontSize = computed(() => { if (props.fontSize) return props.fontSize; const size = props.size; if (size === 'normal') return '16px'; if (size === 'large') return '20px'; if (size === 'huge') return '24px'; return '12px'; }); const defaultHeight = computed(() => { const size = props.size; if (size === 'normal') return '30px'; if (size === 'large') return '45px'; if (size === 'huge') return '60px'; return '15px'; }); </script> <template> <section class="container" :style="`width: ${width ?? '300px'}; height: ${height ?? defaultHeight}; border: ${noBorder ? '' : '2px solid black'}`" > <div class="active"> <span v-show="showLabel" class="value">{{ labelBefore }}{{ value }}{{ labelAfter }}</span> </div> </section> </template> <style scoped> .container { position: relative; overflow: hidden; border-radius: calc(v-bind(fontSize) / 2.5); background-color: v-bind(inactiveColor); } .active { width: v-bind(active); height: 100%; overflow: hidden; display: flex; justify-content: center; align-items: center; position: absolute; top: 0; left: 0; transition: width 0.4s ease-in-out; background-color: v-bind(activeColor); } .value { font-weight: bold; font-size: v-bind(fontSize); color: v-bind(textColor); } </style>