Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feature/1526-grid-key…
Browse files Browse the repository at this point in the history
…board-navigation
  • Loading branch information
Diaan committed Nov 7, 2024
2 parents 9786f15 + dd63dd8 commit b04288e
Show file tree
Hide file tree
Showing 138 changed files with 3,431 additions and 493 deletions.
16 changes: 16 additions & 0 deletions .changeset/clever-ties-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@sl-design-system/editorial-suite': patch
'@sl-design-system/my-digital-book': patch
'@sl-design-system/sanoma-learning': patch
'@sl-design-system/itslearning': patch
'@sl-design-system/bingel-int': patch
'@sl-design-system/bingel-dc': patch
'@sl-design-system/clickedu': patch
'@sl-design-system/magister': patch
'@sl-design-system/kampus': patch
'@sl-design-system/neon': patch
'@sl-design-system/teas': patch
'@sl-design-system/max': patch
---

New paginator tokens, new `ellipsis-down` icon.
8 changes: 8 additions & 0 deletions .changeset/dry-wasps-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@sl-design-system/data-source': patch
'@sl-design-system/shared': patch
'@sl-design-system/form': patch
'@sl-design-system/grid': patch
---

Refactor `getValueByPath` and related functions to properly infer type
5 changes: 5 additions & 0 deletions .changeset/rare-impalas-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sl-design-system/data-source': patch
---

Fix missing data-source reference
5 changes: 5 additions & 0 deletions .changeset/real-steaks-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sl-design-system/locales': patch
---

New translations added necessary for `paginator`, `items counter` and `page size` components.
5 changes: 5 additions & 0 deletions .changeset/smart-bikes-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sl-design-system/paginator': patch
---

Added new `paginator`, `items counter` and `page size` components that can be used together or separately.
7 changes: 7 additions & 0 deletions .changeset/tiny-buses-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@sl-design-system/breadcrumbs': patch
'@sl-design-system/tooltip': patch
'@sl-design-system/select': patch
---

Fix `ShadowRoot.createElement` type definition to properly match `document.createElement`
5 changes: 5 additions & 0 deletions .changeset/twenty-rice-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sl-design-system/data-source': patch
---

Add possibility to use data source with pagination. Added `paginate` method.
5 changes: 4 additions & 1 deletion packages/components/breadcrumbs/src/breadcrumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ declare global {

interface ShadowRoot {
// Workaround for missing type in @open-wc/scoped-elements
createElement(tagName: string): HTMLElement;
createElement<K extends keyof HTMLElementTagNameMap>(
tagName: K,
options?: ElementCreationOptions
): HTMLElementTagNameMap[K];
}
}

Expand Down
51 changes: 48 additions & 3 deletions packages/components/data-source/src/array-data-source.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,60 @@ describe('ArrayDataSource', () => {
});

it('should reset the original order when removing a sort', () => {
ds.setSort('id', 'firstName', 'asc');
ds.setSort('id', 'profession', 'asc');
ds.update();

expect(ds.items.map(({ firstName }) => firstName)).to.deep.equal(['Ann', 'Ann', 'Bob', 'Jane', 'John']);
expect(ds.items.map(({ profession }) => profession)).to.deep.equal([
'Endocrinologist',
'Gastroenterologist',
'Gastroenterologist',
'Nephrologist',
'Ophthalmologist'
]);

ds.removeSort();
ds.update();

expect(ds.items.map(({ firstName }) => firstName)).to.deep.equal(['Ann', 'John', 'Jane', 'Ann', 'Bob']);
expect(ds.items.map(({ profession }) => profession)).to.deep.equal([
'Endocrinologist',
'Nephrologist',
'Ophthalmologist',
'Gastroenterologist',
'Gastroenterologist'
]);
});
});

describe('pagination', () => {
beforeEach(() => {
ds = new ArrayDataSource(people);

ds.paginate(2, 3, people.length);
ds.update();
});

it('should paginate people', () => {
expect(ds.items.map(({ firstName }) => firstName)).to.deep.equal(['Ann', 'Bob']);
});

it('should set the page', () => {
ds.setPage(1);
ds.update();

expect(ds.items.map(({ firstName }) => firstName)).to.deep.equal(['Ann', 'John', 'Jane']);

ds.setPage(2);
ds.update();

expect(ds.items.map(({ firstName }) => firstName)).to.deep.equal(['Ann', 'Bob']);
});

it('should set page size', () => {
ds.setPageSize(2);
ds.update();

expect(ds.page).to.exist;
expect(ds.page!.pageSize).to.equal(2);
});
});
});
27 changes: 21 additions & 6 deletions packages/components/data-source/src/array-data-source.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getStringByPath, getValueByPath } from '@sl-design-system/shared';
import { type PathKeys, getStringByPath, getValueByPath } from '@sl-design-system/shared';
import {
DataSource,
type DataSourceFilterByFunction,
Expand Down Expand Up @@ -37,7 +37,7 @@ export class ArrayDataSource<T = any> extends DataSource<T> {
const filters = Array.from(this.filters.values());

const pathFilters = filters
.filter((f): f is DataSourceFilterByPath => 'path' in f && !!f.path)
.filter((f): f is DataSourceFilterByPath<T> => 'path' in f && !!f.path)
.reduce(
(acc, { path, value }) => {
if (!acc[path]) {
Expand All @@ -52,10 +52,10 @@ export class ArrayDataSource<T = any> extends DataSource<T> {

return acc;
},
{} as Record<string, string[]>
{} as Record<PathKeys<T>, string[]>
);

Object.entries(pathFilters).forEach(([path, values]) => {
for (const [path, values] of Object.entries<string[]>(pathFilters)) {
/**
* Convert the value to a string and trim it, so we can match
* an empty string to:
Expand All @@ -64,8 +64,14 @@ export class ArrayDataSource<T = any> extends DataSource<T> {
* - null
* - undefined
*/
items = items.filter(item => values.includes(getValueByPath(item, path)?.toString()?.trim() ?? ''));
});
items = items.filter(item =>
values.includes(
getValueByPath(item, path as PathKeys<T>)
?.toString()
?.trim() ?? ''
)
);
}

filters
.filter((f): f is DataSourceFilterByFunction<T> => 'filter' in f && !!f.filter)
Expand Down Expand Up @@ -125,6 +131,15 @@ export class ArrayDataSource<T = any> extends DataSource<T> {
});
}

// paginate items
if (this.page) {
const startIndex = (this.page.page - 1) * this.page.pageSize,
endIndex = startIndex + this.page.pageSize;

this.page.totalItems = items.length;
items = items.slice(startIndex, endIndex);
}

this.#filteredItems = items;
this.dispatchEvent(new CustomEvent('sl-update', { detail: { dataSource: this } }));
}
Expand Down
66 changes: 55 additions & 11 deletions packages/components/data-source/src/data-source.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type PathKeys } from '@sl-design-system/shared';

declare global {
interface GlobalEventHandlersEventMap {
'sl-update': DataSourceUpdateEvent;
Expand All @@ -11,12 +13,12 @@ export type DataSourceFilterByFunction<T = unknown> = {
value?: string | string[];
};

export type DataSourceFilterByPath = { path: string; value: string | string[] };
export type DataSourceFilterByPath<T> = { path: PathKeys<T>; value: string | string[] };

export type DataSourceFilter<T> = DataSourceFilterByFunction<T> | DataSourceFilterByPath;
export type DataSourceFilter<T> = DataSourceFilterByFunction<T> | DataSourceFilterByPath<T>;

export type DataSourceGroupBy<T> = {
path: string;
path: PathKeys<T>;
sorter?: DataSourceSortFunction<T>;
direction?: DataSourceSortDirection;
};
Expand All @@ -25,15 +27,17 @@ export type DataSourceSortDirection = 'asc' | 'desc';

export type DataSourceSortFunction<T = unknown> = (a: T, b: T) => number;

export type DataSourceSortByPath = { id?: string; path: string; direction: DataSourceSortDirection };
export type DataSourceSortByPath<T> = { id?: string; path: PathKeys<T>; direction: DataSourceSortDirection };

export type DataSourceSortByFunction<T = unknown> = {
id?: string;
sorter: DataSourceSortFunction<T>;
direction: DataSourceSortDirection;
};

export type DataSourceSort<T> = DataSourceSortByFunction<T> | DataSourceSortByPath;
export type DataSourceSort<T> = DataSourceSortByFunction<T> | DataSourceSortByPath<T>;

export type DataSourcePagination = { page: number; pageSize: number; totalItems: number };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type DataSourceUpdateEvent<T = any> = CustomEvent<{ dataSource: DataSource<T> }>;
Expand All @@ -46,6 +50,9 @@ export abstract class DataSource<T = any> extends EventTarget {
/** Order the items by grouping them on the given attributes. */
#groupBy?: DataSourceGroupBy<T>;

/** Parameters for pagination, contains page number, page size and total items amount. */
#page?: DataSourcePagination;

/**
* The value and path/function to use for sorting. When setting this property,
* it will cause the data to be automatically sorted.
Expand All @@ -60,6 +67,10 @@ export abstract class DataSource<T = any> extends EventTarget {
return this.#groupBy;
}

get page(): DataSourcePagination | undefined {
return this.#page;
}

get sort(): DataSourceSort<T> | undefined {
return this.#sort;
}
Expand All @@ -70,16 +81,16 @@ export abstract class DataSource<T = any> extends EventTarget {
/** Total number of items in this data source. */
abstract readonly size: number;

/** Updates the list of items using filter and sorting if available. */
/** Updates the list of items using filter, sorting and pagination if available. */
abstract update(): void;

addFilter<U extends string | DataSourceFilterFunction<T>>(
addFilter<U extends PathKeys<T> | DataSourceFilterFunction<T>>(
id: string,
pathOrFilter: U,
value?: string | string[]
): void {
if (typeof pathOrFilter === 'string') {
this.#filters.set(id, { path: pathOrFilter, value: value ?? '' });
this.#filters.set(id, { path: pathOrFilter as PathKeys<T>, value: value ?? '' });
} else {
this.#filters.set(id, { filter: pathOrFilter, value });
}
Expand All @@ -99,7 +110,7 @@ export abstract class DataSource<T = any> extends EventTarget {
* @param sorter Optional sorter function.
* @param direction Optional sort direction.
*/
setGroupBy(path: string, sorter?: DataSourceSortFunction<T>, direction?: DataSourceSortDirection): void {
setGroupBy(path: PathKeys<T>, sorter?: DataSourceSortFunction<T>, direction?: DataSourceSortDirection): void {
this.#groupBy = { path, sorter, direction };
}

Expand All @@ -110,20 +121,28 @@ export abstract class DataSource<T = any> extends EventTarget {
this.#groupBy = undefined;
}

setSort<U extends string | DataSourceSortFunction<T>>(
setSort<U extends PathKeys<T> | DataSourceSortFunction<T>>(
id: string,
pathOrSorter: U,
direction: DataSourceSortDirection
): void {
if (typeof pathOrSorter === 'string') {
this.#sort = { id, path: pathOrSorter, direction };
this.#sort = { id, path: pathOrSorter as PathKeys<T>, direction };
} else {
this.#sort = { id, sorter: pathOrSorter, direction };
}

if (this.#page) {
this.setPage(0);
}
}

removeSort(): void {
this.#sort = undefined;

if (this.#page) {
this.setPage(0);
}
}

/**
Expand All @@ -147,4 +166,29 @@ export abstract class DataSource<T = any> extends EventTarget {

this.update();
}

setPage(page: number): void {
if (this.#page) {
this.paginate(page, this.#page.pageSize, this.#page.totalItems);
}
}

setPageSize(pageSize: number): void {
if (this.#page) {
this.paginate(0, pageSize, this.#page.totalItems);
}
}

setTotalItems(totalItems: number): void {
if (this.#page) {
this.paginate(this.#page.page, this.#page.pageSize, totalItems);
}
}

/**
* Use to get the paginated data for usage with the sl-paginator component.
* */
paginate(page: number, pageSize: number, totalItems: number): void {
this.#page = { page: page, pageSize: pageSize, totalItems: totalItems };
}
}
5 changes: 4 additions & 1 deletion packages/components/form/src/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ declare global {

interface ShadowRoot {
// Workaround for missing type in @open-wc/scoped-elements
createElement(tagName: string): HTMLElement;
createElement<K extends keyof HTMLElementTagNameMap>(
tagName: K,
options?: ElementCreationOptions
): HTMLElementTagNameMap[K];
}
}

Expand Down
Loading

0 comments on commit b04288e

Please sign in to comment.