diff --git a/src/common/interfaces/componentsProps.ts b/src/common/interfaces/componentsProps.ts index e509e0de717f187301c43d369f4cbf5d7fc4cdf9..c42ddc71ee2f38726b149f0afa6befa0e26d3074 100644 --- a/src/common/interfaces/componentsProps.ts +++ b/src/common/interfaces/componentsProps.ts @@ -24,6 +24,7 @@ export interface ITableProps { data: ITableItem[][]; multipleSort?: boolean; gap?: string; + size?: TSize; showAllLines?: boolean; stripedRows?: boolean; center?: boolean; diff --git a/src/stories/components/Table/Table.stories.ts b/src/stories/components/Table/Table.stories.ts index 7d417174a86572a2a1ff3d799847347b471d6cec..98769a8d5201f20c16d05b779e48f3847393c3c5 100644 --- a/src/stories/components/Table/Table.stories.ts +++ b/src/stories/components/Table/Table.stories.ts @@ -18,6 +18,7 @@ const meta: Meta = { data: { control: 'text' }, fontSize: { control: 'text' }, gap: { control: 'text' }, + size: { control: 'select', options: ['small', 'normal', 'large', 'huge'] }, showAllLines: { control: 'boolean' }, stripedRows: { control: 'boolean' }, center: { control: 'boolean' }, @@ -125,12 +126,14 @@ export const Full: Story = { name: 'Name', type: 'text', sortable: true, + initSort: 'none', }, { name: 'Age', type: 'number', sortable: true, filterable: true, + initSort: 'down', }, { name: 'Hobbies', @@ -138,12 +141,15 @@ export const Full: Story = { padding: '30px', filterable: true, sortable: true, + initSort: 'none', }, { name: 'Country', type: 'text', + initSort: 'none', }, ], + data: [ [ { @@ -216,12 +222,14 @@ export const Full: Story = { }, ], ], - fontSize: '20px', + + fontSize: '24px', showAllLines: true, border: 'fuchsia', theme: 'black', stripedRows: true, darknessTextColor: '500', center: true, + size: 'large', }, }; diff --git a/src/stories/components/Table/Table.vue b/src/stories/components/Table/Table.vue index 9fd0ddb72879a40531f789e466c7b9874d44137f..5a254bc854dcff0f920ef5c699b143bd68a204cf 100644 --- a/src/stories/components/Table/Table.vue +++ b/src/stories/components/Table/Table.vue @@ -3,10 +3,11 @@ import type { ITableProps } from '@interfaces/componentsProps'; import { computed, ref, watch } from 'vue'; import { convertThemeToColor, convertThemeToSecondaryColor, convertThemeToTextColor } from '@helpers/common'; import type { ITableItem } from '@interfaces/componentsProp'; -import { calcGap, calcRows } from '@stories/components/Table/helpers'; +import { calcAdditionalHeight, calcGap, calcRows } from '@stories/components/Table/helpers'; import TableHeader from '@stories/components/Table/TableHeader.vue'; const props = withDefaults(defineProps<ITableProps>(), { + size: 'normal', theme: 'white', darknessTheme: '500', fontSize: '16px', @@ -23,6 +24,7 @@ const isRegisterSensitive = ref<boolean>(false); watch(props.columns, () => (columns.value = props.columns)); const initGap = computed(() => calcGap(props.gap, props.fontSize)); +const additionalHeightFromSize = computed(() => calcAdditionalHeight(props.size, props.fontSize)); const themeColor = computed(() => convertThemeToColor(props.theme, props.darknessTheme)); const color = computed(() => props.textColor @@ -44,7 +46,8 @@ const rows = computed<ITableItem[][]>(() => data.value!, sortStateActive.value, props.multipleSort, - props.columns[sortStateActive.value[0] ?? 0].type, + columnToFilter.value, + props.columns[columnToFilter.value ?? 0].type, filterValue.value, isRegisterSensitive.value, ), @@ -95,6 +98,7 @@ const cancelFilter = () => { :sortState="sortState" :columnToFilter="columnToFilter" :initGap="initGap" + :additionalHeightFromSize="additionalHeightFromSize" :theme="theme" :themeColor="themeColor" :secondaryColor="secondaryColor" @@ -116,7 +120,7 @@ const cancelFilter = () => { }" v-for="item of row" :key="item.value" - :style="`padding: calc(${initGap} / 2) ${initGap}; text-align: ${center ? 'center' : 'start'}`" + :style="`padding: calc(${initGap} / 2 + ${additionalHeightFromSize}) ${initGap}; text-align: ${center ? 'center' : 'start'}`" > {{ item.value }} </td> diff --git a/src/stories/components/Table/TableHeader.vue b/src/stories/components/Table/TableHeader.vue index 074eed4faee066d8ac73e80878d625bc9bc1a4ab..13264907b50be79103cf356b397065d17b96690e 100644 --- a/src/stories/components/Table/TableHeader.vue +++ b/src/stories/components/Table/TableHeader.vue @@ -17,6 +17,7 @@ interface Props { sortState: string[]; columnToFilter: number; initGap: string; + additionalHeightFromSize: string; theme: TThemeColor; themeColor: string; secondaryColor: string; @@ -54,7 +55,7 @@ const isColumnTypeText = computed(() => props.columns[props.columnToFilter].type }" v-for="(column, index) of columns" :key="column.name" - :style="`padding: calc(${initGap} / 2) ${initGap}`" + :style="`padding: calc(${initGap} / 2 + ${additionalHeightFromSize}) ${initGap}`" > <div :style="`justify-content: ${center ? 'center' : 'start'}; gap: ${center ? '0' : initGap}; padding: ${calcColumnPadding(column, center, initGap)}`" @@ -67,7 +68,7 @@ const isColumnTypeText = computed(() => props.columns[props.columnToFilter].type <button v-if="column.sortable" @click.prevent="emit('changeColumnSortMode', index)" - style="min-width: 20px; min-height: 20px" + :style="`min-width: ${fontSize}; min-height: ${fontSize}; max-height: ${fontSize}`" > <SortVerticalIcon v-show="sortState[index] === 'none'" :color="color" :size="iconSize" /> <SortDownIcon v-show="sortState[index] === 'down'" :color="color" :size="iconSize" /> @@ -77,7 +78,7 @@ const isColumnTypeText = computed(() => props.columns[props.columnToFilter].type v-if="column.filterable" @pointerdown="emit('setFilter', index)" :id="`filter${index}`" - style="position: relative" + :style="`position: relative; width: ${fontSize}; max-height: ${fontSize}`" > <FilterIcon :color="color" :size="iconSize" /> </button> diff --git a/src/stories/components/Table/helpers.ts b/src/stories/components/Table/helpers.ts index 4d7b2dee741fc3b20a3cf6ef300e702be5001d0c..6ebe2797f615c95f0c3bcf94be426fb9ef87089e 100644 --- a/src/stories/components/Table/helpers.ts +++ b/src/stories/components/Table/helpers.ts @@ -1,20 +1,21 @@ import type { ITableColumn, ITableItem, TTableColumnType } from '@interfaces/componentsProp'; +import type { TSize } from '@interfaces/common'; export const calcRows = ( initRows: ITableItem[][], sortStateActive: [number, string] | [], multipleSort: boolean, + columnToFilter: number, columnToFilterType: TTableColumnType, filterValue: string, isRegisterSensitive: boolean, ) => { // ['up', 'down', ...] let rows = [...initRows]; - const sortIndex = sortStateActive[0]; - if (filterValue && sortIndex) { + if (filterValue) { rows = rows.filter((row) => { - const item = isRegisterSensitive ? row[sortIndex].value : row[sortIndex].value.toLowerCase(); + const item = isRegisterSensitive ? row[columnToFilter].value : row[columnToFilter].value.toLowerCase(); return item.startsWith(isRegisterSensitive ? filterValue : filterValue.toLowerCase()); }); } @@ -41,6 +42,7 @@ export const calcRows = ( } else { const index = sortStateActive[0]; const value = sortStateActive[1]; + console.log('index, value, columnToFilterType:', index, value, columnToFilterType); if (columnToFilterType === 'number') return rows.sort((a, b) => value === 'down' ? +a[index].value - +b[index].value : +b[index].value - +a[index].value, @@ -59,5 +61,17 @@ export const calcGap = (gap: string, fontSize: string) => ? '10px' : '15px'); +export const calcAdditionalHeight = (size: TSize, fontSize: string) => { + if (size === 'normal') return '0px'; + + const isTwoLetters = isFinite(+fontSize.at(-3)!); + const value = isTwoLetters ? fontSize.slice(0, -2) : fontSize.slice(0, -3); + const unit = isTwoLetters ? fontSize.slice(-2) : fontSize.slice(-3); + + if (size === 'large') return +value / 2 + unit; + if (size === 'huge') return value + unit; + return -+value / 4 + unit; +}; + export const calcColumnPadding = (column: ITableColumn, center: boolean, gap: string) => center ? `0px calc(${gap} / 2 + ${column.padding ?? '0px'} / 2)` : `0 ${column.padding ?? '0px'} 0 0`;