@paroicms/react-ui 0.5.4 → 0.5.5

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.
@@ -1,12 +1,21 @@
1
1
  import "../styles/DataTable.css";
2
- import { type ReactNode } from "react";
2
+ import type { CSSProperties, ReactNode } from "react";
3
+ export interface DataTableColumn<T = unknown> {
4
+ field?: keyof T & string;
5
+ header?: string;
6
+ body?: (rowData: T) => ReactNode;
7
+ style?: CSSProperties;
8
+ sortable?: boolean;
9
+ bodyClassName?: string;
10
+ }
3
11
  export interface DataTableProps<T> {
4
12
  value: T[];
5
13
  dataKey: keyof T & string;
14
+ columns: DataTableColumn<T>[];
6
15
  size?: "small" | "normal";
7
16
  loading?: boolean;
8
- children: ReactNode;
9
17
  className?: string;
18
+ tableClassName?: string;
10
19
  emptyMessage?: string;
11
20
  paginator?: boolean;
12
21
  rows?: number;
@@ -27,4 +36,4 @@ export interface DataTableProps<T> {
27
36
  rowClassName?: (row: T) => string | undefined;
28
37
  totalLabel?: string;
29
38
  }
30
- export declare function DataTable<T extends object>({ value, dataKey, size, loading, children, className, emptyMessage, paginator, rows, totalRecords, first, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
39
+ export declare function DataTable<T extends object>({ value, dataKey, columns, size, loading, className, tableClassName, emptyMessage, paginator, rows, totalRecords, first, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
package/dist/DataTable.js CHANGED
@@ -2,17 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import "../styles/DataTable.css";
3
3
  import { clsx } from "clsx";
4
4
  import { ArrowDown, ArrowUp, ChevronLeft, ChevronRight, ChevronsUpDown } from "lucide-react";
5
- import { Children, isValidElement } from "react";
6
5
  import { Select } from "./Select.js";
7
6
  import { Spinner } from "./Spinner.js";
8
- export function DataTable({ value, dataKey, size, loading, children, className, emptyMessage = "No data available", paginator, rows = 10, totalRecords, first = 0, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }) {
9
- // Extract column definitions from children
10
- const columns = [];
11
- Children.forEach(children, (child) => {
12
- if (isValidElement(child) && child.props) {
13
- columns.push(child.props);
14
- }
15
- });
7
+ export function DataTable({ value, dataKey, columns, size, loading, className, tableClassName, emptyMessage = "No data available", paginator, rows = 10, totalRecords, first = 0, onPage, rowsPerPageOptions, sortField, sortOrder, onSort, onRowClick, rowClassName, totalLabel, }) {
16
8
  const total = totalRecords ?? value.length;
17
9
  const pageCount = Math.ceil(total / rows);
18
10
  const currentPage = Math.floor(first / rows) + 1;
@@ -22,5 +14,5 @@ export function DataTable({ value, dataKey, size, loading, children, className,
22
14
  const newOrder = sortField === field && sortOrder === 1 ? -1 : 1;
23
15
  onSort({ field, order: newOrder });
24
16
  };
25
- return (_jsxs("div", { className: clsx("PaDataTable-wrapper", loading && "loading"), children: [loading && (_jsx("div", { className: "PaDataTable-overlay", children: _jsx(Spinner, {}) })), _jsx("div", { className: "PaDataTable-scrollable", children: _jsxs("table", { className: clsx("PaDataTable", size, className), children: [_jsx("thead", { className: "PaDataTable-header", children: _jsx("tr", { children: columns.map((col, i) => (_jsx("th", { className: clsx("PaDataTable-headerCell", col.sortable && "sortable"), style: col.style, onClick: col.sortable ? () => handleSort(col.field) : undefined, tabIndex: 0, children: _jsxs("span", { className: "PaDataTable-headerContent", children: [col.header, col.sortable && (_jsx("span", { className: "PaDataTable-sortIcon", children: col.field === sortField ? (sortOrder === 1 ? (_jsx(ArrowDown, { size: 14 })) : (_jsx(ArrowUp, { size: 14 }))) : (_jsx(ChevronsUpDown, { size: 14 })) }))] }) }, col.field ?? i))) }) }), _jsx("tbody", { children: value.length === 0 ? (_jsx("tr", { className: "PaDataTable-emptyRow", children: _jsx("td", { colSpan: columns.length, className: "PaDataTable-emptyCell", children: emptyMessage }) })) : (value.map((row) => (_jsx("tr", { className: clsx("PaDataTable-row", onRowClick && "clickable", rowClassName?.(row)), onClick: onRowClick ? (e) => onRowClick(row, e) : undefined, children: columns.map((col, i) => (_jsx("td", { className: clsx("PaDataTable-cell", col.bodyClassName), style: col.style, children: col.body ? col.body(row) : col.field ? String(row[col.field] ?? "") : null }, col.field ?? i))) }, String(row[dataKey]))))) })] }) }), paginator && onPage && pageCount > 1 && (_jsxs("div", { className: "PaDataTable-footer", children: [_jsxs("span", { className: "PaDataTable-totalCount", children: [total, " ", totalLabel ?? "items"] }), _jsxs("div", { className: "PaDataTable-pagination", children: [_jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage <= 1, onClick: () => onPage({ first: first - rows, rows }), children: _jsx(ChevronLeft, { size: 16 }) }), _jsxs("span", { className: "PaDataTable-paginationText", children: ["Page ", currentPage, " of ", pageCount] }), _jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage >= pageCount, onClick: () => onPage({ first: first + rows, rows }), children: _jsx(ChevronRight, { size: 16 }) }), rowsPerPageOptions && rowsPerPageOptions.length > 0 && (_jsx(Select, { className: "PaDataTable-rowsPerPage", value: String(rows), options: rowsPerPageOptions.map((n) => ({ label: String(n), value: String(n) })), onChange: (val) => onPage({ first: 0, rows: Number(val) }) }))] })] }))] }));
17
+ return (_jsxs("div", { className: clsx("PaDataTable", { loading }, className), children: [loading && (_jsx("div", { className: "PaDataTable-overlay", children: _jsx(Spinner, {}) })), _jsx("div", { className: "PaDataTable-scrollable", children: _jsxs("table", { className: clsx("PaDataTable-table", size, tableClassName), children: [_jsx("thead", { className: "PaDataTable-header", children: _jsx("tr", { children: columns.map((col, i) => (_jsx("th", { className: clsx("PaDataTable-headerCell", col.sortable && "sortable"), style: col.style, onClick: col.sortable ? () => handleSort(col.field) : undefined, tabIndex: 0, children: _jsxs("span", { className: "PaDataTable-headerContent", children: [col.header, col.sortable && (_jsx("span", { className: "PaDataTable-sortIcon", children: col.field === sortField ? (sortOrder === 1 ? (_jsx(ArrowDown, { size: 14 })) : (_jsx(ArrowUp, { size: 14 }))) : (_jsx(ChevronsUpDown, { size: 14 })) }))] }) }, col.field ?? i))) }) }), _jsx("tbody", { children: value.length === 0 ? (_jsx("tr", { className: "PaDataTable-emptyRow", children: _jsx("td", { colSpan: columns.length, className: "PaDataTable-emptyCell", children: emptyMessage }) })) : (value.map((row) => (_jsx("tr", { className: clsx("PaDataTable-row", onRowClick && "clickable", rowClassName?.(row)), onClick: onRowClick ? (e) => onRowClick(row, e) : undefined, children: columns.map((col, i) => (_jsx("td", { className: clsx("PaDataTable-cell", col.bodyClassName), style: col.style, children: col.body ? col.body(row) : col.field ? String(row[col.field] ?? "") : null }, col.field ?? i))) }, String(row[dataKey]))))) })] }) }), paginator && onPage && pageCount > 1 && (_jsxs("div", { className: "PaDataTable-footer", children: [_jsxs("span", { className: "PaDataTable-totalCount", children: [total, " ", totalLabel ?? "items"] }), _jsxs("div", { className: "PaDataTable-pagination", children: [_jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage <= 1, onClick: () => onPage({ first: first - rows, rows }), children: _jsx(ChevronLeft, { size: 16 }) }), _jsxs("span", { className: "PaDataTable-paginationText", children: ["Page ", currentPage, " of ", pageCount] }), _jsx("button", { type: "button", className: "PaDataTable-paginationBtn", disabled: currentPage >= pageCount, onClick: () => onPage({ first: first + rows, rows }), children: _jsx(ChevronRight, { size: 16 }) }), rowsPerPageOptions && rowsPerPageOptions.length > 0 && (_jsx(Select, { className: "PaDataTable-rowsPerPage", value: String(rows), options: rowsPerPageOptions.map((n) => ({ label: String(n), value: String(n) })), onChange: (val) => onPage({ first: 0, rows: Number(val) }) }))] })] }))] }));
26
18
  }
package/dist/index.d.ts CHANGED
@@ -17,7 +17,6 @@ export * from "./Alert.js";
17
17
  export * from "./Badge.js";
18
18
  export * from "./Card.js";
19
19
  export * from "./Chip.js";
20
- export * from "./Column.js";
21
20
  export * from "./DataTable.js";
22
21
  export * from "./Breadcrumb.js";
23
22
  export * from "./MenuItem.js";
package/dist/index.js CHANGED
@@ -20,7 +20,6 @@ export * from "./Alert.js";
20
20
  export * from "./Badge.js";
21
21
  export * from "./Card.js";
22
22
  export * from "./Chip.js";
23
- export * from "./Column.js";
24
23
  export * from "./DataTable.js";
25
24
  // Navigation
26
25
  export * from "./Breadcrumb.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paroicms/react-ui",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "React UI toolkit for ParoiCMS.",
5
5
  "keywords": [
6
6
  "paroicms",
@@ -2,6 +2,14 @@
2
2
  Data Table
3
3
  ======================================== */
4
4
  .PaDataTable {
5
+ position: relative;
6
+
7
+ &.loading {
8
+ min-height: 100px;
9
+ }
10
+ }
11
+
12
+ .PaDataTable-table {
5
13
  overflow: hidden;
6
14
  border-spacing: 0;
7
15
  border-collapse: separate;
@@ -81,15 +89,6 @@
81
89
  white-space: nowrap;
82
90
  }
83
91
 
84
- /* DataTable Wrapper & Loading */
85
- .PaDataTable-wrapper {
86
- position: relative;
87
-
88
- &.loading {
89
- min-height: 100px;
90
- }
91
- }
92
-
93
92
  .PaDataTable-overlay {
94
93
  position: absolute;
95
94
  inset: 0;
package/styles/Dialog.css CHANGED
@@ -82,7 +82,7 @@
82
82
  }
83
83
 
84
84
  .PaDialog-content {
85
- flex: 1;
85
+ flex: 1 1 auto; /* Safari: use content-based flex-basis instead of 0 */
86
86
  padding: var(--space-5);
87
87
  overflow-y: auto;
88
88
  }
@@ -60,6 +60,7 @@
60
60
  .PaTextField-iconWrapper {
61
61
  position: relative;
62
62
  display: flex;
63
+ align-self: flex-start;
63
64
 
64
65
  .PaTextInput {
65
66
  padding-left: var(--space-10);
@@ -10,6 +10,7 @@
10
10
  .PaPasswordInput-inputWrapper {
11
11
  position: relative;
12
12
  display: flex;
13
+ align-self: flex-start;
13
14
 
14
15
  &.error .PaPasswordInput-input {
15
16
  border-color: var(--color-danger);
package/styles/Select.css CHANGED
@@ -13,6 +13,8 @@
13
13
 
14
14
  .PaSelectField-wrapper {
15
15
  position: relative;
16
+ display: flex;
17
+ align-self: flex-start;
16
18
  }
17
19
 
18
20
  ._paForm select,
@@ -12,5 +12,5 @@
12
12
  @import "./tokens.css" layer(tokens);
13
13
  @import "./base.css" layer(base);
14
14
  @import "./common.css" layer(common);
15
- @import "./margins.css";
15
+ @import "./utilities.css";
16
16
  @import "./field.css";
@@ -1,119 +1,146 @@
1
+ .PaButtonBar {
2
+ display: flex;
3
+ flex-wrap: wrap;
4
+ gap: 8px;
5
+
6
+ &.alignRight {
7
+ justify-content: end;
8
+ }
9
+
10
+ &.spaceBetween {
11
+ justify-content: space-between;
12
+ width: 100%;
13
+
14
+ @media (max-width: 400px) {
15
+ justify-content: center;
16
+ }
17
+ }
18
+ }
19
+
20
+ .PaFullW {
21
+ width: 100% !important;
22
+ }
23
+
24
+ .PaFullH {
25
+ height: 100% !important;
26
+ }
27
+
1
28
  /* ========================================
2
29
  Margin Utilities
3
30
  ======================================== */
4
31
 
5
32
  /* Margin Top */
6
- .Mt1 {
33
+ .PaMt1 {
7
34
  margin-top: var(--space-1);
8
35
  }
9
- .Mt2 {
36
+ .PaMt2 {
10
37
  margin-top: var(--space-2);
11
38
  }
12
- .Mt3 {
39
+ .PaMt3 {
13
40
  margin-top: var(--space-3);
14
41
  }
15
- .Mt4 {
42
+ .PaMt4 {
16
43
  margin-top: var(--space-4);
17
44
  }
18
- .Mt5 {
45
+ .PaMt5 {
19
46
  margin-top: var(--space-5);
20
47
  }
21
- .Mt6 {
48
+ .PaMt6 {
22
49
  margin-top: var(--space-6);
23
50
  }
24
- .Mt8 {
51
+ .PaMt8 {
25
52
  margin-top: var(--space-8);
26
53
  }
27
- .Mt10 {
54
+ .PaMt10 {
28
55
  margin-top: var(--space-10);
29
56
  }
30
- .Mt12 {
57
+ .PaMt12 {
31
58
  margin-top: var(--space-12);
32
59
  }
33
60
 
34
61
  /* Margin Bottom */
35
- .Mb1 {
62
+ .PaMb1 {
36
63
  margin-bottom: var(--space-1);
37
64
  }
38
- .Mb2 {
65
+ .PaMb2 {
39
66
  margin-bottom: var(--space-2);
40
67
  }
41
- .Mb3 {
68
+ .PaMb3 {
42
69
  margin-bottom: var(--space-3);
43
70
  }
44
- .Mb4 {
71
+ .PaMb4 {
45
72
  margin-bottom: var(--space-4);
46
73
  }
47
- .Mb5 {
74
+ .PaMb5 {
48
75
  margin-bottom: var(--space-5);
49
76
  }
50
- .Mb6 {
77
+ .PaMb6 {
51
78
  margin-bottom: var(--space-6);
52
79
  }
53
- .Mb8 {
80
+ .PaMb8 {
54
81
  margin-bottom: var(--space-8);
55
82
  }
56
- .Mb10 {
83
+ .PaMb10 {
57
84
  margin-bottom: var(--space-10);
58
85
  }
59
- .Mb12 {
86
+ .PaMb12 {
60
87
  margin-bottom: var(--space-12);
61
88
  }
62
89
 
63
90
  /* Margin Left */
64
- .Ml1 {
91
+ .PaMl1 {
65
92
  margin-left: var(--space-1);
66
93
  }
67
- .Ml2 {
94
+ .PaMl2 {
68
95
  margin-left: var(--space-2);
69
96
  }
70
- .Ml3 {
97
+ .PaMl3 {
71
98
  margin-left: var(--space-3);
72
99
  }
73
- .Ml4 {
100
+ .PaMl4 {
74
101
  margin-left: var(--space-4);
75
102
  }
76
- .Ml5 {
103
+ .PaMl5 {
77
104
  margin-left: var(--space-5);
78
105
  }
79
- .Ml6 {
106
+ .PaMl6 {
80
107
  margin-left: var(--space-6);
81
108
  }
82
- .Ml8 {
109
+ .PaMl8 {
83
110
  margin-left: var(--space-8);
84
111
  }
85
- .Ml10 {
112
+ .PaMl10 {
86
113
  margin-left: var(--space-10);
87
114
  }
88
- .Ml12 {
115
+ .PaMl12 {
89
116
  margin-left: var(--space-12);
90
117
  }
91
118
 
92
119
  /* Margin Right */
93
- .Mr1 {
120
+ .PaMr1 {
94
121
  margin-right: var(--space-1);
95
122
  }
96
- .Mr2 {
123
+ .PaMr2 {
97
124
  margin-right: var(--space-2);
98
125
  }
99
- .Mr3 {
126
+ .PaMr3 {
100
127
  margin-right: var(--space-3);
101
128
  }
102
- .Mr4 {
129
+ .PaMr4 {
103
130
  margin-right: var(--space-4);
104
131
  }
105
- .Mr5 {
132
+ .PaMr5 {
106
133
  margin-right: var(--space-5);
107
134
  }
108
- .Mr6 {
135
+ .PaMr6 {
109
136
  margin-right: var(--space-6);
110
137
  }
111
- .Mr8 {
138
+ .PaMr8 {
112
139
  margin-right: var(--space-8);
113
140
  }
114
- .Mr10 {
141
+ .PaMr10 {
115
142
  margin-right: var(--space-10);
116
143
  }
117
- .Mr12 {
144
+ .PaMr12 {
118
145
  margin-right: var(--space-12);
119
146
  }
package/dist/Column.d.ts DELETED
@@ -1,14 +0,0 @@
1
- import type { CSSProperties, ReactNode } from "react";
2
- export interface ColumnProps<T = unknown> {
3
- field?: keyof T & string;
4
- header?: string;
5
- body?: (rowData: T) => ReactNode;
6
- style?: CSSProperties;
7
- sortable?: boolean;
8
- bodyClassName?: string;
9
- }
10
- /**
11
- * Render-less component for column definition.
12
- * Used for configuration only - does not render anything.
13
- */
14
- export declare function Column<T>(_props: ColumnProps<T>): null;
package/dist/Column.js DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * Render-less component for column definition.
3
- * Used for configuration only - does not render anything.
4
- */
5
- export function Column(_props) {
6
- return null;
7
- }