jattac.libs.web.responsive-table 0.0.1 → 0.0.3

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.
package/README.md CHANGED
@@ -1,47 +1,83 @@
1
- # FormField React Component
1
+ # ResponsiveTable
2
2
 
3
- FormField is a powerful React component designed to streamline the creation of form fields with built-in support for validation, labels, hints, and optional indicators.
3
+ ResponsiveTable is a reusable React component that displays tabular data in a responsive layout.
4
4
 
5
- ## Installation
5
+ ## Features
6
6
 
7
- ```js
8
- npm install jattac.libs.web.form-field
9
- ```
7
+ - Handles mobile and desktop layouts
8
+ - Customizable columns
9
+ - Dynamic column definitions
10
+ - Card-style mobile view
11
+ - Generic types for flexible data
12
+
13
+ ## Usage
10
14
 
11
- ## Example
12
-
13
- ```js
14
- import React from 'react';
15
- import FormField from 'jattac.libs.web.form-field';
16
-
17
- const MyForm = () => {
18
- const validationErrors = [
19
- // Your validation errors here
20
- ];
21
-
22
- return (
23
- <form>
24
- <FormField
25
- label="Email"
26
- id="email"
27
- validationErrors={[{ key: 'email', errors: ['Invalid email address'] }]}
28
- optional={true}
29
- hint="We'll never share your email with anyone else."
30
- >
31
- <input type="email" />
32
- </FormField>
33
-
34
- {/* Add more FormField components for other form elements */}
35
- </form>
36
- );
37
- };
15
+ ```jsx
16
+ <ResponsiveTable columnDefinitions={columns} data={data} />
38
17
  ```
39
18
 
19
+ - 'columnDefinitions' defines an array of columns, which can be a simple configuration object or dynamic function
20
+ - 'data' is an array of data objects to display in rows
21
+
22
+ The component handles switching layout based on screen width to optimize for desktop and mobile.
23
+
24
+ ## Custom Columns
25
+
26
+ Columns can be configured using the 'IResponsiveTableColumnDefinition' interface.
27
+
28
+ Some key configuration options:
29
+
30
+ - 'displayLabel': Header label
31
+ - 'dataKey': Maps column to data property
32
+ - 'cellRenderer': Renders cell value
33
+
34
+ See docs for more details on customization.
35
+
36
+ ## Dynamic Columns
37
+
38
+ Column definitions can also be a function allowing dynamic configurations per row.
39
+
40
+ ## Styling
41
+
42
+ Use CSS modules or global styles to customize visual layout:
43
+
44
+ - '.responsiveTable': Root table
45
+ - '.card': Mobile card containers
46
+
40
47
  ## Props
41
48
 
42
- - **label** (required): The label for the form field.
43
- - **id** (required): A unique identifier for the form field.
44
- - **children** (required): The content of the form field, typically an input element.
45
- - **validationErrors**: An array of validation errors for the form field.
46
- - **optional**: A boolean indicating whether the field is optional. Defaults to false.
47
- - **hint**: Additional information or guidance for the form field.
49
+ Prop definitions provide detailed specification of component contract.
50
+
51
+ ### IProps
52
+
53
+ ```ts
54
+ interface IProps<TData> {
55
+ /** Column definitions */
56
+ columnDefinitions: ColumnDefinition<TData>[];
57
+
58
+ /** Table data rows */
59
+ data: TData[];
60
+
61
+ /** Optional styling */
62
+ className?: string;
63
+
64
+ /** row click handler */
65
+ onRowClicked?: (row: TData) => void;
66
+ }
67
+ ```
68
+
69
+ ```ts
70
+ type ColumnDefinition<TData> =
71
+ | IResponsiveTableColumnDefinition<TData>
72
+ | ((rowData: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>);
73
+ ```
74
+
75
+ ```ts
76
+ interface IResponsiveTableColumnDefinition<TData> {
77
+ displayLabel: string | ReactNode;
78
+
79
+ dataKey?: keyof TData;
80
+
81
+ cellRenderer: (rowData: TData) => ReactNode;
82
+ }
83
+ ```
@@ -1,19 +1,23 @@
1
- import React, { Component } from "react";
2
- import IResponsiveTableColumnDefinition from "../Data/IResponsiveTableColumnDefinition";
1
+ import React, { Component, ReactNode } from 'react';
2
+ import IResponsiveTableColumnDefinition from '../Data/IResponsiveTableColumnDefinition';
3
3
  type ColumnDefinition<TData> = IResponsiveTableColumnDefinition<TData> | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>);
4
4
  interface IProps<TData> {
5
5
  columnDefinitions: ColumnDefinition<TData>[];
6
6
  data: TData[];
7
+ noDataComponent?: ReactNode;
7
8
  }
8
9
  interface IState {
9
10
  isMobile: boolean;
10
11
  }
11
12
  declare class ResponsiveTable<TData> extends Component<IProps<TData>, IState> {
12
13
  constructor(props: IProps<TData>);
14
+ private get data();
15
+ private get hasData();
16
+ private get noDataComponent();
13
17
  componentDidMount(): void;
14
18
  componentWillUnmount(): void;
15
19
  handleResize: () => void;
16
20
  private getColumnDefinition;
17
- render(): React.JSX.Element;
21
+ render(): string | number | boolean | Iterable<React.ReactNode> | React.JSX.Element | null | undefined;
18
22
  }
19
23
  export default ResponsiveTable;
package/dist/index.js CHANGED
@@ -29,8 +29,8 @@ function styleInject(css, ref) {
29
29
  }
30
30
  }
31
31
 
32
- var css_248z = ".ResponsiveTable-module_card__b-U2v {\n border: 1px solid #ccc;\n margin-bottom: 10px;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);\n}\n\n.ResponsiveTable-module_card-header__Ttk51 {\n background-color: #f0f0f0;\n padding: 10px;\n font-weight: bold;\n}\n\n.ResponsiveTable-module_card-body__XIy0h {\n padding: 10px;\n}\n\n/* Apply styles to the table with the specific class 'custom-table' */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 20px;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od thead {\n position: sticky;\n}\n\n/* Style the table header */\n.ResponsiveTable-module_responsiveTable__4y-Od th,\n.ResponsiveTable-module_responsiveTable__4y-Od td {\n padding: 12px;\n text-align: left;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od th {\n background-color: #f2f2f2;\n}\n\n/* Alternate row colors */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(even) {\n background-color: #f9f9f9;\n}\n\n/* Change background color on hover */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:hover {\n background-color: #d9edf7;\n}\n\n.ResponsiveTable-module_tableContainer__VjWjH {\n overflow-x: auto;\n margin-bottom: 20px;\n}\n";
33
- var styles = {"card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-body":"ResponsiveTable-module_card-body__XIy0h","responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","tableContainer":"ResponsiveTable-module_tableContainer__VjWjH"};
32
+ var css_248z = ".ResponsiveTable-module_card__b-U2v {\n border: 1px solid #ccc;\n margin-bottom: 10px;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);\n}\n\n.ResponsiveTable-module_card-header__Ttk51 {\n background-color: #f0f0f0;\n padding: 10px;\n font-weight: bold;\n}\n\n.ResponsiveTable-module_card-body__XIy0h {\n padding: 10px;\n}\n\n/* Apply styles to the table with the specific class 'custom-table' */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n width: 100%;\n border-collapse: collapse;\n margin-bottom: 20px;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od thead {\n position: sticky;\n}\n\n/* Style the table header */\n.ResponsiveTable-module_responsiveTable__4y-Od th,\n.ResponsiveTable-module_responsiveTable__4y-Od td {\n padding: 12px;\n text-align: left;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od th {\n background-color: #f2f2f2;\n}\n\n/* Alternate row colors */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(even) {\n background-color: #f9f9f9;\n}\n\n/* Change background color on hover */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:hover {\n background-color: #d9edf7;\n}\n\n.ResponsiveTable-module_tableContainer__VjWjH {\n overflow-x: auto;\n margin-bottom: 20px;\n}\n\n.ResponsiveTable-module_noData__IpwNq {\n text-align: center;\n font-weight: bold;\n color: #999;\n padding: 20px;\n}\n";
33
+ var styles = {"card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-body":"ResponsiveTable-module_card-body__XIy0h","responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","tableContainer":"ResponsiveTable-module_tableContainer__VjWjH","noData":"ResponsiveTable-module_noData__IpwNq"};
34
34
  styleInject(css_248z);
35
35
 
36
36
  // Class component
@@ -46,25 +46,40 @@ class ResponsiveTable extends React.Component {
46
46
  isMobile: false,
47
47
  };
48
48
  }
49
+ get data() {
50
+ if (Array.isArray(this.props.data) && this.props.data.length === 0) {
51
+ return this.props.data;
52
+ }
53
+ else {
54
+ return [];
55
+ }
56
+ }
57
+ get hasData() {
58
+ return this.data.length > 0;
59
+ }
60
+ get noDataComponent() {
61
+ return this.props.noDataComponent || React.createElement("div", { className: styles.noData }, "No data");
62
+ }
49
63
  componentDidMount() {
50
64
  this.setState(() => {
51
65
  return { isMobile: window.innerWidth <= 600 };
52
66
  });
53
- window.addEventListener("resize", this.handleResize);
67
+ window.addEventListener('resize', this.handleResize);
54
68
  }
55
69
  componentWillUnmount() {
56
- window.removeEventListener("resize", this.handleResize);
70
+ window.removeEventListener('resize', this.handleResize);
57
71
  }
58
72
  getColumnDefinition(columnDefinition, rowIndex) {
59
- return columnDefinition instanceof Function
60
- ? columnDefinition(this.props.data[0], rowIndex)
61
- : columnDefinition;
73
+ return columnDefinition instanceof Function ? columnDefinition(this.props.data[0], rowIndex) : columnDefinition;
62
74
  }
63
75
  render() {
76
+ if (!this.hasData) {
77
+ return this.noDataComponent;
78
+ }
64
79
  if (this.state.isMobile) {
65
- return (React.createElement("div", null, this.props.data.map((row, rowIndex) => (React.createElement("div", { key: rowIndex, className: styles["card"] },
66
- React.createElement("div", { className: styles["card-header"] }, " "),
67
- React.createElement("div", { className: styles["card-body"] }, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
80
+ return (React.createElement("div", null, this.props.data.map((row, rowIndex) => (React.createElement("div", { key: rowIndex, className: styles['card'] },
81
+ React.createElement("div", { className: styles['card-header'] }, " "),
82
+ React.createElement("div", { className: styles['card-body'] }, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
68
83
  const colDef = this.getColumnDefinition(columnDefinition, rowIndex);
69
84
  return (React.createElement("div", { key: colIndex },
70
85
  React.createElement("p", null,
@@ -76,7 +91,7 @@ class ResponsiveTable extends React.Component {
76
91
  })))))));
77
92
  }
78
93
  return (React.createElement("div", { className: styles.tableContainer },
79
- React.createElement("table", { className: styles["responsiveTable"] },
94
+ React.createElement("table", { className: styles['responsiveTable'] },
80
95
  React.createElement("thead", null,
81
96
  React.createElement("tr", null, this.props.columnDefinitions.map((columnDefinition, colIndex) => (React.createElement("th", { key: colIndex }, this.getColumnDefinition(columnDefinition, 0).displayLabel))))),
82
97
  React.createElement("tbody", null, this.props.data.map((row, rowIndex) => (React.createElement("tr", { key: rowIndex }, this.props.columnDefinitions.map((columnDefinition, colIndex) => (React.createElement("td", { key: colIndex }, this.getColumnDefinition(columnDefinition, rowIndex).cellRenderer(row)))))))))));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../node_modules/style-inject/dist/style-inject.es.js","../src/UI/ResponsiveTable.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n",null],"names":["Component"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.js","sources":["../node_modules/style-inject/dist/style-inject.es.js","../src/UI/ResponsiveTable.tsx"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n",null],"names":["Component"],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jattac.libs.web.responsive-table",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
@@ -52,3 +52,10 @@
52
52
  overflow-x: auto;
53
53
  margin-bottom: 20px;
54
54
  }
55
+
56
+ .noData {
57
+ text-align: center;
58
+ font-weight: bold;
59
+ color: #999;
60
+ padding: 20px;
61
+ }
@@ -1,16 +1,14 @@
1
- import React, { Component } from "react";
2
- import styles from "../Styles/ResponsiveTable.module.css";
3
- import IResponsiveTableColumnDefinition from "../Data/IResponsiveTableColumnDefinition";
1
+ import React, { Component, ReactNode } from 'react';
2
+ import styles from '../Styles/ResponsiveTable.module.css';
3
+ import IResponsiveTableColumnDefinition from '../Data/IResponsiveTableColumnDefinition';
4
4
 
5
5
  type ColumnDefinition<TData> =
6
6
  | IResponsiveTableColumnDefinition<TData>
7
- | ((
8
- data: TData,
9
- rowIndex?: number
10
- ) => IResponsiveTableColumnDefinition<TData>);
7
+ | ((data: TData, rowIndex?: number) => IResponsiveTableColumnDefinition<TData>);
11
8
  interface IProps<TData> {
12
9
  columnDefinitions: ColumnDefinition<TData>[];
13
10
  data: TData[];
11
+ noDataComponent?: ReactNode;
14
12
  }
15
13
 
16
14
  interface IState {
@@ -26,16 +24,32 @@ class ResponsiveTable<TData> extends Component<IProps<TData>, IState> {
26
24
  };
27
25
  }
28
26
 
27
+ private get data(): TData[] {
28
+ if (Array.isArray(this.props.data) && this.props.data.length === 0) {
29
+ return this.props.data;
30
+ } else {
31
+ return [];
32
+ }
33
+ }
34
+
35
+ private get hasData(): boolean {
36
+ return this.data.length > 0;
37
+ }
38
+
39
+ private get noDataComponent(): ReactNode {
40
+ return this.props.noDataComponent || <div className={styles.noData}>No data</div>;
41
+ }
42
+
29
43
  componentDidMount(): void {
30
44
  this.setState(() => {
31
45
  return { isMobile: window.innerWidth <= 600 };
32
46
  });
33
47
 
34
- window.addEventListener("resize", this.handleResize);
48
+ window.addEventListener('resize', this.handleResize);
35
49
  }
36
50
 
37
51
  componentWillUnmount(): void {
38
- window.removeEventListener("resize", this.handleResize);
52
+ window.removeEventListener('resize', this.handleResize);
39
53
  }
40
54
 
41
55
  handleResize = (): void => {
@@ -46,39 +60,32 @@ class ResponsiveTable<TData> extends Component<IProps<TData>, IState> {
46
60
 
47
61
  private getColumnDefinition(
48
62
  columnDefinition: ColumnDefinition<TData>,
49
- rowIndex: number
63
+ rowIndex: number,
50
64
  ): IResponsiveTableColumnDefinition<TData> {
51
- return columnDefinition instanceof Function
52
- ? columnDefinition(this.props.data[0], rowIndex)
53
- : columnDefinition;
65
+ return columnDefinition instanceof Function ? columnDefinition(this.props.data[0], rowIndex) : columnDefinition;
54
66
  }
55
67
 
56
68
  render() {
69
+ if (!this.hasData) {
70
+ return this.noDataComponent;
71
+ }
57
72
  if (this.state.isMobile) {
58
73
  return (
59
74
  <div>
60
75
  {this.props.data.map((row, rowIndex) => (
61
- <div key={rowIndex} className={styles["card"]}>
62
- <div className={styles["card-header"]}> </div>
63
- <div className={styles["card-body"]}>
64
- {this.props.columnDefinitions.map(
65
- (columnDefinition, colIndex) => {
66
- const colDef = this.getColumnDefinition(
67
- columnDefinition,
68
- rowIndex
69
- );
70
- return (
71
- <div key={colIndex}>
72
- <p>
73
- <span className="font-bold">
74
- {colDef.displayLabel}:
75
- </span>{" "}
76
- {colDef.cellRenderer(row)}
77
- </p>
78
- </div>
79
- );
80
- }
81
- )}
76
+ <div key={rowIndex} className={styles['card']}>
77
+ <div className={styles['card-header']}> </div>
78
+ <div className={styles['card-body']}>
79
+ {this.props.columnDefinitions.map((columnDefinition, colIndex) => {
80
+ const colDef = this.getColumnDefinition(columnDefinition, rowIndex);
81
+ return (
82
+ <div key={colIndex}>
83
+ <p>
84
+ <span className="font-bold">{colDef.displayLabel}:</span> {colDef.cellRenderer(row)}
85
+ </p>
86
+ </div>
87
+ );
88
+ })}
82
89
  </div>
83
90
  </div>
84
91
  ))}
@@ -88,31 +95,20 @@ class ResponsiveTable<TData> extends Component<IProps<TData>, IState> {
88
95
 
89
96
  return (
90
97
  <div className={styles.tableContainer}>
91
- <table className={styles["responsiveTable"]}>
98
+ <table className={styles['responsiveTable']}>
92
99
  <thead>
93
100
  <tr>
94
- {this.props.columnDefinitions.map(
95
- (columnDefinition, colIndex) => (
96
- <th key={colIndex}>
97
- {this.getColumnDefinition(columnDefinition, 0).displayLabel}
98
- </th>
99
- )
100
- )}
101
+ {this.props.columnDefinitions.map((columnDefinition, colIndex) => (
102
+ <th key={colIndex}>{this.getColumnDefinition(columnDefinition, 0).displayLabel}</th>
103
+ ))}
101
104
  </tr>
102
105
  </thead>
103
106
  <tbody>
104
107
  {this.props.data.map((row, rowIndex) => (
105
108
  <tr key={rowIndex}>
106
- {this.props.columnDefinitions.map(
107
- (columnDefinition, colIndex) => (
108
- <td key={colIndex}>
109
- {this.getColumnDefinition(
110
- columnDefinition,
111
- rowIndex
112
- ).cellRenderer(row)}
113
- </td>
114
- )
115
- )}
109
+ {this.props.columnDefinitions.map((columnDefinition, colIndex) => (
110
+ <td key={colIndex}>{this.getColumnDefinition(columnDefinition, rowIndex).cellRenderer(row)}</td>
111
+ ))}
116
112
  </tr>
117
113
  ))}
118
114
  </tbody>