@paroicms/react-ui 0.5.4 → 0.5.6

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,22 @@
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
+ thClassName?: string;
10
+ tdClassName?: string;
11
+ }
3
12
  export interface DataTableProps<T> {
4
13
  value: T[];
5
14
  dataKey: keyof T & string;
15
+ columns: DataTableColumn<T>[];
6
16
  size?: "small" | "normal";
7
17
  loading?: boolean;
8
- children: ReactNode;
9
18
  className?: string;
19
+ tableClassName?: string;
10
20
  emptyMessage?: string;
11
21
  paginator?: boolean;
12
22
  rows?: number;
@@ -27,4 +37,4 @@ export interface DataTableProps<T> {
27
37
  rowClassName?: (row: T) => string | undefined;
28
38
  totalLabel?: string;
29
39
  }
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;
40
+ 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", col.thClassName), 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.tdClassName), 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.6",
4
4
  "description": "React UI toolkit for ParoiCMS.",
5
5
  "keywords": [
6
6
  "paroicms",
package/styles/Button.css CHANGED
@@ -13,12 +13,17 @@
13
13
  font-weight: var(--font-medium);
14
14
  line-height: 1;
15
15
  white-space: nowrap;
16
- text-decoration: none;
17
16
  cursor: pointer;
18
17
  border: none;
19
18
  border-radius: var(--radius);
20
19
  transition: all var(--transition);
21
20
 
21
+ &,
22
+ &:visited,
23
+ &:hover {
24
+ text-decoration: none;
25
+ }
26
+
22
27
  &:focus-visible {
23
28
  outline: 2px solid var(--color-primary);
24
29
  outline-offset: 2px;
@@ -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;
@@ -17,6 +25,7 @@
17
25
  padding: var(--space-3) var(--space-4);
18
26
  font-size: var(--text-xs);
19
27
  font-weight: var(--font-semibold);
28
+ vertical-align: middle;
20
29
  color: var(--color-text-muted);
21
30
  text-align: left;
22
31
  text-transform: uppercase;
@@ -81,15 +90,6 @@
81
90
  white-space: nowrap;
82
91
  }
83
92
 
84
- /* DataTable Wrapper & Loading */
85
- .PaDataTable-wrapper {
86
- position: relative;
87
-
88
- &.loading {
89
- min-height: 100px;
90
- }
91
- }
92
-
93
93
  .PaDataTable-overlay {
94
94
  position: absolute;
95
95
  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,
@@ -5,6 +5,7 @@
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  gap: var(--space-2);
8
+ width: 100%;
8
9
 
9
10
  &:not(:last-child) {
10
11
  margin-bottom: var(--space-4);
@@ -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
- }