diff --git a/package-lock.json b/package-lock.json
index 75fdbd668..0f5b965be 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,9 +8,9 @@
"name": "code-sandbox",
"version": "0.0.0",
"dependencies": {
- "@abgov/react-components": "6.2.1",
- "@abgov/ui-components-common": "1.2.1",
- "@abgov/web-components": "1.32.1",
+ "@abgov/react-components": "6.2.2-alpha.4",
+ "@abgov/ui-components-common": "1.2.2-alpha.2",
+ "@abgov/web-components": "1.33.0-alpha.2",
"@faker-js/faker": "^8.3.1",
"highlight.js": "^11.8.0",
"js-cookie": "^3.0.5",
@@ -67,9 +67,10 @@
}
},
"node_modules/@abgov/react-components": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.2.1.tgz",
- "integrity": "sha512-CQ2Grpv5R/QR2UifwGP9VvAGDFxCwCpUlfSkcOKMXFUvwT+IQ6FbHPjgKkGViF2Td813/m7Qz7woo8DvoIIQfQ==",
+ "version": "6.2.2-alpha.4",
+ "resolved": "https://registry.npmjs.org/@abgov/react-components/-/react-components-6.2.2-alpha.4.tgz",
+ "integrity": "sha512-3Du7aDHKryBIeJx+uOmzZxLaqeHEXrmJCK8ErE4h8qZ40fjpp0aOp01WcAua8zMG2jxqOxlqSJGZ85jluFB5Og==",
+ "license": "Apache-2.0",
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0",
"react": "^17.0.0 || ^18.0.0",
@@ -77,14 +78,16 @@
}
},
"node_modules/@abgov/ui-components-common": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@abgov/ui-components-common/-/ui-components-common-1.2.1.tgz",
- "integrity": "sha512-RIvetCp7das7VmxiOqudQ2CGFIsWlt9poL65R03SOhpgHPco5PqDNYLF+QiFlHu1Aeq9YMhIk5miHjpNBUWLSQ=="
+ "version": "1.2.2-alpha.2",
+ "resolved": "https://registry.npmjs.org/@abgov/ui-components-common/-/ui-components-common-1.2.2-alpha.2.tgz",
+ "integrity": "sha512-bknk+IfzGAy+v13khWyUhXN/nIoYYhQ+Yg2C7T5lWy2i53DBUSP/Yq9h1RR2DGwpSi5406QMpq8o8xlYVR9G0g==",
+ "license": "Apache-2.0"
},
"node_modules/@abgov/web-components": {
- "version": "1.32.1",
- "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.32.1.tgz",
- "integrity": "sha512-Ezj17LYk5RgnNN3TVazuvlPjyOSfo4ArtpOE2VrnC0XJ0wIBKfmtcXwhdFATtLCtR/ILix829QUU0kxXzkRcSA==",
+ "version": "1.33.0-alpha.2",
+ "resolved": "https://registry.npmjs.org/@abgov/web-components/-/web-components-1.33.0-alpha.2.tgz",
+ "integrity": "sha512-h9wi1of2+wyQx5HYKrkFNGiG5CP+V0w0WRbWAT35nFVlM3V9Bwg8vaw2GVEYDlDVrR817lJl+1a0Ehi3jEU+oA==",
+ "license": "Apache-2.0",
"peerDependencies": {
"@sveltejs/vite-plugin-svelte": "3.x",
"glob": "10.x",
diff --git a/package.json b/package.json
index 664fd95f5..17ba79bbe 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,9 @@
"prettier": "npx prettier . --write"
},
"dependencies": {
- "@abgov/react-components": "6.2.1",
- "@abgov/ui-components-common": "1.2.1",
- "@abgov/web-components": "1.32.1",
+ "@abgov/react-components": "6.2.2-alpha.4",
+ "@abgov/ui-components-common": "1.2.2-alpha.2",
+ "@abgov/web-components": "1.33.0-alpha.2",
"@faker-js/faker": "^8.3.1",
"highlight.js": "^11.8.0",
"js-cookie": "^3.0.5",
diff --git a/src/examples/filter-chip/FilterChipExamples.tsx b/src/examples/filter-chip/FilterChipExamples.tsx
index 488c9a5ca..d04771267 100644
--- a/src/examples/filter-chip/FilterChipExamples.tsx
+++ b/src/examples/filter-chip/FilterChipExamples.tsx
@@ -1,3 +1,4 @@
+import { TableWithGlobalFiltersExample } from "@examples/filter-chip/TableWithGlobalFiltersExample.tsx";
import { FilterChipDeleteEventExample } from "@examples/filter-chip/FilterChipDeleteEventExample.tsx";
import { FilterChipInteractiveExample } from "@examples/filter-chip/FilterChipInteractiveExample.tsx";
import { FilterChipTypedChipExample } from "@examples/filter-chip/FilterChipTypedChipExample.tsx";
@@ -14,8 +15,11 @@ export const FilterChipExamples = () => {
Interactive Example
- Typed Chips Example
+ Create a chip through typing
+
+ Filter data in a table
+
>
)
}
diff --git a/src/examples/filter-chip/FilterChipTypedChipExample.tsx b/src/examples/filter-chip/FilterChipTypedChipExample.tsx
index 2ae8f0f6c..921ec650d 100644
--- a/src/examples/filter-chip/FilterChipTypedChipExample.tsx
+++ b/src/examples/filter-chip/FilterChipTypedChipExample.tsx
@@ -1,68 +1,62 @@
-import { GoabContainer, GoabFilterChip, GoabInput } from "@abgov/react-components";
+import { GoabContainer, GoabFilterChip, GoabFormItem, GoabInput, GoabInputOnChangeDetail, GoabInputOnKeyPressDetail } from "@abgov/react-components";
import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx";
import { useContext, useState } from "react";
import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx";
export const FilterChipTypedChipExample = () => {
const {version} = useContext(LanguageVersionContext);
- const [typedChips, setTypedChips] = useState([
- "Typed Chip 1",
- "Typed Chip 2",
- "Typed Chip 3",
- ]);
-
+ const [typedChips, setTypedChips] = useState([]);
const [inputValue, setInputValue] = useState("");
- const handleInputChange = (_name: string, value: string) => {
- setInputValue(value);
- };
- const handleInputKeyDown = (_name: string, value: string, key: string) => {
- if (key === "Enter" && value.trim() !== "") {
- setTypedChips(prevChips => [...prevChips, value.trim()]);
- setTimeout(() => {
- setInputValue("");
- }, 0);
- } else if (key === "Backspace" && value === "" && typedChips.length > 0) {
- setTypedChips(prevChips => prevChips.slice(0, -1));
- }
- };
+
+ const handleInputChange = (detail: GoabInputOnChangeDetail) => {
+ const newValue = detail.value.trim();
+ setInputValue(newValue);
+ };
+
+ const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
+ const newValue = detail.value.trim();
+ if (detail.key === "Enter" && newValue !== "") {
+ setTypedChips(prevChips => [...prevChips, newValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ } else if (detail.key === "Backspace" && newValue === "" && typedChips.length > 0) {
+ setTypedChips(prevChips => prevChips.slice(0, -1));
+ }
+ };
const removeTypedChip = (chip: string) => {
setTypedChips(prevChips => prevChips.filter(c => c !== chip));
};
+
return (
+ // NOTE: Input onKeyPress functionality breaks when wrapped in Sandbox component
+ //
<>
-
- handleInputChange(detail.name, detail.value)}
- onKeyPress={detail => handleInputKeyDown(detail.name, detail.value, detail.key)}
- width="30ch"
- mr="s"
- />
- {typedChips.map((chip, index) => (
- removeTypedChip(chip)}
- mr="s"
- mt="s"
- mb="s"
- />
- ))}
-
-
+
+
+
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+
+
+
{version === "old" && (
<>
{
tags="angular"
allowCopy={true}
code={`
+export class FilterChipComponent {
+ typedChips: string[] = [];
+ inputValue = "";
- import { Component } from "@angular/core";
-
- @Component({
- selector: "abgov-chip",
- templateUrl: "./filter-chip.component.html",
- styleUrl: "./filter-chip.component.css",
- })
- export class FilterChipComponent {
-
- typedChips: string[] = ["Typed Chip 1", "Typed Chip 2", "Typed Chip 3"];
- inputValue = "";
+ handleInputChange(event: Event): void {
+ const newValue = (event.target as HTMLInputElement).value.trim();
+ this.inputValue = newValue;
+ }
+ handleInputKeyPress(event: KeyboardEvent): void {
+ const newValue = (event.target as HTMLInputElement).value.trim();
+ if (event.key === "Enter" && newValue !== "") {
+ this.addChip();
+ } else if (!this.inputValue && this.typedChips.length > 0 && event.key === "Backspace") {
+ this.typedChips.pop();
+ }
+ }
- onInput(event: Event): void {
- this.inputValue = (event.target as HTMLInputElement).value;
- }
-
- addChip(): void {
- if (this.inputValue.trim()) {
- this.typedChips.push(this.inputValue.trim());
- this.inputValue = "";
- }
- }
-
- removeTypedChip(chip: string): void {
- this.typedChips = this.typedChips.filter((c) => c !== chip);
- }
+ addChip(): void {
+ if (this.inputValue.trim()) {
+ this.typedChips.push(this.inputValue.trim());
+ this.inputValue = "";
+ }
+ }
- handleBackspace(event: KeyboardEvent): void {
- if (!this.inputValue && this.typedChips.length > 0 && event.key === "Backspace") {
- this.typedChips.pop();
- event.preventDefault();
- }
- }
- }
-
+ removeTypedChip(chip: string): void {
+ this.typedChips = this.typedChips.filter((c) => c !== chip);
+ }
+}
`}
/>
{
tags="angular"
allowCopy={true}
code={`
-
-
-
-
+
+
+
+
+ 0">
+
+
+
`}
/>
>
@@ -144,151 +132,193 @@ export const FilterChipTypedChipExample = () => {
tags="angular"
allowCopy={true}
code={`
- export class FilterChipComponent {
- typedChips: string[] = ["Typed Chip 1", "Typed Chip 2", "Typed Chip 3"];
- inputValue = "";
+export class FilterChipComponent {
+ typedChips: string[] = [];
+ inputValue = "";
- onInput(detail: GoabInputOnChangeDetail): void {
- this.inputValue = detail.value;
- }
+ handleInputChange(detail: GoabInputOnChangeDetail): void {
+ const newValue = detail.value.trim();
+ this.inputValue = newValue;
+ }
- addChip(): void {
- if (this.inputValue.trim()) {
- this.typedChips.push(this.inputValue.trim());
- this.inputValue = "";
- }
- }
+ handleInputKeyPress(detail: GoabInputOnKeyPressDetail): void {
+ const newValue = detail.value.trim();
+ if (detail.key === "Enter" && newValue !== "") {
+ this.addChip();
+ } else if (!this.inputValue && this.typedChips.length > 0 && detail.key === "Backspace") {
+ this.typedChips.pop();
+ }
+ }
- removeTypedChip(chip: string): void {
- this.typedChips = this.typedChips.filter((c) => c !== chip);
- }
+ addChip(): void {
+ if (this.inputValue.trim()) {
+ this.typedChips.push(this.inputValue.trim());
+ this.inputValue = "";
+ }
+ }
- handleBackspace(event: KeyboardEvent): void {
- if (!this.inputValue && this.typedChips.length > 0 && event.key === "Backspace") {
- this.typedChips.pop();
- event.preventDefault();
- }
- }
- `}
+ removeTypedChip(chip: string): void {
+ this.typedChips = this.typedChips.filter((c) => c !== chip);
+ }
+}
+ `}
/>
Typed Chip
-
-
-
-
- `}
+
+
+
+
+ 0">
+
+
+
+ `}
/>
>
)}
- ([
- "Typed Chip 1",
- "Typed Chip 2",
- "Typed Chip 3",
- ]);
- const [inputValue, setInputValue] = useState("");
- const handleInputChange = (name: string, value: string) => {
- setInputValue(value);
- };
+ {version === "old" && (
+ <>
+ ([]);
+ const [inputValue, setInputValue] = useState("");
+
+ const handleInputChange = (_name: string, value: string) => {
+ const newValue = value.trim();
+ setInputValue(newValue);
+ };
- const handleInputKeyDown = (name: string,
- value: string,
- key: string) => {
- if (key === "Enter" && value.trim() !== "") {
- setTypedChips((prevChips) => [...prevChips, value.trim()]);
- setTimeout(() => {
- setInputValue("");
- }, 0);
- } else if (key === "Backspace"
- && value === ""
- && typedChips.length > 0) {
- setTypedChips((prevChips) => prevChips.slice(0, -1));
- }
- };
+ const handleInputKeyPress = (_name: string, value: string, key: string) => {
+ const newValue = value.trim();
+ if (key === "Enter" && newValue !== "") {
+ setTypedChips(prevChips => [...prevChips, newValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ } else if (key === "Backspace" && newValue === "" && typedChips.length > 0) {
+ setTypedChips(prevChips => prevChips.slice(0, -1));
+ }
+ };
- const removeTypedChip = (chip: string) => {
- setTypedChips((prevChips) => prevChips.filter((c) => c !== chip));
- };
- `}
- />
- {version === "old" && (
-
- {typedChips.map((chip, index) => (
- removeTypedChip(chip)}
- mr="s"
- mt="s"
- mb="s"/>
- ))}
- `}
+ const removeTypedChip = (chip: string) => {
+ setTypedChips(prevChips => prevChips.filter(c => c !== chip));
+ };
+ `}
+ />
+
+
+
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+
+ `}
+ />
+ >
)}
+
{version === "new" && (
- handleInputChange(detail.name, detail.value)}
- onKeyPress={(detail) => handleInputKeyDown(detail.name, detail.value, detail.key)}
- width="30ch"
- mr="s"
- />
- {typedChips.map((chip, index) => (
- removeTypedChip(chip)}
- mr="s"
- mt="s"
- mb="s"/>
- ))}
- `}
+ <>
+ ([]);
+ const [inputValue, setInputValue] = useState("");
+
+ const handleInputChange = (detail: GoabInputOnChangeDetail) => {
+ const newValue = detail.value.trim();
+ setInputValue(newValue);
+ };
+
+ const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
+ const newValue = detail.value.trim();
+ if (detail.key === "Enter" && newValue !== "") {
+ setTypedChips(prevChips => [...prevChips, newValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ } else if (detail.key === "Backspace" && newValue === "" && typedChips.length > 0) {
+ setTypedChips(prevChips => prevChips.slice(0, -1));
+ }
+ };
+
+ const removeTypedChip = (chip: string) => {
+ setTypedChips(prevChips => prevChips.filter(c => c !== chip));
+ };
+ `}
+ />
+
+
+
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+
+ `}
+ />
+ >
)}
>
+ //
);
}
diff --git a/src/examples/filter-chip/TableWithGlobalFiltersExample.tsx b/src/examples/filter-chip/TableWithGlobalFiltersExample.tsx
new file mode 100644
index 000000000..d469f752f
--- /dev/null
+++ b/src/examples/filter-chip/TableWithGlobalFiltersExample.tsx
@@ -0,0 +1,914 @@
+import { useCallback, useContext, useEffect, useMemo, useState } from "react";
+import {
+ GoabBadge,
+ GoabBlock,
+ GoabButton,
+ GoabContainer,
+ GoabFilterChip,
+ GoabFormItem,
+ GoabInput,
+ GoabTable,
+ GoabText,
+} from "@abgov/react-components";
+import type {
+ GoabBadgeType,
+ GoabInputOnChangeDetail,
+ GoabInputOnKeyPressDetail,
+} from "@abgov/react-components";
+import { LanguageVersionContext } from "@contexts/LanguageVersionContext.tsx";
+import { CodeSnippet } from "@components/code-snippet/CodeSnippet.tsx";
+
+export const TableWithGlobalFiltersExample = () => {
+ const { version } = useContext(LanguageVersionContext);
+
+ const [typedChips, setTypedChips] = useState([]);
+ const [inputValue, setInputValue] = useState("");
+ const [inputError, setInputError] = useState("");
+ const errorEmpty = "Empty filter";
+ const errorDuplicate = "Enter a unique filter";
+ const data = useMemo(
+ () => [
+ {
+ status: { type: "information" as GoabBadgeType, text: "In progress" },
+ name: "Ivan Schmidt",
+ id: "7838576954",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Luz Lakin",
+ id: "8576953364",
+ },
+ {
+ status: { type: "information" as GoabBadgeType, text: "In progress" },
+ name: "Keith McGlynn",
+ id: "9846041345",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Melody Frami",
+ id: "7385256175",
+ },
+ {
+ status: { type: "important" as GoabBadgeType, text: "Updated" },
+ name: "Frederick Skiles",
+ id: "5807570418",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Dana Pfannerstill",
+ id: "5736306857",
+ },
+ ],
+ []
+ );
+ const [dataFiltered, setDataFiltered] = useState(data);
+
+ const handleInputChange = (detail: GoabInputOnChangeDetail) => {
+ const newValue = detail.value.trim();
+ setInputValue(newValue);
+ };
+
+ const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
+ if (detail.key === "Enter") {
+ applyFilter();
+ }
+ };
+
+ const applyFilter = () => {
+ if (inputValue === "") {
+ setInputError(errorEmpty);
+ return;
+ }
+ if (typedChips.length > 0 && typedChips.includes(inputValue)) {
+ setInputError(errorDuplicate);
+ return;
+ }
+ setTypedChips([...typedChips, inputValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ setInputError("");
+ };
+
+ const removeTypedChip = (chip: string) => {
+ setTypedChips(typedChips.filter(c => c !== chip));
+ setInputError("");
+ };
+
+ const checkNested = useCallback((obj: object, chip: string): boolean => {
+ return Object.values(obj).some(value =>
+ typeof value === "object" && value !== null
+ ? checkNested(value, chip)
+ : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase())
+ );
+ }, []);
+
+ const getFilteredData = useCallback(
+ (typedChips: string[]) => {
+ if (typedChips.length === 0) {
+ return data;
+ }
+ const filteredData = data.filter((item: object) =>
+ typedChips.every(chip => checkNested(item, chip))
+ );
+
+ return filteredData;
+ },
+ [checkNested, data]
+ );
+
+ useEffect(() => {
+ setDataFiltered(getFilteredData(typedChips));
+ }, [getFilteredData, typedChips]);
+
+ return (
+ // NOTE: Input onKeyPress functionality breaks when wrapped in Sandbox component
+ //
+ <>
+
+
+
+
+
+ Filter
+
+
+
+
+ {typedChips.length > 0 && (
+
+
+ Filter:
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+ setTypedChips([])}>
+ Clear all
+
+
+ )}
+
+
+
+
+ | Status |
+ Name |
+ ID Number |
+
+
+
+ {dataFiltered.map(item => (
+
+ |
+
+ |
+ {item.name} |
+ {item.id} |
+
+ ))}
+
+
+
+ {dataFiltered.length === 0 && data.length > 0 && (
+
+ No results found
+
+ )}
+
+
+ {version === "old" && (
+ <>
+ c !== chip);
+ this.dataFiltered = this.getFilteredData(this.typedChips);
+ this.inputError = "";
+ }
+
+ removeAllTypedChips() {
+ this.typedChips = [];
+ this.dataFiltered = this.getFilteredData(this.typedChips);
+ this.inputError = "";
+ }
+
+ getFilteredData(typedChips: string[]) {
+ if (typedChips.length === 0) {
+ return this.data;
+ }
+ const filteredData = this.data.filter((item) =>
+ typedChips.every((chip) => this.checkNested(item, chip)),
+ );
+ return filteredData;
+ }
+
+ checkNested(obj: object, chip: string): boolean {
+ return Object.values(obj).some((value) =>
+ typeof value === "object" && value !== null
+ ? this.checkNested(value, chip)
+ : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()),
+ );
+ }
+}
+ `}
+ />
+
+
+
+
+
+ Filter
+
+
+
+
+ 0">
+
+ Filter:
+
+
+
+ Clear all
+
+
+
+
+
+
+ | Status |
+ Name |
+ ID Number |
+
+
+
+
+ |
+
+ |
+ {{ item.name }} |
+ {{ item.id }} |
+
+
+
+
+ 0">
+ No results found
+
+ `}
+ />
+ ([]);
+ const [inputValue, setInputValue] = useState("");
+ const [inputError, setInputError] = useState("");
+ const errorEmpty = "Empty filter";
+ const errorDuplicate = "Enter a unique filter";
+ const data = useMemo(
+ () => [
+ {
+ status: { type: "information" as GoABadgeType, text: "In progress" },
+ name: "Ivan Schmidt",
+ id: "7838576954",
+ },
+ {
+ status: { type: "success" as GoABadgeType, text: "Completed" },
+ name: "Luz Lakin",
+ id: "8576953364",
+ },
+ {
+ status: { type: "information" as GoABadgeType, text: "In progress" },
+ name: "Keith McGlynn",
+ id: "9846041345",
+ },
+ {
+ status: { type: "success" as GoABadgeType, text: "Completed" },
+ name: "Melody Frami",
+ id: "7385256175",
+ },
+ {
+ status: { type: "important" as GoABadgeType, text: "Updated" },
+ name: "Frederick Skiles",
+ id: "5807570418",
+ },
+ {
+ status: { type: "success" as GoABadgeType, text: "Completed" },
+ name: "Dana Pfannerstill",
+ id: "5736306857",
+ },
+ ],
+ [],
+ );
+ const [dataFiltered, setDataFiltered] = useState(data);
+
+ const handleInputChange = (_name: string, value: string) => {
+ const newValue = value.trim();
+ setInputValue(newValue);
+ };
+
+ const handleInputKeyPress = (_name: string, _value: string, key: string) => {
+ if (key === "Enter") {
+ applyFilter();
+ }
+ };
+
+ const applyFilter = () => {
+ if (inputValue === "") {
+ setInputError(errorEmpty);
+ return;
+ }
+ if (typedChips.length > 0 && typedChips.includes(inputValue)) {
+ setInputError(errorDuplicate);
+ return;
+ }
+ setTypedChips([...typedChips, inputValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ setInputError("");
+ };
+
+ const removeTypedChip = (chip: string) => {
+ setTypedChips(typedChips.filter((c) => c !== chip));
+ setInputError("");
+ };
+
+ const checkNested = useCallback((obj: object, chip: string): boolean => {
+ return Object.values(obj).some((value) =>
+ typeof value === "object" && value !== null
+ ? checkNested(value, chip)
+ : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()),
+ );
+ }, []);
+
+ const getFilteredData = useCallback(
+ (typedChips: string[]) => {
+ if (typedChips.length === 0) {
+ return data;
+ }
+ const filteredData = data.filter((item: object) =>
+ typedChips.every((chip) => checkNested(item, chip)),
+ );
+
+ return filteredData;
+ },
+ [checkNested, data],
+ );
+
+ useEffect(() => {
+ setDataFiltered(getFilteredData(typedChips));
+ }, [getFilteredData, typedChips]);
+ `}
+ />
+
+
+
+
+
+
+ Filter
+
+
+
+
+ {typedChips.length > 0 && (
+
+
+ Filter:
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+ setTypedChips([])}
+ >
+ Clear all
+
+
+ )}
+
+
+
+
+ | Status |
+ Name |
+ ID Number |
+
+
+
+ {dataFiltered.map((item) => (
+
+ |
+
+ |
+ {item.name} |
+ {item.id} |
+
+ ))}
+
+
+
+ {dataFiltered.length === 0 && data.length > 0 && (
+ No results found
+ )}
+ >
+ `}
+ />
+ >
+ )}
+
+ {version === "new" && (
+ <>
+ c !== chip);
+ this.dataFiltered = this.getFilteredData(this.typedChips);
+ this.inputError = "";
+ }
+
+ removeAllTypedChips() {
+ this.typedChips = [];
+ this.dataFiltered = this.getFilteredData(this.typedChips);
+ this.inputError = "";
+ }
+
+ getFilteredData(typedChips: string[]) {
+ if (typedChips.length === 0) {
+ return this.data;
+ }
+ const filteredData = this.data.filter((item) =>
+ typedChips.every((chip) => this.checkNested(item, chip)),
+ );
+ return filteredData;
+ }
+
+ checkNested(obj: object, chip: string): boolean {
+ return Object.values(obj).some((value) =>
+ typeof value === "object" && value !== null
+ ? this.checkNested(value, chip)
+ : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase()),
+ );
+ }
+}
+ `}
+ />
+
+
+
+
+
+ Filter
+
+
+
+
+ 0">
+
+ Filter:
+
+
+
+ Clear all
+
+
+
+
+
+
+ | Status |
+ Name |
+ ID Number |
+
+
+
+
+ |
+
+ |
+ {{ item.name }} |
+ {{ item.id }} |
+
+
+
+
+ 0">
+ No results found
+
+ `}
+ />
+ ([]);
+ const [inputValue, setInputValue] = useState("");
+ const [inputError, setInputError] = useState("");
+ const errorEmpty = "Empty filter";
+ const errorDuplicate = "Enter a unique filter";
+ const data = useMemo(
+ () => [
+ {
+ status: { type: "information" as GoabBadgeType, text: "In progress" },
+ name: "Ivan Schmidt",
+ id: "7838576954",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Luz Lakin",
+ id: "8576953364",
+ },
+ {
+ status: { type: "information" as GoabBadgeType, text: "In progress" },
+ name: "Keith McGlynn",
+ id: "9846041345",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Melody Frami",
+ id: "7385256175",
+ },
+ {
+ status: { type: "important" as GoabBadgeType, text: "Updated" },
+ name: "Frederick Skiles",
+ id: "5807570418",
+ },
+ {
+ status: { type: "success" as GoabBadgeType, text: "Completed" },
+ name: "Dana Pfannerstill",
+ id: "5736306857",
+ },
+ ],
+ []
+ );
+ const [dataFiltered, setDataFiltered] = useState(data);
+
+ const handleInputChange = (detail: GoabInputOnChangeDetail) => {
+ const newValue = detail.value.trim();
+ setInputValue(newValue);
+ };
+
+ const handleInputKeyPress = (detail: GoabInputOnKeyPressDetail) => {
+ if (detail.key === "Enter") {
+ applyFilter();
+ }
+ };
+
+ const applyFilter = () => {
+ if (inputValue === "") {
+ setInputError(errorEmpty);
+ return;
+ }
+ if (typedChips.length > 0 && typedChips.includes(inputValue)) {
+ setInputError(errorDuplicate);
+ return;
+ }
+ setTypedChips([...typedChips, inputValue]);
+ setTimeout(() => {
+ setInputValue("");
+ }, 0);
+ setInputError("");
+ };
+
+ const removeTypedChip = (chip: string) => {
+ setTypedChips(typedChips.filter(c => c !== chip));
+ setInputError("");
+ };
+
+ const checkNested = useCallback((obj: object, chip: string): boolean => {
+ return Object.values(obj).some(value =>
+ typeof value === "object" && value !== null
+ ? checkNested(value, chip)
+ : typeof value === "string" && value.toLowerCase().includes(chip.toLowerCase())
+ );
+ }, []);
+
+ const getFilteredData = useCallback(
+ (typedChips: string[]) => {
+ if (typedChips.length === 0) {
+ return data;
+ }
+ const filteredData = data.filter((item: object) =>
+ typedChips.every(chip => checkNested(item, chip))
+ );
+
+ return filteredData;
+ },
+ [checkNested, data]
+ );
+
+ useEffect(() => {
+ setDataFiltered(getFilteredData(typedChips));
+ }, [getFilteredData, typedChips]);
+ `}
+ />
+
+
+
+
+
+
+ Filter
+
+
+
+
+ {typedChips.length > 0 && (
+
+
+ Filter:
+
+ {typedChips.length > 0 &&
+ typedChips.map((typedChip, index) => (
+ removeTypedChip(typedChip)}
+ />
+ ))}
+ setTypedChips([])}>
+ Clear all
+
+
+ )}
+
+
+
+
+ | Status |
+ Name |
+ ID Number |
+
+
+
+ {dataFiltered.map(item => (
+
+ |
+
+ |
+ {item.name} |
+ {item.id} |
+
+ ))}
+
+
+
+ {dataFiltered.length === 0 && data.length > 0 && (
+ No results found
+ )}
+ >
+ `}
+ />
+ >
+ )}
+ >
+ //
+ );
+};
diff --git a/src/routes/components/Badge.tsx b/src/routes/components/Badge.tsx
index 5e5ccbaa4..39469c39a 100644
--- a/src/routes/components/Badge.tsx
+++ b/src/routes/components/Badge.tsx
@@ -18,14 +18,17 @@ const description =
const category = Category.FEEDBACK_AND_ALERTS;
const relatedComponents = [
{
- link: "/components/filter-chip", name: "Filter Chip"
+ link: "/components/filter-chip",
+ name: "Filter chip",
},
{
- link: "/components/icons", name: "Icons"
+ link: "/components/icons",
+ name: "Icons",
},
{
- link: "/components/table", name: "Table"
- }
+ link: "/components/table",
+ name: "Table",
+ },
];
type ComponentPropsType = GoabBadgeProps;
@@ -152,7 +155,7 @@ export default function BadgePage() {
type: "Spacing(none | 3xs | 2xs | xs | s | m | l | xl | 2xl | 3xl | 4xl)",
description: "Apply margin to the top, right, bottom, and/or left of the component.",
},
- ]
+ ];
function onSandboxChange(badgeBindings: ComponentBinding[], props: Record) {
setBadgeBindings(badgeBindings);
@@ -161,16 +164,25 @@ export default function BadgePage() {
return (
<>
-
+
-
- Component
+
+ Component
+
-
+
@@ -180,8 +192,7 @@ export default function BadgePage() {
Design guidelines
>
- }
- >
+ }>
>
diff --git a/src/routes/components/FilterChip.tsx b/src/routes/components/FilterChip.tsx
index 924a9fb20..8ae1920b4 100644
--- a/src/routes/components/FilterChip.tsx
+++ b/src/routes/components/FilterChip.tsx
@@ -1,9 +1,10 @@
import { Category, ComponentHeader } from "@components/component-header/ComponentHeader.tsx";
import {
GoabBadge,
- GoabFilterChip, GoabFilterChipProps,
+ GoabFilterChip,
+ GoabFilterChipProps,
GoabTab,
- GoabTabs
+ GoabTabs,
} from "@abgov/react-components";
import { ComponentBinding, Sandbox } from "@components/sandbox";
import { useState } from "react";
@@ -15,7 +16,7 @@ import { ComponentContent } from "@components/component-content/ComponentContent
import {
LegacyTestIdProperties,
MarginProperty,
- TestIdProperty
+ TestIdProperty,
} from "@components/component-properties/common-properties.ts";
import { FilterChipExamples } from "@examples/filter-chip/FilterChipExamples.tsx";
@@ -26,6 +27,7 @@ const category = Category.FEEDBACK_AND_ALERTS;
const relatedComponents = [
{ link: "/components/badge", name: "Badge" },
{ link: "/components/popover", name: "Popover" },
+ { link: "/components/input", name: "Input" },
{ link: "/components/table", name: "Table" },
];
type ComponentPropsType = GoabFilterChipProps;
@@ -130,7 +132,7 @@ export default function FilterChipPage() {
oldProperties={oldComponentProperties}
/>
-
+
& {
+type ComponentPropsType = Omit & {
onSort?: (sortBy: string, sortDir: number) => void;
};
export default function TablePage() {
- const {version} = useContext(LanguageVersionContext);
+ const { version } = useContext(LanguageVersionContext);
const [tableProps, setTableProps] = useState({
- width: "100%"
+ width: "100%",
});
const [tableBindings, setTableBindings] = useState([
{
@@ -83,6 +84,7 @@ export default function TablePage() {
description: "Apply margin to the top, right, bottom, and/or left of the component.",
},
];
+
const componentProperties: ComponentProperty[] = [
{
name: "width",
@@ -162,24 +164,23 @@ export default function TablePage() {
relatedComponents={[
{ link: "/components/button", name: "Button" },
{ link: "/components/dropdown", name: "Dropdown" },
+ { link: "/components/filter-chip", name: "Filter chip" },
{ link: "/components/pagination", name: "Pagination" },
{ link: "/components/tabs", name: "Tabs" },
]}
/>
-
{
if (tableProps.onSort) {
tableProps.onSort(detail.sortBy, detail.sortDir);
}
- }}
- >
+ }}>
| Status |
@@ -233,8 +234,13 @@ export default function TablePage() {
-
- Examples
+
+
+ Examples
+
Sortable columns
@@ -602,6 +608,9 @@ export default function TablePage() {
+
+ Filter data in a table
+