working on types....
This commit is contained in:
parent
bbe68f489f
commit
b7fc8b6064
3 changed files with 52 additions and 24 deletions
|
|
@ -48,3 +48,10 @@ export interface ScrollerStep {
|
|||
*/
|
||||
foregroundProps?: object;
|
||||
}
|
||||
|
||||
/** Datum type for data that goes into the Table component */
|
||||
type TableDatum = {
|
||||
[key: string]: string | number | boolean | undefined | null;
|
||||
searchStr?: string;
|
||||
};
|
||||
export type TableData = TableDatum[];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
<!-- @component `Table` [Read the docs.](https://reuters-graphics.github.io/graphics-components/?path=/docs/components-text-elements-table--docs) -->
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
/** Import local helpers */
|
||||
import Block from '../Block/Block.svelte';
|
||||
import Pagination from './Pagination.svelte';
|
||||
|
|
@ -10,9 +8,13 @@
|
|||
import SearchInput from '../SearchInput/SearchInput.svelte';
|
||||
import { filterArray, paginateArray, getOptions } from './utils';
|
||||
|
||||
// Types
|
||||
import type { TableData } from '../@types/global';
|
||||
|
||||
interface Props {
|
||||
/** Data for the table as an array of objects. */
|
||||
data: object[];
|
||||
data: TableData;
|
||||
|
||||
/** A title that runs above the table. */
|
||||
title?: string;
|
||||
/** A block of text that runs above the table. */
|
||||
|
|
@ -184,15 +186,16 @@
|
|||
console.log('currentPageData', currentPageData);
|
||||
});
|
||||
|
||||
/** Boot it up. */
|
||||
onMount(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data.forEach((d: any) => {
|
||||
// Compose the string we will allow users to search
|
||||
d.searchStr = includedFieldsDerived
|
||||
.map((field) => d[field])
|
||||
.join(' ')
|
||||
.toLowerCase();
|
||||
/** Add the `searchStr` field to data */
|
||||
let searchableData = $derived.by(() => {
|
||||
return data.map((d) => {
|
||||
return {
|
||||
...d,
|
||||
searchStr: includedFieldsDerived
|
||||
.map((field) => d[field])
|
||||
.join(' ')
|
||||
.toLowerCase(),
|
||||
};
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
@ -234,7 +237,9 @@
|
|||
<table
|
||||
class="w-full"
|
||||
class:paginated
|
||||
class:truncated={truncated && !showAll && data.length > truncateLength}
|
||||
class:truncated={truncated &&
|
||||
!showAll &&
|
||||
searchableData.length > truncateLength}
|
||||
>
|
||||
<thead class="table--thead">
|
||||
<tr>
|
||||
|
|
@ -310,7 +315,7 @@
|
|||
{/if}
|
||||
</table>
|
||||
</div>
|
||||
{#if truncated && data.length > truncateLength}
|
||||
{#if truncated && searchableData.length > truncateLength}
|
||||
<nav
|
||||
aria-label="Show all button"
|
||||
class="show-all flex items-center justify-center fmt-2"
|
||||
|
|
@ -319,7 +324,7 @@
|
|||
{#if showAll}
|
||||
Show fewer rows
|
||||
{:else}
|
||||
Show {data.length - truncateLength}
|
||||
Show {searchableData.length - truncateLength}
|
||||
more rows
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
export function filterArray(data, searchText, filterField, filterValue) {
|
||||
import type { TableData } from '../@types/global';
|
||||
|
||||
export function filterArray(
|
||||
data: TableData,
|
||||
searchText: string,
|
||||
filterField: string | undefined,
|
||||
filterValue: string
|
||||
) {
|
||||
if (searchText) {
|
||||
data = data.filter((item) => {
|
||||
return item.searchStr.includes(searchText.toLowerCase());
|
||||
return item.searchStr?.includes(searchText.toLowerCase());
|
||||
});
|
||||
}
|
||||
if (filterValue && filterValue) {
|
||||
if (filterField && filterValue) {
|
||||
data = data.filter((item) => {
|
||||
return item[filterField] === filterValue;
|
||||
});
|
||||
|
|
@ -12,25 +19,34 @@ export function filterArray(data, searchText, filterField, filterValue) {
|
|||
return data;
|
||||
}
|
||||
|
||||
export function paginateArray(array, pageSize, pageNumber) {
|
||||
export function paginateArray(
|
||||
array: TableData,
|
||||
pageSize: number,
|
||||
pageNumber: number
|
||||
) {
|
||||
return array.slice((pageNumber - 1) * pageSize, pageNumber * pageSize);
|
||||
}
|
||||
|
||||
function uniqueAttr(array, attr) {
|
||||
function uniqueAttr(array: TableData, attr: string) {
|
||||
return array.map((e) => e[attr]).filter(unique);
|
||||
}
|
||||
|
||||
function unique(value, index, array) {
|
||||
// rewrite this with types
|
||||
function unique(value: any, index: number, array: TableData) {
|
||||
return array.indexOf(value) === index;
|
||||
}
|
||||
|
||||
export function getOptions(data, attr) {
|
||||
export function getOptions(data: TableData, attr: string) {
|
||||
// Get all the unique values in the provided field. Sort it.
|
||||
const attrList = uniqueAttr(data, attr).sort((a, b) => a.localeCompare(b));
|
||||
|
||||
// @TODO - check if a and b need to be typed and sorted for non-strings
|
||||
const attrList = uniqueAttr(data, attr).sort((a: any, b: any) =>
|
||||
a.localeCompare(b)
|
||||
);
|
||||
|
||||
// Tack 'All' as the front as the first option.
|
||||
attrList.unshift('All');
|
||||
|
||||
// Convert the list into Option typed objects ready for our Select component
|
||||
return attrList.map((a) => ({ text: a, value: a }));
|
||||
return attrList.map((a: string) => ({ text: a, value: a }));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue