@scheels-softdev/kendoreact-generics 2.4.9 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/package.json +1 -1
  2. package/src/FilterCellDropdown.tsx +50 -0
  3. package/src/GenericDropdown.tsx +170 -0
  4. package/src/MultiSelectDropdown.tsx +111 -0
  5. package/{PropTypes.d.ts → src/PropTypes.ts} +1 -0
  6. package/src/Toolbar.tsx +27 -0
  7. package/src/Utility.ts +19 -0
  8. package/src/commandCell/CommandCellCheckbox.tsx +28 -0
  9. package/{commandCell/CommandCellDDWithoutId.d.ts → src/commandCell/CommandCellDDWithoutId.tsx} +16 -2
  10. package/src/commandCell/CommandCellDate.tsx +36 -0
  11. package/src/commandCell/CommandCellDropdown.tsx +39 -0
  12. package/src/commandCell/CommandCellPrice.tsx +9 -0
  13. package/src/commandCell/CommandCellSwitch.tsx +21 -0
  14. package/tsconfig.json +13 -0
  15. package/FilterCellDropdown.d.ts +0 -11
  16. package/FilterCellDropdown.js +0 -32
  17. package/GenericDropdown.d.ts +0 -33
  18. package/GenericDropdown.js +0 -74
  19. package/MultiSelectDropdown.d.ts +0 -16
  20. package/MultiSelectDropdown.js +0 -54
  21. package/PropTypes.js +0 -1
  22. package/Toolbar.d.ts +0 -13
  23. package/Toolbar.js +0 -4
  24. package/Utility.d.ts +0 -4
  25. package/Utility.js +0 -11
  26. package/commandCell/CommandCellCheckbox.d.ts +0 -8
  27. package/commandCell/CommandCellCheckbox.js +0 -13
  28. package/commandCell/CommandCellDDWithoutId.js +0 -8
  29. package/commandCell/CommandCellDate.d.ts +0 -9
  30. package/commandCell/CommandCellDate.js +0 -12
  31. package/commandCell/CommandCellDropdown.d.ts +0 -21
  32. package/commandCell/CommandCellDropdown.js +0 -11
  33. package/commandCell/CommandCellPrice.d.ts +0 -3
  34. package/commandCell/CommandCellPrice.js +0 -10
  35. package/commandCell/CommandCellSwitch.d.ts +0 -7
  36. package/commandCell/CommandCellSwitch.js +0 -5
  37. package/index.js +0 -10
  38. /package/{index.d.ts → src/index.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scheels-softdev/kendoreact-generics",
3
- "version": "2.4.9",
3
+ "version": "2.5.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -0,0 +1,50 @@
1
+ import { ComboBoxChangeEvent } from "@progress/kendo-react-dropdowns";
2
+ import { GridFilterCellProps } from "@progress/kendo-react-grid";
3
+ import { Button } from "@progress/kendo-react-buttons";
4
+ import { GenericDropdown } from "./GenericDropdown";
5
+
6
+ interface DropdownFilterCellProps<T> extends GridFilterCellProps {
7
+ /** The data to populate the dropdown options */
8
+ data: T[];
9
+ /** The field names used to extract text values for display */
10
+ textFields: (keyof T)[];
11
+ /** The separator to use when concatenating multiple text values */
12
+ separator?: string;
13
+ }
14
+
15
+ // Define the DropdownFilterCell component with props of type DropdownFilterCellProps
16
+ export function FilterCellDropdown<T>(props: DropdownFilterCellProps<T>) {
17
+ // Define a function that returns true if a value is not undefined or null, and is different from the default item
18
+ let hasValue: any = (value: string) => Boolean(value);
19
+
20
+ // Define an onChange function that will be called when the ComboBox value changes
21
+ const onChange = (event: ComboBoxChangeEvent) => {
22
+ // Update the hasValue variable based on the new value of the ComboBox
23
+ hasValue = hasValue(event?.target?.value?.id);
24
+ // Call the onChange function passed down as a prop, passing a filter object with the new value and operator
25
+ props.onChange({
26
+ value: hasValue ? event.target.value.id : "", // Use the ID of the selected value as the filter value
27
+ operator: hasValue ? "eq" : "", // Use the "eq" operator if the value is non-empty, otherwise use an empty string
28
+ syntheticEvent: event.syntheticEvent,
29
+ });
30
+ };
31
+
32
+ // Define an onClearButtonClick function that will be called when the Clear button is clicked
33
+ const onClearButtonClick = (event: any) => {
34
+ event.preventDefault();
35
+ // Call the onChange function passed down as a prop, passing a filter object with empty values
36
+ props.onChange({
37
+ value: "", // Set the filter value to an empty string
38
+ operator: "", // Set the operator to an empty string
39
+ syntheticEvent: event,
40
+ });
41
+ };
42
+
43
+ // Render a div containing a GenericDropdownWithSearch component and a Clear button
44
+ return (
45
+ <div className="k-filtercell" data-testid="dropdownFilter">
46
+ <GenericDropdown data={props.data} onChange={onChange} selectedId={props.value} textFields={[...props.textFields]} separator={props.separator} />
47
+ <Button title="Clear" disabled={!hasValue(props.value)} onClick={onClearButtonClick} icon="filter-clear" />
48
+ </div>
49
+ );
50
+ }
@@ -0,0 +1,170 @@
1
+ import { ComboBox, ComboBoxFilterChangeEvent, ComboBoxPageChangeEvent } from "@progress/kendo-react-dropdowns";
2
+ import { filterBy } from "@progress/kendo-data-query";
3
+ import { CSSProperties, useEffect, useRef, useState } from "react";
4
+ import { getTextValue } from "./Utility";
5
+ import { Skeleton } from "@progress/kendo-react-indicators";
6
+ //TODO add a style property
7
+ //TODO add metadata documentation
8
+ // component that renders a dropdown with a search filter
9
+ /**
10
+ * JSX Component for displaying items in a virtualized combobox
11
+ * @template T - The type of the data objects in the dropdown.
12
+ * @param {object} props - The component props.
13
+ * @returns {JSX.Element}
14
+ */
15
+
16
+ type GenericDDProps<T> = {
17
+ /*1* The data to populate the dropdown options */
18
+ data: T[];
19
+ /** The ID of the currently selected item. (optional)*/
20
+ selectedId?: number;
21
+ /** The currently selected data object. (optional)*/
22
+ selectedData?: T;
23
+ /** Callback function triggered when the selected value changes*/
24
+ onChange: Function;
25
+ /** The field names used to extract text values for display */
26
+ textFields: (keyof T)[];
27
+ /** The separator to use when concatenating multiple text values. (optional)*/
28
+ separator?: string;
29
+ /** Determines whether the dropdown is disabled. (optional)*/
30
+ idField?: keyof T;
31
+ /** The field name used as the identity key (optional)*/
32
+ disabled?: boolean;
33
+ /** The label displayed for the dropdown (optional)*/
34
+ title?: string;
35
+ /** The Determines whether the clear button is hidden from the dropdown. (optional)*/
36
+ hideClearButton?: boolean;
37
+ /** Custom CSS properties for the component. (optional)*/
38
+ style?: CSSProperties;
39
+ isLoading?: boolean;
40
+ };
41
+ export function GenericDropdown<T>({
42
+ data,
43
+ selectedId,
44
+ selectedData,
45
+ onChange,
46
+ textFields,
47
+ separator,
48
+ disabled,
49
+ idField,
50
+ title,
51
+ hideClearButton,
52
+ style,
53
+ isLoading,
54
+ }: GenericDDProps<T>) {
55
+ if (selectedId !== undefined && selectedData !== undefined) {
56
+ throw new Error("You cannot provide both selectedData and selectedId to GenericDropdown.");
57
+ }
58
+ //local state
59
+ const pageSize = 8;
60
+
61
+ const [dataList, setDataList] = useState<any[]>([]);
62
+ const [state, setState] = useState({
63
+ skip: 0,
64
+ total: dataList.length,
65
+ subsetData: dataList.slice(0, pageSize),
66
+ });
67
+
68
+ //external function variables
69
+ let filteredData = useRef(dataList.slice());
70
+
71
+ //function creation
72
+ // function to handle filter changes
73
+ const onFilterChange = (event: ComboBoxFilterChangeEvent) => {
74
+ if (event.filter.value?.length) filteredData.current = filterBy(dataList.slice(), event.filter);
75
+ else filteredData.current = dataList;
76
+ const newData = filteredData.current.slice(0, pageSize);
77
+ setState({
78
+ subsetData: newData,
79
+ skip: 0,
80
+ total: filteredData.current.length,
81
+ });
82
+ };
83
+ // function to handle page changes for virtualization
84
+ const pageChange = (event: ComboBoxPageChangeEvent) => {
85
+ console.log("page change data: ", event.page, filteredData.current);
86
+ const skip = event.page.skip;
87
+ const take = event.page.take;
88
+ const newSubsetData = filteredData.current.length ? filteredData.current.slice(skip, skip + take) : dataList.slice(skip, skip + take);
89
+ setState({ ...state, subsetData: newSubsetData, skip: skip });
90
+ };
91
+
92
+ //change event listeners
93
+ useEffect(() => {
94
+ dataList;
95
+ });
96
+ useEffect(() => {
97
+ if (data.length) {
98
+ setDataList(
99
+ data.map((x) => {
100
+ return {
101
+ ...x,
102
+ textValue: getTextValue(
103
+ x,
104
+ textFields.map((x) => x.toString()),
105
+ separator
106
+ ),
107
+ };
108
+ })
109
+ );
110
+ setState({
111
+ ...state,
112
+ total: data.length,
113
+ subsetData: data.map((x) => {
114
+ return {
115
+ ...x,
116
+ textValue: getTextValue(
117
+ x,
118
+ textFields.map((x) => x.toString()),
119
+ separator
120
+ ),
121
+ };
122
+ }),
123
+ });
124
+ }
125
+ }, [data, textFields, separator]);
126
+ const findByIndex = (id: number | undefined, idKey: keyof T | undefined) => {
127
+ console.log(id, data, idField);
128
+ const item = dataList.find((item: any) => id === item[idKey || "id"]);
129
+ console.log(item);
130
+ return item;
131
+ };
132
+ const findByValue = (item: T | undefined) => {
133
+ console.log(item, data);
134
+ const returnVal = dataList.find((x) => JSON.stringify({ ...x, ...selectedData }) === JSON.stringify({ ...x }));
135
+ console.log(returnVal);
136
+ return returnVal;
137
+ };
138
+ return (
139
+ <div data-testid={"dropdown"}>
140
+ {dataList.length && !isLoading ? (
141
+ <ComboBox
142
+ style={style}
143
+ label={title}
144
+ disabled={disabled}
145
+ data={state.subsetData} // data to display in the dropdown
146
+ textField={"textValue"} // name of the field to use for display text
147
+ virtual={{
148
+ // enable virtualization for large datasets
149
+ total: state.total,
150
+ pageSize: pageSize,
151
+ skip: state.skip,
152
+ }}
153
+ suggest
154
+ onPageChange={pageChange} // handle page changes for virtualization
155
+ filterable={true} // enable filter
156
+ onFilterChange={onFilterChange} // handle filter changes
157
+ popupSettings={{
158
+ height: "210px",
159
+ }}
160
+ onChange={(e) => onChange(e)}
161
+ onBlur={(e) => e.nativeEvent.preventDefault()}
162
+ clearButton={!hideClearButton}
163
+ value={!selectedId && !selectedData ? null : findByIndex(selectedId, idField) || findByValue(selectedData) || null}
164
+ />
165
+ ) : (
166
+ <Skeleton shape="rectangle" style={style ? style : { height: "40px", width: "100%" }} />
167
+ )}
168
+ </div>
169
+ );
170
+ }
@@ -0,0 +1,111 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { filterBy } from "@progress/kendo-data-query";
3
+ import { MultiSelect, MultiSelectPageChangeEvent, MultiSelectFilterChangeEvent } from "@progress/kendo-react-dropdowns";
4
+ import { getTextValue } from "./Utility";
5
+ export function MultiSelectDropdown<T>({
6
+ data,
7
+ selectedData,
8
+ textFields,
9
+ selectEvent,
10
+ title,
11
+ separator,
12
+ limit,
13
+ }: {
14
+ /** The data array for the dropdown options. */
15
+ data: T[];
16
+ /** The array of selected data items. */
17
+ selectedData: T[];
18
+ /** The field names to use for text values in the dropdown. */
19
+ textFields: (keyof T)[];
20
+ /** The function to call when an item is selected or deselected. */
21
+ selectEvent: Function;
22
+ /** The optional title of the dropdown. */
23
+ title?: string;
24
+ /** The optional separator to use for concatenating text values. */
25
+ separator?: string;
26
+ /** The optional limit of the maximum number of selected items. */
27
+ limit?: number;
28
+ }) {
29
+ //local state
30
+ const pageSize = 8;
31
+ const [dataList, setDataList] = useState(
32
+ data.map((x) => {
33
+ return {
34
+ ...x,
35
+ textValue: getTextValue(
36
+ x,
37
+ textFields.map((x) => x.toString()),
38
+ separator
39
+ ),
40
+ };
41
+ })
42
+ );
43
+ const [state, setState] = useState({
44
+ skip: 0,
45
+ total: dataList.length,
46
+ subsetData: dataList.slice(0, pageSize),
47
+ });
48
+
49
+ //external function variables
50
+ const filteredData = useRef(dataList.slice());
51
+ //function creation
52
+ // function to handle filter changes
53
+ const onFilterChange = (event: MultiSelectFilterChangeEvent) => {
54
+ if (event.filter.value?.length) filteredData.current = filterBy(dataList.slice(), event.filter);
55
+ else filteredData.current = dataList;
56
+ const newData = filteredData.current.slice(0, pageSize);
57
+ setState({
58
+ subsetData: newData,
59
+ skip: 0,
60
+ total: filteredData.current.length,
61
+ });
62
+ };
63
+ // function to handle page changes for virtualization
64
+ const pageChange = (event: MultiSelectPageChangeEvent) => {
65
+ const skip = event.page.skip;
66
+ const take = event.page.take;
67
+ const newSubsetData = filteredData.current.slice(skip, skip + take);
68
+ setState({ ...state, subsetData: newSubsetData, skip: skip });
69
+ };
70
+
71
+ //change event listeners
72
+ useEffect(() => {
73
+ setDataList(
74
+ data.map((x) => {
75
+ return {
76
+ ...x,
77
+ textValue: getTextValue(
78
+ x,
79
+ textFields.map((x) => x.toString()),
80
+ separator
81
+ ),
82
+ };
83
+ })
84
+ );
85
+ }, [data, textFields, separator]);
86
+
87
+ return (
88
+ <div data-testid={"multiselect"} style={{ width: "100%" }}>
89
+ <MultiSelect
90
+ label={title}
91
+ data={state.subsetData}
92
+ textField={"textValue"} // name of the field to use for display text
93
+ style={{ width: "100%" }}
94
+ virtual={{
95
+ total: state.total,
96
+ pageSize: pageSize,
97
+ skip: state.skip,
98
+ }}
99
+ onPageChange={pageChange}
100
+ filterable={true}
101
+ onFilterChange={onFilterChange}
102
+ popupSettings={{
103
+ height: "210px",
104
+ }}
105
+ onChange={(e) => selectEvent(limit && e.value.length ? e.value.slice(0, limit) : e.value)}
106
+ autoClose={false}
107
+ value={selectedData} ///right now: clears selected values whenever selected Vendor Value changes. This will need to be changed to something better in the future
108
+ />
109
+ </div>
110
+ );
111
+ }
@@ -2,6 +2,7 @@ export type CommonProps = {
2
2
  isEditing?: boolean;
3
3
  id?: number;
4
4
  };
5
+
5
6
  export type GridChangeEvent = {
6
7
  value: any;
7
8
  field?: string;
@@ -0,0 +1,27 @@
1
+ type CommonProps = {
2
+ id: number;
3
+ isEditing?: boolean;
4
+ };
5
+ export function ToolbarButton<T extends CommonProps>({
6
+ item,
7
+ data,
8
+ setData,
9
+ }: {
10
+ /** The item object to add. */
11
+ item: T;
12
+ /** The data array. */
13
+ data: T[];
14
+ /** The function to set the updated data. */
15
+ setData: Function;
16
+ }) {
17
+ return (
18
+ <button
19
+ title="Add new"
20
+ className="k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary"
21
+ onClick={() => setData([{ ...item, isEditing: true, id: 0 }, ...data])}
22
+ disabled={data.find((x) => x.isEditing) ? true : false}
23
+ >
24
+ Add Another
25
+ </button>
26
+ );
27
+ }
package/src/Utility.ts ADDED
@@ -0,0 +1,19 @@
1
+ // function to concatenate text values from dataItem using specified fields and separator
2
+ export const getTextValue = (dataItem: any, fields: string[], separator?: string) => {
3
+ let textValue = "";
4
+ fields.forEach((field, index) => (textValue += index > 0 ? (separator ? separator : " ") + dataItem[field] : dataItem[field]));
5
+ return textValue;
6
+ };
7
+
8
+ export const getDropdownArray = <T>(data: T[], textFields: (keyof T)[], separator: string) => {
9
+ return data.map((x) => {
10
+ return {
11
+ ...x,
12
+ textValue: getTextValue(
13
+ x,
14
+ textFields.map((x) => x.toString()),
15
+ separator
16
+ ),
17
+ };
18
+ });
19
+ };
@@ -0,0 +1,28 @@
1
+ import { Checkbox } from "@progress/kendo-react-inputs";
2
+
3
+ export function CommandCellCheckBox({
4
+ checked,
5
+ onCheck,
6
+ onUncheck,
7
+ }: {
8
+ /** Boolean value indicating whether the checkbox is checked (`true`) or unchecked (`false`). */
9
+ checked: boolean;
10
+ /** Callback function to be called when the checkbox is checked. */
11
+ onCheck: Function;
12
+ /** Callback function to be called when the checkbox is unchecked. */
13
+ onUncheck: Function;
14
+ }) {
15
+ const functionToRun = () => {
16
+ if (checked) {
17
+ onUncheck();
18
+ } else {
19
+ onCheck();
20
+ }
21
+ };
22
+
23
+ return (
24
+ <td className="justify-content-center" data-testid="checkbox">
25
+ <Checkbox checked={checked} onChange={functionToRun} />
26
+ </td>
27
+ );
28
+ }
@@ -1,5 +1,7 @@
1
1
  import { ComboBoxChangeEvent } from "@progress/kendo-react-dropdowns";
2
- export declare function CommandCellDDWithoutId<T>(props: {
2
+ import { GenericDropdown } from "../GenericDropdown";
3
+
4
+ export function CommandCellDDWithoutId<T>(props: {
3
5
  /** The data array for the dropdown options. */
4
6
  data: T[];
5
7
  /** The currently selected data item. */
@@ -16,4 +18,16 @@ export declare function CommandCellDDWithoutId<T>(props: {
16
18
  isEditing?: boolean;
17
19
  /** Determines if the clear button should be displayed in the dropdown. */
18
20
  showClearButton?: boolean;
19
- }): import("react/jsx-runtime").JSX.Element;
21
+ }) {
22
+ // Function implementation...
23
+ return (
24
+ <td>
25
+ {props.checkEditField && !props.isEditing ? (
26
+ props.textFields.map((x) => props.data.find((y) => y === props.selectedData)![x]).join(props.separator || " ")
27
+ ) : (
28
+ // If "props.checkEditField" is false or "props.isEditing" is true, render the GenericDropdownWithSearch component with the "props" passed to it
29
+ <GenericDropdown {...props} />
30
+ )}
31
+ </td>
32
+ );
33
+ }
@@ -0,0 +1,36 @@
1
+ import { DatePicker } from "@progress/kendo-react-dateinputs";
2
+ import moment from "moment";
3
+ import { CommonProps, GridChangeEvent } from "../PropTypes";
4
+ export function CommandCellDate<T extends CommonProps>({
5
+ dataItem,
6
+ onChange,
7
+ field,
8
+ }: {
9
+ /** The data item for the cell. */
10
+ dataItem: T;
11
+ /** Callback function to be called when the value changes. */
12
+ onChange: (e: GridChangeEvent) => void;
13
+ /** The field of the data item to display in the cell. this field must be formattable into a date. */
14
+ field: keyof T;
15
+ }) {
16
+ let valString = "" + dataItem[field];
17
+ let date = moment(valString).format("MM/DD/YY");
18
+ return (
19
+ <td data-testid="date">
20
+ {valString === undefined || dataItem.isEditing ? (
21
+ <DatePicker
22
+ value={new Date(moment(valString).format("MMMM, DD YYYY"))}
23
+ onChange={(e) =>
24
+ onChange({
25
+ field: field.toString(),
26
+ value: moment(e.value),
27
+ dataItem: dataItem,
28
+ })
29
+ }
30
+ />
31
+ ) : (
32
+ date
33
+ )}
34
+ </td>
35
+ );
36
+ }
@@ -0,0 +1,39 @@
1
+ import { ComboBoxChangeEvent } from "@progress/kendo-react-dropdowns";
2
+ import { GenericDropdown } from "../GenericDropdown";
3
+ import { CommonProps } from "../PropTypes";
4
+
5
+ // This exports a function component called "CommandCellDropdown"
6
+ // It takes in various props that are used to render a dropdown in a table cell
7
+ export function CommandCellDropdown<T>(props: {
8
+ /** The data array for the dropdown options. */
9
+ data: T[];
10
+ /** The ID of the currently selected item. */
11
+ selectedId: number;
12
+ /** The field names to use for text values in the dropdown. */
13
+ textFields: (keyof T)[];
14
+ /** Callback function to be called when the selected value changes. */
15
+ onChange: (e: ComboBoxChangeEvent) => void;
16
+ /** Optional separator to use for concatenating text values. */
17
+ separator?: string;
18
+ /** Determines if the edit field should be checked. */
19
+ checkEditField?: boolean;
20
+ /** Determines if the cell is in an editing state. */
21
+ isEditing?: boolean;
22
+ /** The field to use as the identity key. */
23
+ idField?: keyof T;
24
+ /** Determines if the clear button should be displayed in the dropdown. */
25
+ showClearButton?: boolean;
26
+ }) {
27
+ return (
28
+ <td>
29
+ {props.checkEditField && !props.isEditing && props.data.length ? (
30
+ props.textFields
31
+ .map((x) => props.data.find((y: any) => y[props.idField ? props.idField : "id"] === props.selectedId)![x])
32
+ .join(props.separator || " ")
33
+ ) : (
34
+ // If "props.checkEditField" is false or "props.isEditing" is true, render the GenericDropdownWithSearch component with the "props" passed to it
35
+ <GenericDropdown {...props} />
36
+ )}
37
+ </td>
38
+ );
39
+ }
@@ -0,0 +1,9 @@
1
+ export function CommandCellPrice({ cost }: { /** The cost value for the cell. */ cost: number }) {
2
+ let formattedCost: any = new Intl.NumberFormat("en", {
3
+ style: "currency",
4
+ currency: "USD",
5
+ minimumSignificantDigits: 2,
6
+ maximumFractionDigits: 3,
7
+ }).format(cost);
8
+ return <td data-testid="price">{formattedCost}</td>;
9
+ }
@@ -0,0 +1,21 @@
1
+ import { GridCellProps } from "@progress/kendo-react-grid";
2
+ import { Switch } from "@progress/kendo-react-inputs";
3
+ export function CommandCellSwitch({
4
+ props,
5
+ changeFunction,
6
+ }: {
7
+ /** The GridCellProps object containing cell-related properties. */
8
+ props: GridCellProps;
9
+ /** The function to call when the switch value changes. */
10
+ changeFunction: Function;
11
+ }) {
12
+ return (
13
+ <td data-testid="switch">
14
+ {props.dataItem.isEditing ? (
15
+ <Switch onChange={() => changeFunction()} checked={props.dataItem[props.field!]} />
16
+ ) : (
17
+ props.dataItem[props.field!].toString()
18
+ )}
19
+ </td>
20
+ );
21
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "jsx": "react-jsx",
5
+ "declaration": true,
6
+ "esModuleInterop": true,
7
+ "outDir": "dist",
8
+ "target": "es6",
9
+ "module": "es6",
10
+ "moduleResolution": "node"
11
+ },
12
+ "include": ["src"]
13
+ }
@@ -1,11 +0,0 @@
1
- import { GridFilterCellProps } from "@progress/kendo-react-grid";
2
- interface DropdownFilterCellProps<T> extends GridFilterCellProps {
3
- /** The data to populate the dropdown options */
4
- data: T[];
5
- /** The field names used to extract text values for display */
6
- textFields: (keyof T)[];
7
- /** The separator to use when concatenating multiple text values */
8
- separator?: string;
9
- }
10
- export declare function FilterCellDropdown<T>(props: DropdownFilterCellProps<T>): import("react/jsx-runtime").JSX.Element;
11
- export {};
@@ -1,32 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button } from "@progress/kendo-react-buttons";
3
- import { GenericDropdown } from "./GenericDropdown";
4
- // Define the DropdownFilterCell component with props of type DropdownFilterCellProps
5
- export function FilterCellDropdown(props) {
6
- // Define a function that returns true if a value is not undefined or null, and is different from the default item
7
- let hasValue = (value) => Boolean(value);
8
- // Define an onChange function that will be called when the ComboBox value changes
9
- const onChange = (event) => {
10
- var _a, _b;
11
- // Update the hasValue variable based on the new value of the ComboBox
12
- hasValue = hasValue((_b = (_a = event === null || event === void 0 ? void 0 : event.target) === null || _a === void 0 ? void 0 : _a.value) === null || _b === void 0 ? void 0 : _b.id);
13
- // Call the onChange function passed down as a prop, passing a filter object with the new value and operator
14
- props.onChange({
15
- value: hasValue ? event.target.value.id : "",
16
- operator: hasValue ? "eq" : "",
17
- syntheticEvent: event.syntheticEvent,
18
- });
19
- };
20
- // Define an onClearButtonClick function that will be called when the Clear button is clicked
21
- const onClearButtonClick = (event) => {
22
- event.preventDefault();
23
- // Call the onChange function passed down as a prop, passing a filter object with empty values
24
- props.onChange({
25
- value: "",
26
- operator: "",
27
- syntheticEvent: event,
28
- });
29
- };
30
- // Render a div containing a GenericDropdownWithSearch component and a Clear button
31
- return (_jsxs("div", Object.assign({ className: "k-filtercell", "data-testid": "dropdownFilter" }, { children: [_jsx(GenericDropdown, { data: props.data, onChange: onChange, selectedId: props.value, textFields: [...props.textFields], separator: props.separator }), _jsx(Button, { title: "Clear", disabled: !hasValue(props.value), onClick: onClearButtonClick, icon: "filter-clear" })] })));
32
- }
@@ -1,33 +0,0 @@
1
- import { CSSProperties } from "react";
2
- /**
3
- * JSX Component for displaying items in a virtualized combobox
4
- * @template T - The type of the data objects in the dropdown.
5
- * @param {object} props - The component props.
6
- * @returns {JSX.Element}
7
- */
8
- type GenericDDProps<T> = {
9
- data: T[];
10
- /** The ID of the currently selected item. (optional)*/
11
- selectedId?: number;
12
- /** The currently selected data object. (optional)*/
13
- selectedData?: T;
14
- /** Callback function triggered when the selected value changes*/
15
- onChange: Function;
16
- /** The field names used to extract text values for display */
17
- textFields: (keyof T)[];
18
- /** The separator to use when concatenating multiple text values. (optional)*/
19
- separator?: string;
20
- /** Determines whether the dropdown is disabled. (optional)*/
21
- idField?: keyof T;
22
- /** The field name used as the identity key (optional)*/
23
- disabled?: boolean;
24
- /** The label displayed for the dropdown (optional)*/
25
- title?: string;
26
- /** The Determines whether the clear button is hidden from the dropdown. (optional)*/
27
- hideClearButton?: boolean;
28
- /** Custom CSS properties for the component. (optional)*/
29
- style?: CSSProperties;
30
- isLoading?: boolean;
31
- };
32
- export declare function GenericDropdown<T>({ data, selectedId, selectedData, onChange, textFields, separator, disabled, idField, title, hideClearButton, style, isLoading, }: GenericDDProps<T>): import("react/jsx-runtime").JSX.Element;
33
- export {};
@@ -1,74 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { ComboBox } from "@progress/kendo-react-dropdowns";
3
- import { filterBy } from "@progress/kendo-data-query";
4
- import { useEffect, useRef, useState } from "react";
5
- import { getTextValue } from "./Utility";
6
- import { Skeleton } from "@progress/kendo-react-indicators";
7
- export function GenericDropdown({ data, selectedId, selectedData, onChange, textFields, separator, disabled, idField, title, hideClearButton, style, isLoading, }) {
8
- if (selectedId !== undefined && selectedData !== undefined) {
9
- throw new Error("You cannot provide both selectedData and selectedId to GenericDropdown.");
10
- }
11
- //local state
12
- const pageSize = 8;
13
- const [dataList, setDataList] = useState([]);
14
- const [state, setState] = useState({
15
- skip: 0,
16
- total: dataList.length,
17
- subsetData: dataList.slice(0, pageSize),
18
- });
19
- //external function variables
20
- let filteredData = useRef(dataList.slice());
21
- //function creation
22
- // function to handle filter changes
23
- const onFilterChange = (event) => {
24
- filteredData.current = filterBy(dataList.slice(), event.filter);
25
- const newData = filteredData.current.slice(0, pageSize);
26
- setState({
27
- subsetData: newData,
28
- skip: 0,
29
- total: filteredData.current.length,
30
- });
31
- };
32
- // function to handle page changes for virtualization
33
- const pageChange = (event) => {
34
- console.log("page change data: ", event.page, filteredData.current);
35
- const skip = event.page.skip;
36
- const take = event.page.take;
37
- const newSubsetData = filteredData.current.slice(skip, skip + take);
38
- setState(Object.assign(Object.assign({}, state), { subsetData: newSubsetData, skip: skip }));
39
- };
40
- //change event listeners
41
- useEffect(() => {
42
- dataList;
43
- });
44
- useEffect(() => {
45
- if (data.length) {
46
- setDataList(data.map((x) => {
47
- return Object.assign(Object.assign({}, x), { textValue: getTextValue(x, textFields.map((x) => x.toString()), separator) });
48
- }));
49
- setState(Object.assign(Object.assign({}, state), { total: data.length, subsetData: data.map((x) => {
50
- return Object.assign(Object.assign({}, x), { textValue: getTextValue(x, textFields.map((x) => x.toString()), separator) });
51
- }) }));
52
- }
53
- }, [data, textFields, separator]);
54
- const findByIndex = (id, idKey) => {
55
- console.log(id, data, idField);
56
- const item = dataList.find((item) => id === item[idKey || "id"]);
57
- console.log(item);
58
- return item;
59
- };
60
- const findByValue = (item) => {
61
- console.log(item, data);
62
- const returnVal = dataList.find((x) => JSON.stringify(Object.assign(Object.assign({}, x), selectedData)) === JSON.stringify(Object.assign({}, x)));
63
- console.log(returnVal);
64
- return returnVal;
65
- };
66
- return (_jsx("div", Object.assign({ "data-testid": "dropdown" }, { children: dataList.length && !isLoading ? (_jsx(ComboBox, { style: style, label: title, disabled: disabled, data: state.subsetData, textField: "textValue", virtual: {
67
- // enable virtualization for large datasets
68
- total: state.total,
69
- pageSize: pageSize,
70
- skip: state.skip,
71
- }, suggest: true, onPageChange: pageChange, filterable: true, onFilterChange: onFilterChange, popupSettings: {
72
- height: "210px",
73
- }, onChange: (e) => onChange(e), onBlur: (e) => e.nativeEvent.preventDefault(), clearButton: !hideClearButton, value: !selectedId && !selectedData ? null : findByIndex(selectedId, idField) || findByValue(selectedData) || null })) : (_jsx(Skeleton, { shape: "rectangle", style: style ? style : { height: "40px", width: "100%" } })) })));
74
- }
@@ -1,16 +0,0 @@
1
- export declare function MultiSelectDropdown<T>({ data, selectedData, textFields, selectEvent, title, separator, limit, }: {
2
- /** The data array for the dropdown options. */
3
- data: T[];
4
- /** The array of selected data items. */
5
- selectedData: T[];
6
- /** The field names to use for text values in the dropdown. */
7
- textFields: (keyof T)[];
8
- /** The function to call when an item is selected or deselected. */
9
- selectEvent: Function;
10
- /** The optional title of the dropdown. */
11
- title?: string;
12
- /** The optional separator to use for concatenating text values. */
13
- separator?: string;
14
- /** The optional limit of the maximum number of selected items. */
15
- limit?: number;
16
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,54 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useEffect, useRef, useState } from "react";
3
- import { filterBy } from "@progress/kendo-data-query";
4
- import { MultiSelect } from "@progress/kendo-react-dropdowns";
5
- import { getTextValue } from "./Utility";
6
- export function MultiSelectDropdown({ data, selectedData, textFields, selectEvent, title, separator, limit, }) {
7
- //local state
8
- const pageSize = 8;
9
- const [dataList, setDataList] = useState(data.map((x) => {
10
- return Object.assign(Object.assign({}, x), { textValue: getTextValue(x, textFields.map((x) => x.toString()), separator) });
11
- }));
12
- const [state, setState] = useState({
13
- skip: 0,
14
- total: dataList.length,
15
- subsetData: dataList.slice(0, pageSize),
16
- });
17
- //external function variables
18
- const filteredData = useRef(dataList.slice());
19
- //function creation
20
- // function to handle filter changes
21
- const onFilterChange = (event) => {
22
- var _a;
23
- if ((_a = event.filter.value) === null || _a === void 0 ? void 0 : _a.length)
24
- filteredData.current = filterBy(dataList.slice(), event.filter);
25
- else
26
- filteredData.current = dataList;
27
- const newData = filteredData.current.slice(0, pageSize);
28
- setState({
29
- subsetData: newData,
30
- skip: 0,
31
- total: filteredData.current.length,
32
- });
33
- };
34
- // function to handle page changes for virtualization
35
- const pageChange = (event) => {
36
- const skip = event.page.skip;
37
- const take = event.page.take;
38
- const newSubsetData = filteredData.current.slice(skip, skip + take);
39
- setState(Object.assign(Object.assign({}, state), { subsetData: newSubsetData, skip: skip }));
40
- };
41
- //change event listeners
42
- useEffect(() => {
43
- setDataList(data.map((x) => {
44
- return Object.assign(Object.assign({}, x), { textValue: getTextValue(x, textFields.map((x) => x.toString()), separator) });
45
- }));
46
- }, [data, textFields, separator]);
47
- return (_jsx("div", Object.assign({ "data-testid": "multiselect", style: { width: "100%" } }, { children: _jsx(MultiSelect, { label: title, data: state.subsetData, textField: "textValue", style: { width: "100%" }, virtual: {
48
- total: state.total,
49
- pageSize: pageSize,
50
- skip: state.skip,
51
- }, onPageChange: pageChange, filterable: true, onFilterChange: onFilterChange, popupSettings: {
52
- height: "210px",
53
- }, onChange: (e) => selectEvent(limit && e.value.length ? e.value.slice(0, limit) : e.value), autoClose: false, value: selectedData }) })));
54
- }
package/PropTypes.js DELETED
@@ -1 +0,0 @@
1
- export {};
package/Toolbar.d.ts DELETED
@@ -1,13 +0,0 @@
1
- type CommonProps = {
2
- id: number;
3
- isEditing?: boolean;
4
- };
5
- export declare function ToolbarButton<T extends CommonProps>({ item, data, setData, }: {
6
- /** The item object to add. */
7
- item: T;
8
- /** The data array. */
9
- data: T[];
10
- /** The function to set the updated data. */
11
- setData: Function;
12
- }): import("react/jsx-runtime").JSX.Element;
13
- export {};
package/Toolbar.js DELETED
@@ -1,4 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- export function ToolbarButton({ item, data, setData, }) {
3
- return (_jsx("button", Object.assign({ title: "Add new", className: "k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary", onClick: () => setData([Object.assign(Object.assign({}, item), { isEditing: true, id: 0 }), ...data]), disabled: data.find((x) => x.isEditing) ? true : false }, { children: "Add Another" })));
4
- }
package/Utility.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare const getTextValue: (dataItem: any, fields: string[], separator?: string) => string;
2
- export declare const getDropdownArray: <T>(data: T[], textFields: (keyof T)[], separator: string) => (T & {
3
- textValue: string;
4
- })[];
package/Utility.js DELETED
@@ -1,11 +0,0 @@
1
- // function to concatenate text values from dataItem using specified fields and separator
2
- export const getTextValue = (dataItem, fields, separator) => {
3
- let textValue = "";
4
- fields.forEach((field, index) => (textValue += index > 0 ? (separator ? separator : " ") + dataItem[field] : dataItem[field]));
5
- return textValue;
6
- };
7
- export const getDropdownArray = (data, textFields, separator) => {
8
- return data.map((x) => {
9
- return Object.assign(Object.assign({}, x), { textValue: getTextValue(x, textFields.map((x) => x.toString()), separator) });
10
- });
11
- };
@@ -1,8 +0,0 @@
1
- export declare function CommandCellCheckBox({ checked, onCheck, onUncheck, }: {
2
- /** Boolean value indicating whether the checkbox is checked (`true`) or unchecked (`false`). */
3
- checked: boolean;
4
- /** Callback function to be called when the checkbox is checked. */
5
- onCheck: Function;
6
- /** Callback function to be called when the checkbox is unchecked. */
7
- onUncheck: Function;
8
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Checkbox } from "@progress/kendo-react-inputs";
3
- export function CommandCellCheckBox({ checked, onCheck, onUncheck, }) {
4
- const functionToRun = () => {
5
- if (checked) {
6
- onUncheck();
7
- }
8
- else {
9
- onCheck();
10
- }
11
- };
12
- return (_jsx("td", Object.assign({ className: "justify-content-center", "data-testid": "checkbox" }, { children: _jsx(Checkbox, { checked: checked, onChange: functionToRun }) })));
13
- }
@@ -1,8 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { GenericDropdown } from "../GenericDropdown";
3
- export function CommandCellDDWithoutId(props) {
4
- // Function implementation...
5
- return (_jsx("td", { children: props.checkEditField && !props.isEditing ? (props.textFields.map((x) => props.data.find((y) => y === props.selectedData)[x]).join(props.separator || " ")) : (
6
- // If "props.checkEditField" is false or "props.isEditing" is true, render the GenericDropdownWithSearch component with the "props" passed to it
7
- _jsx(GenericDropdown, Object.assign({}, props))) }));
8
- }
@@ -1,9 +0,0 @@
1
- import { CommonProps, GridChangeEvent } from "../PropTypes";
2
- export declare function CommandCellDate<T extends CommonProps>({ dataItem, onChange, field, }: {
3
- /** The data item for the cell. */
4
- dataItem: T;
5
- /** Callback function to be called when the value changes. */
6
- onChange: (e: GridChangeEvent) => void;
7
- /** The field of the data item to display in the cell. this field must be formattable into a date. */
8
- field: keyof T;
9
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { DatePicker } from "@progress/kendo-react-dateinputs";
3
- import moment from "moment";
4
- export function CommandCellDate({ dataItem, onChange, field, }) {
5
- let valString = "" + dataItem[field];
6
- let date = moment(valString).format("MM/DD/YY");
7
- return (_jsx("td", Object.assign({ "data-testid": "date" }, { children: valString === undefined || dataItem.isEditing ? (_jsx(DatePicker, { value: new Date(moment(valString).format("MMMM, DD YYYY")), onChange: (e) => onChange({
8
- field: field.toString(),
9
- value: moment(e.value),
10
- dataItem: dataItem,
11
- }) })) : (date) })));
12
- }
@@ -1,21 +0,0 @@
1
- import { ComboBoxChangeEvent } from "@progress/kendo-react-dropdowns";
2
- export declare function CommandCellDropdown<T>(props: {
3
- /** The data array for the dropdown options. */
4
- data: T[];
5
- /** The ID of the currently selected item. */
6
- selectedId: number;
7
- /** The field names to use for text values in the dropdown. */
8
- textFields: (keyof T)[];
9
- /** Callback function to be called when the selected value changes. */
10
- onChange: (e: ComboBoxChangeEvent) => void;
11
- /** Optional separator to use for concatenating text values. */
12
- separator?: string;
13
- /** Determines if the edit field should be checked. */
14
- checkEditField?: boolean;
15
- /** Determines if the cell is in an editing state. */
16
- isEditing?: boolean;
17
- /** The field to use as the identity key. */
18
- idField?: keyof T;
19
- /** Determines if the clear button should be displayed in the dropdown. */
20
- showClearButton?: boolean;
21
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,11 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { GenericDropdown } from "../GenericDropdown";
3
- // This exports a function component called "CommandCellDropdown"
4
- // It takes in various props that are used to render a dropdown in a table cell
5
- export function CommandCellDropdown(props) {
6
- return (_jsx("td", { children: props.checkEditField && !props.isEditing && props.data.length ? (props.textFields
7
- .map((x) => props.data.find((y) => y[props.idField ? props.idField : "id"] === props.selectedId)[x])
8
- .join(props.separator || " ")) : (
9
- // If "props.checkEditField" is false or "props.isEditing" is true, render the GenericDropdownWithSearch component with the "props" passed to it
10
- _jsx(GenericDropdown, Object.assign({}, props))) }));
11
- }
@@ -1,3 +0,0 @@
1
- export declare function CommandCellPrice({ cost }: {
2
- cost: number;
3
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,10 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- export function CommandCellPrice({ cost }) {
3
- let formattedCost = new Intl.NumberFormat("en", {
4
- style: "currency",
5
- currency: "USD",
6
- minimumSignificantDigits: 2,
7
- maximumFractionDigits: 3,
8
- }).format(cost);
9
- return _jsx("td", Object.assign({ "data-testid": "price" }, { children: formattedCost }));
10
- }
@@ -1,7 +0,0 @@
1
- import { GridCellProps } from "@progress/kendo-react-grid";
2
- export declare function CommandCellSwitch({ props, changeFunction, }: {
3
- /** The GridCellProps object containing cell-related properties. */
4
- props: GridCellProps;
5
- /** The function to call when the switch value changes. */
6
- changeFunction: Function;
7
- }): import("react/jsx-runtime").JSX.Element;
@@ -1,5 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Switch } from "@progress/kendo-react-inputs";
3
- export function CommandCellSwitch({ props, changeFunction, }) {
4
- return (_jsx("td", Object.assign({ "data-testid": "switch" }, { children: props.dataItem.isEditing ? (_jsx(Switch, { onChange: () => changeFunction(), checked: props.dataItem[props.field] })) : (props.dataItem[props.field].toString()) })));
5
- }
package/index.js DELETED
@@ -1,10 +0,0 @@
1
- export { CommandCellCheckBox } from "./commandCell/CommandCellCheckbox";
2
- export { CommandCellDate } from "./commandCell/CommandCellDate";
3
- export { CommandCellDropdown } from "./commandCell/CommandCellDropdown";
4
- export { CommandCellDDWithoutId } from "./commandCell/CommandCellDDWithoutId";
5
- export { CommandCellPrice } from "./commandCell/CommandCellPrice";
6
- export { CommandCellSwitch } from "./commandCell/CommandCellSwitch";
7
- export { FilterCellDropdown } from "./FilterCellDropdown";
8
- export { ToolbarButton } from "./Toolbar";
9
- export { GenericDropdown } from "./GenericDropdown";
10
- export { MultiSelectDropdown } from "./MultiSelectDropdown";
File without changes