Assembled first draft

This commit is contained in:
palewire 2023-03-27 14:42:00 -04:00
parent 14771cd9c4
commit af8097cf24
No known key found for this signature in database
GPG key ID: A5AD4A9AD42D69AB
15 changed files with 45730 additions and 30432 deletions

44296
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -4,14 +4,28 @@
// Don't lose the "?raw" in markdown imports!
// @ts-ignore
import componentDocs from './stories/docs/component.md?raw';
// @ts-ignore
import metadataDocs from './stories/docs/metadata.md?raw';
// @ts-ignore
import searchDocs from './stories/docs/search.md?raw';
// @ts-ignore
import filterDocs from './stories/docs/filter.md?raw';
// @ts-ignore
import bothDocs from './stories/docs/both.md?raw';
// @ts-ignore
import sortDocs from './stories/docs/sort.md?raw';
// @ts-ignore
import formatDocs from './stories/docs/format.md?raw';
import Table from './Table.svelte';
import { withComponentDocs } from '$docs/utils/withParams.js';
import { withComponentDocs, withStoryDocs } from '$docs/utils/withParams.js';
// You can import JSON you need in stories directly in code!
// @ts-ignore
import AirportsData from './stories/airports.json';
import pressFreedom from './stories/pressFreedom.json';
import homeRuns from './stories/homeRuns.json';
import richestWomen from './stories/richestWomen.json';
const meta = {
title: 'Components/Table',
@ -37,7 +51,83 @@
name="Default"
args="{{
width: 'normal',
data: AirportsData,
includedFields: ['iata', 'name', 'city', 'state'],
data: homeRuns,
}}"
/>
<Story
name="Metadata"
{...withStoryDocs(metadataDocs)}
args="{{
width: 'normal',
data: homeRuns,
title: 'Career home run leaders',
notes: 'As of Opening Day 2023',
}}"
/>
<Story
name="Search"
{...withStoryDocs(searchDocs)}
args="{{
data: pressFreedom,
searchable: true,
title: 'Press Freedom Index',
notes:
"Source: <a href='https://en.wikipedia.org/wiki/Press_Freedom_Index'>Reporters Without Borders</a>",
}}"
/>
<Story
name="Filter"
{...withStoryDocs(filterDocs)}
args="{{
data: pressFreedom,
filterField: 'Region',
title: 'Press Freedom Index',
notes:
"Source: <a href='https://en.wikipedia.org/wiki/Press_Freedom_Index'>Reporters Without Borders</a>",
}}"
/>
<Story
name="Search and filter"
{...withStoryDocs(bothDocs)}
args="{{
data: pressFreedom,
searchable: true,
filterField: 'Region',
title: 'Press Freedom Index',
notes:
"Source: <a href='https://en.wikipedia.org/wiki/Press_Freedom_Index'>Reporters Without Borders</a>",
}}"
/>
<Story
name="Sort"
{...withStoryDocs(sortDocs)}
args="{{
data: pressFreedom,
title: 'Press Freedom Index',
notes:
"Source: <a href='https://en.wikipedia.org/wiki/Press_Freedom_Index'>Reporters Without Borders</a>",
sortable: true,
sortField: 'Score',
sortDirection: 'descending',
}}"
/>
<Story
name="Format"
{...withStoryDocs(formatDocs)}
args="{{
data: richestWomen,
title: 'The Richest Women in the World',
notes:
"Source: <a href='https://www.forbes.com/sites/rachelsandler/2022/04/05/the-top-richest-women-in-the-world-2022/?sh=29c2f69446a8'>Forbes</a>",
sortable: true,
sortField: 'Net worth (in billions)',
sortDirection: 'descending',
fieldFormatters: { 'Net worth (in billions)': (v) => '$' + v },
}}"
/>

View file

@ -4,23 +4,94 @@
/**
* A source for the data.
* @type []
* @required
*/
export let data: [];
// A list of the fields to include in the table. By default everything goes.
export let includedFields: string[] = Object.keys(data[0]);
/**
* A title that runs above the table.
* @type string
*/
export let title: string;
export let allowSearch: boolean = true;
export let searchPlaceholder: string = 'Type to search';
/**
* A footnote that runs below the table.
* @type string
*/
export let notes: string;
// Table row limit
/**
* list of the fields to include in the table. By default everything goes.
* @type []
*/
export let includedFields: string[] = Object.keys(data[0]).filter(
(f) => f !== 'searchStr'
);
/**
* The default page size.
* @type number
*/
export let pageSize: number = 25;
// You can declare custom types to help users implement your component.
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
/**
* Whether or not searches are allowed.
* @type boolean
*/
export let searchable: boolean = false;
/**
* The label to place above the search box.
* @type string
*/
export let searchLabel: string;
/**
* The placeholder text that appears in the search box.
* @type string
*/
export let searchPlaceholder: string;
/**
* A field to offer uses as an interactive filter.
* @type string
*/
export let filterField: string;
/**
* The label to place above the filter box
* @type string
*/
export let filterLabel: string;
/**
* Whether or not sorts are allowed.
* @type boolean
*/
export let sortable: boolean = false;
/**
* The column to sort by. By default it's the first header.
* @type string
*/
export let sortField: string = Object.keys(data[0])[0];
/**
* The direction of the sort. By default it's ascending.
* @type SortDirection
*/
type SortDirection = 'ascending' | 'descending';
export let sortDirection: SortDirection = 'ascending';
/**
* Custom field formatting functions. Should be keyed to the name of the field.
* @type object
*/
export let fieldFormatters: object = {};
/** Width of the component within the text well. */
type ContainerWidth = 'normal' | 'wide' | 'wider' | 'widest' | 'fluid';
export let width: ContainerWidth = 'normal';
/** Add an ID to target with SCSS. */
@ -31,20 +102,52 @@
/** Import local helpers */
import Block from '../Block/Block.svelte';
import { filterArray, paginateArray, numberWithCommas } from './utils.js';
import {
filterArray,
paginateArray,
numberWithCommas,
uniqueAttr,
isNumeric,
} from './utils.js';
/** Set filtering and pagination configuration */
let pageNumber = 1;
let searchText = '';
$: filteredData = filterArray(data, searchText);
$: currentPageData = paginateArray(filteredData, pageSize, pageNumber);
const filterList = filterField
? uniqueAttr(data, filterField).sort((a, b) => a.localeCompare(b))
: undefined;
let filterValue = '';
$: filteredData = filterArray(data, searchText, filterField, filterValue);
$: sortedData = sortArray(filteredData, sortField, sortDirection);
$: currentPageData = paginateArray(sortedData, pageSize, pageNumber);
//* * Handle filtering and pagination events */
// Estimate the text alignment of our fields. Strings go left. Numbers go right.
function getAlignment(value) {
return isNumeric(value) ? 'right' : 'left';
}
const fieldAlignments = includedFields.reduce((acc, cur) => {
acc[cur] = getAlignment(data[0][cur]);
return acc;
}, {});
//* * Handle search, filter, sort and pagination events */
function handleSearchInput(event) {
searchText = event.target.value;
pageNumber = 1;
}
function handleFilterInput(event) {
const value = event.target.value;
filterValue = value === 'all' ? '' : value;
pageNumber = 1;
}
function handleSort(event) {
if (!sortable) return;
sortField = event.target.getAttribute('data-field');
sortDirection = sortDirection === 'ascending' ? 'descending' : 'ascending';
}
function goToPreviousPage() {
if (pageNumber > 1) {
pageNumber -= 1;
@ -57,9 +160,33 @@
}
}
function sortArray(array, column, direction) {
if (!sortable) return array;
return array.sort((a, b) => {
if (a[column] < b[column]) {
return direction === 'ascending' ? -1 : 1;
} else if (a[column] > b[column]) {
return direction === 'ascending' ? 1 : -1;
} else {
return 0;
}
});
}
function formatValue(item, field) {
const value = item[field];
if (field in fieldFormatters) {
const func = fieldFormatters[field];
return func(value);
} else {
return value;
}
}
/** Boot it up. */
onMount(() => {
data.forEach((d) => {
// Compose the string we will allow users to search
d.searchStr = includedFields
.map((field) => d[field])
.join(' ')
@ -70,39 +197,96 @@
<Block width="{width}" id="{id}" cls="{cls}">
<section class="table-wrapper">
{#if allowSearch}
{#if searchable || filterList}
<section class="input">
<div class="search">
<input
id="search--input"
class="search--input"
type="text"
placeholder="{searchPlaceholder}"
on:input="{handleSearchInput}"
/>
</div>
{#if searchable}
<div class="search">
<label for="filter--select"
>{#if searchLabel}{searchLabel}{:else}Search{/if}</label
>
<input
id="search--input"
class="search--input"
type="text"
placeholder="{searchPlaceholder}"
on:input="{handleSearchInput}"
/>
</div>
{/if}
{#if filterList}
{#if searchable}<div
style="clear: both; display: block; padding-top: 1rem;"
></div>{/if}
<div class="filter">
<label for="filter--select"
>{#if filterLabel}{filterLabel}{:else}Filter by {filterField}{/if}</label
>
<select
class="filter--select"
name="filter--select"
id="filter--select"
on:input="{handleFilterInput}"
>
<option value="all">All</option>
{#each filterList as object}
<option value="{object}">{object}</option>
{/each}
</select>
</div>
{/if}
</section>
{/if}
<section class="table">
<table>
<thead>
{#if title}
<caption class="table--caption table--caption--title"
>{@html title}</caption
>
{/if}
<thead class="table--thead">
<tr>
{#each includedFields as field}
<th>{field}</th>
<th
scope="col"
class:sortable
class:sort-ascending="{sortable &&
sortField === field &&
sortDirection === 'ascending'}"
class:sort-descending="{sortable &&
sortField === field &&
sortDirection === 'descending'}"
data-field="{field}"
on:click="{handleSort}"
style="text-align: {fieldAlignments[field]}"
>
{field}
</th>
{/each}
</tr>
</thead>
<tbody>
<tbody class="table--tbody">
{#each currentPageData as item, idx}
<tr data-row-index="{idx}">
{#each includedFields as field}
<td>
{@html item[field]}
<td
data-row-index="{idx}"
data-field="{field}"
data-value="{item[field]}"
style="text-align: {fieldAlignments[field]}"
>
{@html formatValue(item, field)}
</td>
{/each}
</tr>
{/each}
</tbody>
{#if notes}
<tfoot class="table--tfoot table--tfoot--footnote">
<tr>
<td colspan="{includedFields.length}">{@html notes}</td>
</tr>
</tfoot>
{/if}
</table>
</section>
{#if filteredData.length > pageSize}
@ -166,12 +350,35 @@
font-size: 1rem;
font-family: var(--theme-font-family-sans-serif, $font-family-sans-serif);
color: var(--theme-colour-text-primary, $tr-dark-grey);
.table--caption--title {
caption-side: top;
font-weight: 500;
color: var(--theme-colour-text-primary, $tr-dark-grey);
font-size: 1.25rem;
}
thead {
tr {
border-bottom: 1px solid $tr-muted-grey;
th {
font-weight: 500;
vertical-align: bottom;
line-height: 1.4;
&.sortable {
cursor: pointer;
}
&.sort-ascending:after {
content: ' ▲';
font-size: 0.75rem;
color: $tr-orange;
vertical-align: 10%;
padding: 0 0 0 0.0612rem;
}
&.sort-descending:after {
content: ' ▼';
font-size: 0.75rem;
color: $tr-orange;
vertical-align: 10%;
padding: 0 0 0 0.0612rem;
}
}
}
}
@ -180,7 +387,18 @@
border-bottom: 1px solid $tr-light-muted-grey;
}
td {
line-height: 2rem;
padding: 0.333rem 0;
}
}
.table--tfoot--footnote {
tr {
border-bottom: 0;
}
td {
font-weight: 400;
color: var(--theme-colour-text-primary, $tr-dark-grey);
font-size: 0.75rem;
padding: 0.666rem 0 0 0;
}
}
}
@ -189,14 +407,31 @@
section.input {
margin: 16px 0;
background-color: $tr-ultra-light-grey;
padding: 1.25rem 0.75rem;
padding: 0.75rem;
font-size: 1rem;
width: 100%;
border: 1px solid $tr-light-muted-grey;
label {
line-height: 1.333;
display: block;
font-size: 1.125rem;
font-family: $font-family-display;
font-weight: 500;
}
.search {
.search--input {
padding: 0.33rem;
font-size: 1.15rem;
font-size: 1.1rem;
height: 2.3rem;
border: 1px solid $tr-muted-grey;
border-radius: 5px;
width: 300px;
}
}
.filter {
.filter--select {
padding: 0.33rem;
font-size: 1.1rem;
height: 2.3rem;
border: 1px solid $tr-muted-grey;
border-radius: 5px;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
Feel free to both search and filter.
```svelte
<Table
data={yourData},
searchable=true,
filterField='Region',
title='Press Freedom Index',
notes='Source: <a href="https://en.wikipedia.org/wiki/Press_Freedom_Index">Reporters Without Borders</a>',
/>
```

View file

@ -1,4 +1,4 @@
Present structured data in an interactive table
Present structured data in a table. Consider making it interactive.
---
@ -6,11 +6,9 @@ Present structured data in an interactive table
<script>
import { Table } from '@reuters-graphics/graphics-components';
const sampleData = [];
// Import your data as JSON, or otherwise structure it
import yourData from './stories/homeRuns.json';
</script>
<Table
width: 'normal',
data: sampleData,
/>
<Table data="{yourData}" />
```

View file

@ -0,0 +1,10 @@
Allow users to filter the table by providing one of the attributes as the `filterField`. This works best with categorical columns.
```svelte
<Table
data={yourData},
filterField='Region',
title='Press Freedom Index',
notes='Source: <a href="https://en.wikipedia.org/wiki/Press_Freedom_Index">Reporters Without Borders</a>',
/>
```

View file

@ -0,0 +1,19 @@
Provide custom formatters by providing functions keyed to your field names to the `fieldFormatters` option. Columns are still sorted by the raw, underlying values. This can be used to provide the unit of measurement with numeric fields.
```svelte
<script lang="ts">
const fieldFormatters = {
'Net worth (in billions)': (v) => '$' + v
};
</script>
<Table
data={yourData}
fieldFormatters={fieldFormatters},
sortable=true,
sortField='Score',
sortDirection='descending',
title='Press Freedom Index',
notes='Source: <a href="https://en.wikipedia.org/wiki/Press_Freedom_Index">Reporters Without Borders</a>',
/>
```

View file

@ -0,0 +1,9 @@
Set the `title` and `notes` options to add supporting metadata above and below the table.
```svelte
<Table
data="{yourData}"
title="Career home run leaders"
notes="As of Opening Day 2023"
/>
```

View file

@ -0,0 +1,10 @@
Allow users to search the table by setting the optional `searchable` variable to `true`.
```svelte
<Table
data={yourData},
searchable=true,
title='Press Freedom Index',
notes='Source: <a href="https://en.wikipedia.org/wiki/Press_Freedom_Index">Reporters Without Borders</a>',
/>
```

View file

@ -0,0 +1,12 @@
Allow users to sort the table by setting the optional `searchable` variable to `true`. Specify the starting order by setting `sortField` to a column name and `sortDirection` to `ascending` or `descending`.
```svelte
<Table
data={yourData}
sortable=true,
sortField='Score',
sortDirection='descending',
title='Press Freedom Index',
notes='Source: <a href="https://en.wikipedia.org/wiki/Press_Freedom_Index">Reporters Without Borders</a>',
/>
```

View file

@ -0,0 +1,42 @@
[
{
"Name": "Barry Bonds",
"Home runs": 762
},
{
"Name": "Hank Aaron",
"Home runs": 755
},
{
"Name": "Babe Ruth",
"Home runs": 714
},
{
"Name": "Albert Pujols",
"Home runs": 703
},
{
"Name": "Alex Rodriguez",
"Home runs": 696
},
{
"Name": "Willie Mays",
"Home runs": 660
},
{
"Name": "Ken Griffey Jr.",
"Home runs": 630
},
{
"Name": "Jim Thome",
"Home runs": 612
},
{
"Name": "Sammy Sosa",
"Home runs": 609
},
{
"Name": "Frank Robinson",
"Home runs": 586
}
]

View file

@ -0,0 +1,887 @@
[
{
"Country": "Afghanistan",
"Region": "Southern Asia",
"Score": 40.19
},
{
"Country": "Albania",
"Region": "Southern Europe",
"Score": 30.59
},
{
"Country": "Algeria",
"Region": "Northern Africa",
"Score": 47.26
},
{
"Country": "Andorra",
"Region": "Southern Europe",
"Score": 23.32
},
{
"Country": "Angola",
"Region": "Sub-Saharan Africa",
"Score": 34.06
},
{
"Country": "Argentina",
"Region": "Latin America and the Caribbean",
"Score": 28.99
},
{
"Country": "Armenia",
"Region": "Western Asia",
"Score": 28.83
},
{
"Country": "Australia",
"Region": "Australia and New Zealand",
"Score": 19.79
},
{
"Country": "Austria",
"Region": "Western Europe",
"Score": 16.34
},
{
"Country": "Azerbaijan",
"Region": "Western Asia",
"Score": 58.77
},
{
"Country": "Bahrain",
"Region": "Western Asia",
"Score": 61.1
},
{
"Country": "Bangladesh",
"Region": "Southern Asia",
"Score": 49.71
},
{
"Country": "Belarus",
"Region": "Eastern Europe",
"Score": 50.82
},
{
"Country": "Belgium",
"Region": "Western Europe",
"Score": 11.69
},
{
"Country": "Belize",
"Region": "Latin America and the Caribbean",
"Score": 27.61
},
{
"Country": "Benin",
"Region": "Sub-Saharan Africa",
"Score": 38.18
},
{
"Country": "Bhutan",
"Region": "Southern Asia",
"Score": 28.86
},
{
"Country": "Bolivia",
"Region": "Latin America and the Caribbean",
"Score": 35.47
},
{
"Country": "Bosnia and Herzegovina",
"Region": "Southern Europe",
"Score": 28.34
},
{
"Country": "Botswana",
"Region": "Sub-Saharan Africa",
"Score": 23.25
},
{
"Country": "Brazil",
"Region": "Latin America and the Caribbean",
"Score": 36.25
},
{
"Country": "Brunei",
"Region": "South-eastern Asia",
"Score": 49.91
},
{
"Country": "Bulgaria",
"Region": "Eastern Europe",
"Score": 37.29
},
{
"Country": "Burkina Faso",
"Region": "Sub-Saharan Africa",
"Score": 23.17
},
{
"Country": "Burundi",
"Region": "Sub-Saharan Africa",
"Score": 47.57
},
{
"Country": "Cambodia",
"Region": "South-eastern Asia",
"Score": 46.84
},
{
"Country": "Cameroon",
"Region": "Sub-Saharan Africa",
"Score": 43.78
},
{
"Country": "Canada",
"Region": "Northern America",
"Score": 15.25
},
{
"Country": "Cape Verde",
"Region": "Sub-Saharan Africa",
"Score": 20.09
},
{
"Country": "Central African Republic",
"Region": "Sub-Saharan Africa",
"Score": 41.92
},
{
"Country": "Chad",
"Region": "Sub-Saharan Africa",
"Score": 40.2
},
{
"Country": "Chile",
"Region": "Latin America and the Caribbean",
"Score": 27.89
},
{
"Country": "China",
"Region": "Eastern Asia",
"Score": 78.72
},
{
"Country": "Colombia",
"Region": "Latin America and the Caribbean",
"Score": 43.74
},
{
"Country": "Comoros",
"Region": "Sub-Saharan Africa",
"Score": 30.65
},
{
"Country": "Congo",
"Region": "Sub-Saharan Africa",
"Score": 38.83
},
{
"Country": "Costa Rica",
"Region": "Latin America and the Caribbean",
"Score": 8.76
},
{
"Country": "Cote d'Ivoire",
"Region": "Sub-Saharan Africa",
"Score": 28.87
},
{
"Country": "Croatia",
"Region": "Southern Europe",
"Score": 27.95
},
{
"Country": "Cuba",
"Region": "Latin America and the Caribbean",
"Score": 63.94
},
{
"Country": "Cyprus",
"Region": "Western Asia",
"Score": 19.85
},
{
"Country": "Czechia",
"Region": "Eastern Europe",
"Score": 23.38
},
{
"Country": "Democratic Republic of Congo",
"Region": "Sub-Saharan Africa",
"Score": 48.59
},
{
"Country": "Denmark",
"Region": "Northern Europe",
"Score": 8.57
},
{
"Country": "Djibouti",
"Region": "Sub-Saharan Africa",
"Score": 78.62
},
{
"Country": "Dominican Republic",
"Region": "Latin America and the Caribbean",
"Score": 25.6
},
{
"Country": "Ecuador",
"Region": "Latin America and the Caribbean",
"Score": 32.83
},
{
"Country": "Egypt",
"Region": "Northern Africa",
"Score": 56.17
},
{
"Country": "El Salvador",
"Region": "Latin America and the Caribbean",
"Score": 30.49
},
{
"Country": "Equatorial Guinea",
"Region": "Sub-Saharan Africa",
"Score": 55.67
},
{
"Country": "Eritrea",
"Region": "Sub-Saharan Africa",
"Score": 81.45
},
{
"Country": "Estonia",
"Region": "Northern Europe",
"Score": 15.25
},
{
"Country": "Eswatini",
"Region": "Sub-Saharan Africa",
"Score": 46.34
},
{
"Country": "Ethiopia",
"Region": "Sub-Saharan Africa",
"Score": 33.63
},
{
"Country": "Fiji",
"Region": "Melanesia",
"Score": 27.92
},
{
"Country": "Finland",
"Region": "Northern Europe",
"Score": 6.99
},
{
"Country": "France",
"Region": "Western Europe",
"Score": 22.6
},
{
"Country": "Gabon",
"Region": "Sub-Saharan Africa",
"Score": 38.6
},
{
"Country": "Gambia",
"Region": "Sub-Saharan Africa",
"Score": 30.76
},
{
"Country": "Georgia",
"Region": "Western Asia",
"Score": 28.64
},
{
"Country": "Germany",
"Region": "Western Europe",
"Score": 15.24
},
{
"Country": "Ghana",
"Region": "Sub-Saharan Africa",
"Score": 21.33
},
{
"Country": "Greece",
"Region": "Southern Europe",
"Score": 29.01
},
{
"Country": "Guatemala",
"Region": "Latin America and the Caribbean",
"Score": 38.45
},
{
"Country": "Guinea",
"Region": "Sub-Saharan Africa",
"Score": 35.42
},
{
"Country": "Guinea-Bissau",
"Region": "Sub-Saharan Africa",
"Score": 32.68
},
{
"Country": "Guyana",
"Region": "Latin America and the Caribbean",
"Score": 25.61
},
{
"Country": "Haiti",
"Region": "Latin America and the Caribbean",
"Score": 31.12
},
{
"Country": "Honduras",
"Region": "Latin America and the Caribbean",
"Score": 49.35
},
{
"Country": "Hong Kong",
"Region": "Eastern Asia",
"Score": 30.44
},
{
"Country": "Hungary",
"Region": "Eastern Europe",
"Score": 31.76
},
{
"Country": "Iceland",
"Region": "Northern Europe",
"Score": 15.37
},
{
"Country": "India",
"Region": "Southern Asia",
"Score": 46.56
},
{
"Country": "Indonesia",
"Region": "South-eastern Asia",
"Score": 37.4
},
{
"Country": "Iran",
"Region": "Southern Asia",
"Score": 72.7
},
{
"Country": "Iraq",
"Region": "Western Asia",
"Score": 55.57
},
{
"Country": "Ireland",
"Region": "Northern Europe",
"Score": 11.91
},
{
"Country": "Israel",
"Region": "Western Asia",
"Score": 30.9
},
{
"Country": "Italy",
"Region": "Southern Europe",
"Score": 23.39
},
{
"Country": "Jamaica",
"Region": "Latin America and the Caribbean",
"Score": 9.96
},
{
"Country": "Japan",
"Region": "Eastern Asia",
"Score": 28.88
},
{
"Country": "Jordan",
"Region": "Western Asia",
"Score": 42.89
},
{
"Country": "Kazakhstan",
"Region": "Central Asia",
"Score": 50.28
},
{
"Country": "Kenya",
"Region": "Sub-Saharan Africa",
"Score": 33.65
},
{
"Country": "Kuwait",
"Region": "Western Asia",
"Score": 34.36
},
{
"Country": "Kyrgyzstan",
"Region": "Central Asia",
"Score": 30.37
},
{
"Country": "Laos",
"Region": "South-eastern Asia",
"Score": 70.56
},
{
"Country": "Latvia",
"Region": "Northern Europe",
"Score": 19.26
},
{
"Country": "Lebanon",
"Region": "Western Asia",
"Score": 34.93
},
{
"Country": "Lesotho",
"Region": "Sub-Saharan Africa",
"Score": 31.61
},
{
"Country": "Liberia",
"Region": "Sub-Saharan Africa",
"Score": 33.36
},
{
"Country": "Libya",
"Region": "Northern Africa",
"Score": 55.73
},
{
"Country": "Liechtenstein",
"Region": "Western Europe",
"Score": 19.49
},
{
"Country": "Lithuania",
"Region": "Northern Europe",
"Score": 20.15
},
{
"Country": "Luxembourg",
"Region": "Western Europe",
"Score": 17.56
},
{
"Country": "Madagascar",
"Region": "Sub-Saharan Africa",
"Score": 28.24
},
{
"Country": "Malawi",
"Region": "Sub-Saharan Africa",
"Score": 28.8
},
{
"Country": "Malaysia",
"Region": "South-eastern Asia",
"Score": 39.47
},
{
"Country": "Maldives",
"Region": "Southern Asia",
"Score": 29.13
},
{
"Country": "Mali",
"Region": "Sub-Saharan Africa",
"Score": 33.5
},
{
"Country": "Malta",
"Region": "Southern Europe",
"Score": 30.46
},
{
"Country": "Mauritania",
"Region": "Sub-Saharan Africa",
"Score": 32.25
},
{
"Country": "Mauritius",
"Region": "Sub-Saharan Africa",
"Score": 28.74
},
{
"Country": "Mexico",
"Region": "Latin America and the Caribbean",
"Score": 46.71
},
{
"Country": "Moldova",
"Region": "Eastern Europe",
"Score": 31.61
},
{
"Country": "Mongolia",
"Region": "Eastern Asia",
"Score": 28.97
},
{
"Country": "Montenegro",
"Region": "Southern Europe",
"Score": 34.33
},
{
"Country": "Morocco",
"Region": "Northern Africa",
"Score": 43.94
},
{
"Country": "Mozambique",
"Region": "Sub-Saharan Africa",
"Score": 35.39
},
{
"Country": "Myanmar",
"Region": "South-eastern Asia",
"Score": 46.14
},
{
"Country": "Namibia",
"Region": "Sub-Saharan Africa",
"Score": 19.72
},
{
"Country": "Nepal",
"Region": "Southern Asia",
"Score": 34.62
},
{
"Country": "Netherlands",
"Region": "Western Europe",
"Score": 9.67
},
{
"Country": "New Zealand",
"Region": "Australia and New Zealand",
"Score": 10.04
},
{
"Country": "Nicaragua",
"Region": "Latin America and the Caribbean",
"Score": 39.98
},
{
"Country": "Niger",
"Region": "Sub-Saharan Africa",
"Score": 28.44
},
{
"Country": "Nigeria",
"Region": "Sub-Saharan Africa",
"Score": 39.69
},
{
"Country": "North Korea",
"Region": "Eastern Asia",
"Score": 81.28
},
{
"Country": "North Macedonia",
"Region": "Southern Europe",
"Score": 31.67
},
{
"Country": "Norway",
"Region": "Northern Europe",
"Score": 6.72
},
{
"Country": "Oman",
"Region": "Western Asia",
"Score": 43.37
},
{
"Country": "Pakistan",
"Region": "Southern Asia",
"Score": 46.86
},
{
"Country": "Palestine",
"Region": "Western Asia",
"Score": 43.18
},
{
"Country": "Panama",
"Region": "Latin America and the Caribbean",
"Score": 29.94
},
{
"Country": "Papua New Guinea",
"Region": "Melanesia",
"Score": 24.88
},
{
"Country": "Paraguay",
"Region": "Latin America and the Caribbean",
"Score": 33.52
},
{
"Country": "Peru",
"Region": "Latin America and the Caribbean",
"Score": 31.71
},
{
"Country": "Philippines",
"Region": "South-eastern Asia",
"Score": 45.64
},
{
"Country": "Poland",
"Region": "Eastern Europe",
"Score": 28.84
},
{
"Country": "Portugal",
"Region": "Southern Europe",
"Score": 10.11
},
{
"Country": "Qatar",
"Region": "Western Asia",
"Score": 42.6
},
{
"Country": "Romania",
"Region": "Eastern Europe",
"Score": 24.91
},
{
"Country": "Russia",
"Region": "Eastern Europe",
"Score": 48.71
},
{
"Country": "Rwanda",
"Region": "Sub-Saharan Africa",
"Score": 50.66
},
{
"Country": "Samoa",
"Region": "Polynesia",
"Score": 19.24
},
{
"Country": "Saudi Arabia",
"Region": "Western Asia",
"Score": 62.73
},
{
"Country": "Senegal",
"Region": "Sub-Saharan Africa",
"Score": 25.22
},
{
"Country": "Serbia",
"Region": "Southern Europe",
"Score": 32.03
},
{
"Country": "Seychelles",
"Region": "Sub-Saharan Africa",
"Score": 25.66
},
{
"Country": "Sierra Leone",
"Region": "Sub-Saharan Africa",
"Score": 29.61
},
{
"Country": "Singapore",
"Region": "South-eastern Asia",
"Score": 55.2
},
{
"Country": "Slovakia",
"Region": "Eastern Europe",
"Score": 23.02
},
{
"Country": "Slovenia",
"Region": "Southern Europe",
"Score": 23.1
},
{
"Country": "Somalia",
"Region": "Sub-Saharan Africa",
"Score": 55.47
},
{
"Country": "South Africa",
"Region": "Sub-Saharan Africa",
"Score": 21.59
},
{
"Country": "South Korea",
"Region": "Eastern Asia",
"Score": 23.43
},
{
"Country": "South Sudan",
"Region": "Sub-Saharan Africa",
"Score": 45.78
},
{
"Country": "Spain",
"Region": "Southern Europe",
"Score": 20.44
},
{
"Country": "Sri Lanka",
"Region": "Southern Asia",
"Score": 42.2
},
{
"Country": "Sudan",
"Region": "Northern Africa",
"Score": 52.93
},
{
"Country": "Suriname",
"Region": "Latin America and the Caribbean",
"Score": 16.95
},
{
"Country": "Sweden",
"Region": "Northern Europe",
"Score": 7.24
},
{
"Country": "Switzerland",
"Region": "Western Europe",
"Score": 10.55
},
{
"Country": "Syria",
"Region": "Western Asia",
"Score": 70.63
},
{
"Country": "Taiwan",
"Region": "Eastern Asia",
"Score": 23.86
},
{
"Country": "Tajikistan",
"Region": "Central Asia",
"Score": 55.52
},
{
"Country": "Tanzania",
"Region": "Sub-Saharan Africa",
"Score": 40.69
},
{
"Country": "Thailand",
"Region": "South-eastern Asia",
"Score": 45.22
},
{
"Country": "Timor",
"Region": "South-eastern Asia",
"Score": 29.11
},
{
"Country": "Togo",
"Region": "Sub-Saharan Africa",
"Score": 29.59
},
{
"Country": "Tonga",
"Region": "Polynesia",
"Score": 24.59
},
{
"Country": "Trinidad and Tobago",
"Region": "Latin America and the Caribbean",
"Score": 21.55
},
{
"Country": "Tunisia",
"Region": "Northern Africa",
"Score": 29.53
},
{
"Country": "Turkey",
"Region": "Western Asia",
"Score": 49.79
},
{
"Country": "Turkmenistan",
"Region": "Central Asia",
"Score": 80.03
},
{
"Country": "Uganda",
"Region": "Sub-Saharan Africa",
"Score": 41.19
},
{
"Country": "Ukraine",
"Region": "Eastern Europe",
"Score": 32.96
},
{
"Country": "United Arab Emirates",
"Region": "Western Asia",
"Score": 43.13
},
{
"Country": "United Kingdom",
"Region": "Northern Europe",
"Score": 21.59
},
{
"Country": "United States",
"Region": "Northern America",
"Score": 23.93
},
{
"Country": "Uruguay",
"Region": "Latin America and the Caribbean",
"Score": 16.38
},
{
"Country": "Uzbekistan",
"Region": "Central Asia",
"Score": 50.74
},
{
"Country": "Venezuela",
"Region": "Latin America and the Caribbean",
"Score": 47.6
},
{
"Country": "Vietnam",
"Region": "South-eastern Asia",
"Score": 78.46
},
{
"Country": "Yemen",
"Region": "Western Asia",
"Score": 62.35
},
{
"Country": "Zambia",
"Region": "Sub-Saharan Africa",
"Score": 38.21
},
{
"Country": "Zimbabwe",
"Region": "Sub-Saharan Africa",
"Score": 43.12
}
]

View file

@ -0,0 +1,42 @@
[
{
"Name": "Francoise Bettencourt Meyers",
"Net worth (in billions)": 74.8
},
{
"Name": "Alice Walton",
"Net worth (in billions)": 65.3
},
{
"Name": "Julia Koch",
"Net worth (in billions)": 60
},
{
"Name": "MacKenzie Scott",
"Net worth (in billions)": 43.6
},
{
"Name": "Jacqueline Mars",
"Net worth (in billions)": 31.7
},
{
"Name": "Gina Rinehart",
"Net worth (in billions)": 30.2
},
{
"Name": "Miriam Adelson",
"Net worth (in billions)": 27.5
},
{
"Name": "Susanne Klatten",
"Net worth (in billions)": 24.3
},
{
"Name": "Iris Fontbona",
"Net worth (in billions)": 22.8
},
{
"Name": "Abigail Johnson",
"Net worth (in billions)": 21.2
}
]

View file

@ -1,10 +1,15 @@
export function filterArray(data, searchText) {
if (!searchText) {
return data;
export function filterArray(data, searchText, filterField, filterValue) {
if (searchText) {
data = data.filter((item) => {
return item.searchStr.includes(searchText.toLowerCase());
});
}
return data.filter((item) => {
return item.searchStr.includes(searchText.toLowerCase());
});
if (filterValue && filterValue) {
data = data.filter((item) => {
return item[filterField] === filterValue;
});
}
return data;
}
export function paginateArray(array, pageSize, pageNumber) {
@ -16,3 +21,21 @@ export function numberWithCommas(n) {
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}
export function uniqueAttr(array, attr) {
return array.map((e) => e[attr]).filter(unique);
}
export function unique(value, index, array) {
return array.indexOf(value) === index;
}
export function isNumeric(value) {
return (
typeof value === 'number' ||
value instanceof Number ||
typeof value === 'bigint' ||
value instanceof BigInt ||
(typeof value === 'string' && !isNaN(value))
);
}