@extrachill/components 0.2.0 → 1.0.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.
- package/README.md +19 -33
- package/dist/index.d.mts +91 -0
- package/dist/index.d.ts +88 -8
- package/dist/index.js +213 -10
- package/dist/index.mjs +183 -0
- package/package.json +23 -35
- package/{styles → src/styles}/components.scss +0 -54
- package/CHANGELOG.md +0 -14
- package/dist/DataTable.d.ts +0 -19
- package/dist/DataTable.d.ts.map +0 -1
- package/dist/DataTable.js +0 -27
- package/dist/Modal.d.ts +0 -10
- package/dist/Modal.d.ts.map +0 -1
- package/dist/Modal.js +0 -19
- package/dist/Pagination.d.ts +0 -8
- package/dist/Pagination.d.ts.map +0 -1
- package/dist/Pagination.js +0 -7
- package/dist/SearchBox.d.ts +0 -8
- package/dist/SearchBox.d.ts.map +0 -1
- package/dist/SearchBox.js +0 -23
- package/dist/Tabs.d.ts +0 -14
- package/dist/Tabs.d.ts.map +0 -1
- package/dist/Tabs.js +0 -11
- package/dist/index.d.ts.map +0 -1
- package/src/DataTable.tsx +0 -109
- package/src/Modal.tsx +0 -52
- package/src/Pagination.tsx +0 -41
- package/src/SearchBox.tsx +0 -56
- package/src/Tabs.tsx +0 -51
- package/src/index.tsx +0 -11
package/package.json
CHANGED
|
@@ -1,62 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@extrachill/components",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Shared React components for the Extra Chill Platform
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"types": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Shared React components for the Extra Chill Platform",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
"./package.json": "./package.json",
|
|
10
9
|
".": {
|
|
11
10
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
13
|
},
|
|
14
|
-
"./styles/components.scss": "./styles/components.scss",
|
|
15
|
-
"./styles/*": "./styles/*"
|
|
16
|
-
"./src": {
|
|
17
|
-
"types": "./src/index.tsx",
|
|
18
|
-
"default": "./src/index.tsx"
|
|
19
|
-
},
|
|
20
|
-
"./src/*": {
|
|
21
|
-
"types": "./src/*.tsx",
|
|
22
|
-
"default": "./src/*.tsx"
|
|
23
|
-
}
|
|
14
|
+
"./styles/components.scss": "./src/styles/components.scss",
|
|
15
|
+
"./styles/*": "./src/styles/*"
|
|
24
16
|
},
|
|
25
17
|
"files": [
|
|
26
|
-
"src",
|
|
27
18
|
"dist",
|
|
28
|
-
"styles"
|
|
29
|
-
"README.md",
|
|
30
|
-
"CHANGELOG.md"
|
|
19
|
+
"src/styles"
|
|
31
20
|
],
|
|
32
21
|
"scripts": {
|
|
33
|
-
"build": "
|
|
22
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --external react --external @wordpress/components --external @wordpress/element",
|
|
34
23
|
"typecheck": "tsc --noEmit",
|
|
35
24
|
"prepublishOnly": "npm run build"
|
|
36
25
|
},
|
|
37
|
-
"keywords": [
|
|
38
|
-
"extrachill",
|
|
39
|
-
"react",
|
|
40
|
-
"components",
|
|
41
|
-
"wordpress",
|
|
42
|
-
"design-system"
|
|
43
|
-
],
|
|
44
26
|
"author": "Chris Huber <hello@chubes.net>",
|
|
45
27
|
"license": "GPL-2.0+",
|
|
46
28
|
"repository": {
|
|
47
29
|
"type": "git",
|
|
48
30
|
"url": "https://github.com/Extra-Chill/extrachill-components.git"
|
|
49
31
|
},
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"
|
|
54
|
-
|
|
32
|
+
"keywords": [
|
|
33
|
+
"extrachill",
|
|
34
|
+
"react",
|
|
35
|
+
"components",
|
|
36
|
+
"wordpress"
|
|
37
|
+
],
|
|
55
38
|
"peerDependencies": {
|
|
39
|
+
"@wordpress/components": ">=28.0.0",
|
|
40
|
+
"@wordpress/element": ">=6.0.0",
|
|
56
41
|
"react": ">=18.0.0"
|
|
57
42
|
},
|
|
58
43
|
"devDependencies": {
|
|
59
44
|
"@types/react": "^18.0.0",
|
|
60
|
-
"
|
|
45
|
+
"@wordpress/components": "^28.0.0",
|
|
46
|
+
"@wordpress/element": "^6.0.0",
|
|
47
|
+
"tsup": "^8.0.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
61
49
|
}
|
|
62
50
|
}
|
|
@@ -74,60 +74,6 @@
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// Tabs — default styles for classPrefix="ec-tabs"
|
|
78
|
-
// Consumers with custom classPrefix (e.g. "ec-am") duplicate
|
|
79
|
-
// these rules under their own namespace in their block SCSS.
|
|
80
|
-
.ec-tabs__tabs {
|
|
81
|
-
display: inline-flex;
|
|
82
|
-
gap: var(--spacing-sm, 0.5rem);
|
|
83
|
-
flex-wrap: wrap;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
.ec-tabs__tab {
|
|
87
|
-
display: inline-flex;
|
|
88
|
-
align-items: center;
|
|
89
|
-
gap: var(--spacing-xs, 0.25rem);
|
|
90
|
-
border: 1px solid var(--border-color, #ddd);
|
|
91
|
-
background: var(--background-color, #fff);
|
|
92
|
-
padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
|
|
93
|
-
border-radius: var(--border-radius-sm, 4px);
|
|
94
|
-
cursor: pointer;
|
|
95
|
-
color: var(--text-color, #111);
|
|
96
|
-
font: inherit;
|
|
97
|
-
font-size: var(--font-size-base, 1rem);
|
|
98
|
-
font-weight: 600;
|
|
99
|
-
transition: background-color 0.2s, color 0.2s, border-color 0.2s;
|
|
100
|
-
|
|
101
|
-
&:hover {
|
|
102
|
-
background: var(--card-background, #f1f5f9);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
&.is-active {
|
|
106
|
-
border-color: var(--header-background, #1a1a1a);
|
|
107
|
-
background: var(--header-background, #1a1a1a);
|
|
108
|
-
color: var(--header-text-color, #fff);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.ec-tabs__tab-badge {
|
|
113
|
-
display: inline-flex;
|
|
114
|
-
align-items: center;
|
|
115
|
-
justify-content: center;
|
|
116
|
-
min-width: 20px;
|
|
117
|
-
height: 20px;
|
|
118
|
-
padding: 0 6px;
|
|
119
|
-
border-radius: 10px;
|
|
120
|
-
background: var(--accent, #53940b);
|
|
121
|
-
color: var(--background-color, #fff);
|
|
122
|
-
font-size: var(--font-size-xs, 0.625rem);
|
|
123
|
-
font-weight: 600;
|
|
124
|
-
|
|
125
|
-
.ec-tabs__tab.is-active & {
|
|
126
|
-
background: var(--background-color, #fff);
|
|
127
|
-
color: var(--header-background, #1a1a1a);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
77
|
// Badges (commonly used with tables)
|
|
132
78
|
.ec-badge {
|
|
133
79
|
display: inline-block;
|
package/CHANGELOG.md
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## [0.2.0] - 2026-03-25
|
|
4
|
-
|
|
5
|
-
### Changed
|
|
6
|
-
- Convert all components from JSX to TypeScript with exported prop interfaces
|
|
7
|
-
- Remove @wordpress/components and @wordpress/element peer dependencies — use plain React
|
|
8
|
-
- Add proper npm package config (exports, tsconfig, homeboy.json)
|
|
9
|
-
- Add DataTable, Pagination, SearchBox, Modal, Tabs components
|
|
10
|
-
|
|
11
|
-
## [0.1.0] - 2026-03-02
|
|
12
|
-
|
|
13
|
-
### Added
|
|
14
|
-
- Initial release with DataTable, Pagination, SearchBox, Modal components
|
package/dist/DataTable.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
export interface DataTableColumn<T = Record<string, unknown>> {
|
|
3
|
-
key: string;
|
|
4
|
-
label: string;
|
|
5
|
-
width?: string;
|
|
6
|
-
render?: (value: unknown, row: T) => ReactNode;
|
|
7
|
-
}
|
|
8
|
-
export interface DataTableProps<T = Record<string, unknown>> {
|
|
9
|
-
columns: DataTableColumn<T>[];
|
|
10
|
-
data: T[];
|
|
11
|
-
isLoading?: boolean;
|
|
12
|
-
selectable?: boolean;
|
|
13
|
-
selectedIds?: Array<string | number>;
|
|
14
|
-
onSelectChange?: (ids: Array<string | number>) => void;
|
|
15
|
-
emptyMessage?: string;
|
|
16
|
-
rowKey?: string;
|
|
17
|
-
}
|
|
18
|
-
export declare function DataTable<T extends Record<string, unknown>>({ columns, data, isLoading, selectable, selectedIds, onSelectChange, emptyMessage, rowKey, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
//# sourceMappingURL=DataTable.d.ts.map
|
package/dist/DataTable.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../src/DataTable.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAC5D,OAAO,EACP,IAAI,EACJ,SAAiB,EACjB,UAAkB,EAClB,WAAgB,EAChB,cAAyB,EACzB,YAA+B,EAC/B,MAAa,GACb,EAAE,cAAc,CAAC,CAAC,CAAC,2CA+EnB"}
|
package/dist/DataTable.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
export function DataTable({ columns, data, isLoading = false, selectable = false, selectedIds = [], onSelectChange = () => { }, emptyMessage = 'No data found.', rowKey = 'id', }) {
|
|
3
|
-
const allSelected = data.length > 0 && selectedIds.length === data.length;
|
|
4
|
-
const handleSelectAll = (e) => {
|
|
5
|
-
if (e.target.checked) {
|
|
6
|
-
onSelectChange(data.map((row) => row[rowKey]));
|
|
7
|
-
}
|
|
8
|
-
else {
|
|
9
|
-
onSelectChange([]);
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
const handleSelectRow = (id, checked) => {
|
|
13
|
-
if (checked) {
|
|
14
|
-
onSelectChange([...selectedIds, id]);
|
|
15
|
-
}
|
|
16
|
-
else {
|
|
17
|
-
onSelectChange(selectedIds.filter((sid) => sid !== id));
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
if (isLoading) {
|
|
21
|
-
return (_jsx("div", { className: "ec-data-table__loading", children: _jsx("span", { children: "Loading..." }) }));
|
|
22
|
-
}
|
|
23
|
-
if (data.length === 0) {
|
|
24
|
-
return (_jsx("div", { className: "ec-data-table__empty", children: _jsx("p", { children: emptyMessage }) }));
|
|
25
|
-
}
|
|
26
|
-
return (_jsxs("table", { className: "ec-data-table wp-list-table widefat fixed striped", children: [_jsx("thead", { children: _jsxs("tr", { children: [selectable && (_jsx("th", { className: "ec-data-table__check-column", children: _jsx("input", { type: "checkbox", checked: allSelected, onChange: handleSelectAll }) })), columns.map((col) => (_jsx("th", { style: col.width ? { width: col.width } : undefined, children: col.label }, col.key)))] }) }), _jsx("tbody", { children: data.map((row) => (_jsxs("tr", { children: [selectable && (_jsx("td", { className: "ec-data-table__check-column", children: _jsx("input", { type: "checkbox", checked: selectedIds.includes(row[rowKey]), onChange: (e) => handleSelectRow(row[rowKey], e.target.checked) }) })), columns.map((col) => (_jsx("td", { children: col.render ? col.render(row[col.key], row) : row[col.key] }, col.key)))] }, row[rowKey]))) })] }));
|
|
27
|
-
}
|
package/dist/Modal.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type ReactNode } from 'react';
|
|
2
|
-
export interface ModalProps {
|
|
3
|
-
title: string;
|
|
4
|
-
isOpen: boolean;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
children: ReactNode;
|
|
7
|
-
className?: string;
|
|
8
|
-
}
|
|
9
|
-
export declare function Modal({ title, isOpen, onClose, children, className, }: ModalProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
-
//# sourceMappingURL=Modal.d.ts.map
|
package/dist/Modal.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../src/Modal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE/D,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,KAAK,CAAC,EACrB,KAAK,EACL,MAAM,EACN,OAAO,EACP,QAAQ,EACR,SAAc,GACd,EAAE,UAAU,kDAmCZ"}
|
package/dist/Modal.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useCallback } from 'react';
|
|
3
|
-
export function Modal({ title, isOpen, onClose, children, className = '', }) {
|
|
4
|
-
const handleKeyDown = useCallback((e) => {
|
|
5
|
-
if (e.key === 'Escape') {
|
|
6
|
-
onClose();
|
|
7
|
-
}
|
|
8
|
-
}, [onClose]);
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
if (isOpen) {
|
|
11
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
12
|
-
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
13
|
-
}
|
|
14
|
-
}, [isOpen, handleKeyDown]);
|
|
15
|
-
if (!isOpen) {
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
return (_jsxs("div", { className: `ec-modal ${className}`, role: "dialog", "aria-label": title, children: [_jsx("div", { className: "ec-modal__backdrop", onClick: onClose, "aria-hidden": "true" }), _jsxs("div", { className: "ec-modal__content", children: [_jsxs("div", { className: "ec-modal__header", children: [_jsx("h2", { children: title }), _jsx("button", { type: "button", onClick: onClose, "aria-label": "Close", children: "\u00D7" })] }), _jsx("div", { className: "ec-modal__body", children: children })] })] }));
|
|
19
|
-
}
|
package/dist/Pagination.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface PaginationProps {
|
|
2
|
-
currentPage: number;
|
|
3
|
-
totalPages: number;
|
|
4
|
-
totalItems: number;
|
|
5
|
-
onPageChange: (page: number) => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function Pagination({ currentPage, totalPages, totalItems, onPageChange, }: PaginationProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
-
//# sourceMappingURL=Pagination.d.ts.map
|
package/dist/Pagination.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../src/Pagination.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,UAAU,CAAC,EAC1B,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,GACZ,EAAE,eAAe,kDA4BjB"}
|
package/dist/Pagination.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
export function Pagination({ currentPage, totalPages, totalItems, onPageChange, }) {
|
|
3
|
-
if (totalPages <= 1) {
|
|
4
|
-
return null;
|
|
5
|
-
}
|
|
6
|
-
return (_jsxs("div", { className: "ec-pagination", children: [_jsxs("span", { className: "ec-pagination__info", children: ["Page ", currentPage, " of ", totalPages, " (", totalItems, " items)"] }), _jsxs("div", { className: "ec-pagination__buttons", children: [_jsx("button", { type: "button", disabled: currentPage <= 1, onClick: () => onPageChange(currentPage - 1), children: "Previous" }), _jsx("button", { type: "button", disabled: currentPage >= totalPages, onClick: () => onPageChange(currentPage + 1), children: "Next" })] })] }));
|
|
7
|
-
}
|
package/dist/SearchBox.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface SearchBoxProps {
|
|
2
|
-
value?: string;
|
|
3
|
-
onSearch: (value: string) => void;
|
|
4
|
-
placeholder?: string;
|
|
5
|
-
onClear?: () => void;
|
|
6
|
-
}
|
|
7
|
-
export declare function SearchBox({ value, onSearch, placeholder, onClear, }: SearchBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
//# sourceMappingURL=SearchBox.d.ts.map
|
package/dist/SearchBox.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBox.d.ts","sourceRoot":"","sources":["../src/SearchBox.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EACzB,KAAU,EACV,QAAQ,EACR,WAAyB,EACzB,OAAO,GACP,EAAE,cAAc,2CAyChB"}
|
package/dist/SearchBox.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
export function SearchBox({ value = '', onSearch, placeholder = 'Search...', onClear, }) {
|
|
4
|
-
const [inputValue, setInputValue] = useState(value);
|
|
5
|
-
const handleSearch = () => {
|
|
6
|
-
onSearch(inputValue);
|
|
7
|
-
};
|
|
8
|
-
const handleClear = () => {
|
|
9
|
-
setInputValue('');
|
|
10
|
-
if (onClear) {
|
|
11
|
-
onClear();
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
onSearch('');
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
const handleKeyDown = (e) => {
|
|
18
|
-
if (e.key === 'Enter') {
|
|
19
|
-
handleSearch();
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
return (_jsxs("div", { className: "ec-search-box", children: [_jsx("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown }), _jsx("button", { type: "button", onClick: handleSearch, children: "Search" }), inputValue && (_jsx("button", { type: "button", onClick: handleClear, children: "Clear" }))] }));
|
|
23
|
-
}
|
package/dist/Tabs.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export interface TabItem {
|
|
2
|
-
id: string;
|
|
3
|
-
label: string;
|
|
4
|
-
badge?: number;
|
|
5
|
-
}
|
|
6
|
-
export interface TabsProps {
|
|
7
|
-
tabs: TabItem[];
|
|
8
|
-
active: string;
|
|
9
|
-
onChange: (id: string) => void;
|
|
10
|
-
classPrefix?: string;
|
|
11
|
-
className?: string;
|
|
12
|
-
}
|
|
13
|
-
export declare function Tabs({ tabs, active, onChange, classPrefix, className, }: TabsProps): import("react/jsx-runtime").JSX.Element | null;
|
|
14
|
-
//# sourceMappingURL=Tabs.d.ts.map
|
package/dist/Tabs.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../src/Tabs.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,IAAI,CAAC,EACpB,IAAS,EACT,MAAM,EACN,QAAQ,EACR,WAAuB,EACvB,SAAc,GACd,EAAE,SAAS,kDA8BX"}
|
package/dist/Tabs.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
export function Tabs({ tabs = [], active, onChange, classPrefix = 'ec-tabs', className = '', }) {
|
|
3
|
-
if (tabs.length === 0) {
|
|
4
|
-
return null;
|
|
5
|
-
}
|
|
6
|
-
const rootClass = [`${classPrefix}__tabs`, className].filter(Boolean).join(' ');
|
|
7
|
-
return (_jsx("div", { className: rootClass, role: "tablist", "aria-orientation": "horizontal", children: tabs.map((tab) => {
|
|
8
|
-
const isActive = active === tab.id;
|
|
9
|
-
return (_jsxs("button", { type: "button", role: "tab", "aria-selected": isActive, className: `${classPrefix}__tab${isActive ? ' is-active' : ''}`, onClick: () => onChange(tab.id), children: [tab.label, tab.badge != null && tab.badge > 0 && (_jsx("span", { className: `${classPrefix}__tab-badge`, children: tab.badge }))] }, tab.id));
|
|
10
|
-
}) }));
|
|
11
|
-
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC"}
|
package/src/DataTable.tsx
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface DataTableColumn<T = Record<string, unknown>> {
|
|
4
|
-
key: string;
|
|
5
|
-
label: string;
|
|
6
|
-
width?: string;
|
|
7
|
-
render?: (value: unknown, row: T) => ReactNode;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface DataTableProps<T = Record<string, unknown>> {
|
|
11
|
-
columns: DataTableColumn<T>[];
|
|
12
|
-
data: T[];
|
|
13
|
-
isLoading?: boolean;
|
|
14
|
-
selectable?: boolean;
|
|
15
|
-
selectedIds?: Array<string | number>;
|
|
16
|
-
onSelectChange?: (ids: Array<string | number>) => void;
|
|
17
|
-
emptyMessage?: string;
|
|
18
|
-
rowKey?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function DataTable<T extends Record<string, unknown>>({
|
|
22
|
-
columns,
|
|
23
|
-
data,
|
|
24
|
-
isLoading = false,
|
|
25
|
-
selectable = false,
|
|
26
|
-
selectedIds = [],
|
|
27
|
-
onSelectChange = () => {},
|
|
28
|
-
emptyMessage = 'No data found.',
|
|
29
|
-
rowKey = 'id',
|
|
30
|
-
}: DataTableProps<T>) {
|
|
31
|
-
const allSelected = data.length > 0 && selectedIds.length === data.length;
|
|
32
|
-
|
|
33
|
-
const handleSelectAll = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
34
|
-
if (e.target.checked) {
|
|
35
|
-
onSelectChange(data.map((row) => row[rowKey] as string | number));
|
|
36
|
-
} else {
|
|
37
|
-
onSelectChange([]);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const handleSelectRow = (id: string | number, checked: boolean) => {
|
|
42
|
-
if (checked) {
|
|
43
|
-
onSelectChange([...selectedIds, id]);
|
|
44
|
-
} else {
|
|
45
|
-
onSelectChange(selectedIds.filter((sid) => sid !== id));
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
if (isLoading) {
|
|
50
|
-
return (
|
|
51
|
-
<div className="ec-data-table__loading">
|
|
52
|
-
<span>Loading...</span>
|
|
53
|
-
</div>
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (data.length === 0) {
|
|
58
|
-
return (
|
|
59
|
-
<div className="ec-data-table__empty">
|
|
60
|
-
<p>{emptyMessage}</p>
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<table className="ec-data-table wp-list-table widefat fixed striped">
|
|
67
|
-
<thead>
|
|
68
|
-
<tr>
|
|
69
|
-
{selectable && (
|
|
70
|
-
<th className="ec-data-table__check-column">
|
|
71
|
-
<input
|
|
72
|
-
type="checkbox"
|
|
73
|
-
checked={allSelected}
|
|
74
|
-
onChange={handleSelectAll}
|
|
75
|
-
/>
|
|
76
|
-
</th>
|
|
77
|
-
)}
|
|
78
|
-
{columns.map((col) => (
|
|
79
|
-
<th key={col.key} style={col.width ? { width: col.width } : undefined}>
|
|
80
|
-
{col.label}
|
|
81
|
-
</th>
|
|
82
|
-
))}
|
|
83
|
-
</tr>
|
|
84
|
-
</thead>
|
|
85
|
-
<tbody>
|
|
86
|
-
{data.map((row) => (
|
|
87
|
-
<tr key={row[rowKey] as string | number}>
|
|
88
|
-
{selectable && (
|
|
89
|
-
<td className="ec-data-table__check-column">
|
|
90
|
-
<input
|
|
91
|
-
type="checkbox"
|
|
92
|
-
checked={selectedIds.includes(row[rowKey] as string | number)}
|
|
93
|
-
onChange={(e) =>
|
|
94
|
-
handleSelectRow(row[rowKey] as string | number, e.target.checked)
|
|
95
|
-
}
|
|
96
|
-
/>
|
|
97
|
-
</td>
|
|
98
|
-
)}
|
|
99
|
-
{columns.map((col) => (
|
|
100
|
-
<td key={col.key}>
|
|
101
|
-
{col.render ? col.render(row[col.key], row) : (row[col.key] as ReactNode)}
|
|
102
|
-
</td>
|
|
103
|
-
))}
|
|
104
|
-
</tr>
|
|
105
|
-
))}
|
|
106
|
-
</tbody>
|
|
107
|
-
</table>
|
|
108
|
-
);
|
|
109
|
-
}
|
package/src/Modal.tsx
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { useEffect, useCallback, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface ModalProps {
|
|
4
|
-
title: string;
|
|
5
|
-
isOpen: boolean;
|
|
6
|
-
onClose: () => void;
|
|
7
|
-
children: ReactNode;
|
|
8
|
-
className?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function Modal({
|
|
12
|
-
title,
|
|
13
|
-
isOpen,
|
|
14
|
-
onClose,
|
|
15
|
-
children,
|
|
16
|
-
className = '',
|
|
17
|
-
}: ModalProps) {
|
|
18
|
-
const handleKeyDown = useCallback(
|
|
19
|
-
(e: KeyboardEvent) => {
|
|
20
|
-
if (e.key === 'Escape') {
|
|
21
|
-
onClose();
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
[onClose]
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (isOpen) {
|
|
29
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
30
|
-
return () => document.removeEventListener('keydown', handleKeyDown);
|
|
31
|
-
}
|
|
32
|
-
}, [isOpen, handleKeyDown]);
|
|
33
|
-
|
|
34
|
-
if (!isOpen) {
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<div className={`ec-modal ${className}`} role="dialog" aria-label={title}>
|
|
40
|
-
<div className="ec-modal__backdrop" onClick={onClose} aria-hidden="true" />
|
|
41
|
-
<div className="ec-modal__content">
|
|
42
|
-
<div className="ec-modal__header">
|
|
43
|
-
<h2>{title}</h2>
|
|
44
|
-
<button type="button" onClick={onClose} aria-label="Close">
|
|
45
|
-
×
|
|
46
|
-
</button>
|
|
47
|
-
</div>
|
|
48
|
-
<div className="ec-modal__body">{children}</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
}
|
package/src/Pagination.tsx
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
export interface PaginationProps {
|
|
2
|
-
currentPage: number;
|
|
3
|
-
totalPages: number;
|
|
4
|
-
totalItems: number;
|
|
5
|
-
onPageChange: (page: number) => void;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function Pagination({
|
|
9
|
-
currentPage,
|
|
10
|
-
totalPages,
|
|
11
|
-
totalItems,
|
|
12
|
-
onPageChange,
|
|
13
|
-
}: PaginationProps) {
|
|
14
|
-
if (totalPages <= 1) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<div className="ec-pagination">
|
|
20
|
-
<span className="ec-pagination__info">
|
|
21
|
-
Page {currentPage} of {totalPages} ({totalItems} items)
|
|
22
|
-
</span>
|
|
23
|
-
<div className="ec-pagination__buttons">
|
|
24
|
-
<button
|
|
25
|
-
type="button"
|
|
26
|
-
disabled={currentPage <= 1}
|
|
27
|
-
onClick={() => onPageChange(currentPage - 1)}
|
|
28
|
-
>
|
|
29
|
-
Previous
|
|
30
|
-
</button>
|
|
31
|
-
<button
|
|
32
|
-
type="button"
|
|
33
|
-
disabled={currentPage >= totalPages}
|
|
34
|
-
onClick={() => onPageChange(currentPage + 1)}
|
|
35
|
-
>
|
|
36
|
-
Next
|
|
37
|
-
</button>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
);
|
|
41
|
-
}
|
package/src/SearchBox.tsx
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useState, type KeyboardEvent } from 'react';
|
|
2
|
-
|
|
3
|
-
export interface SearchBoxProps {
|
|
4
|
-
value?: string;
|
|
5
|
-
onSearch: (value: string) => void;
|
|
6
|
-
placeholder?: string;
|
|
7
|
-
onClear?: () => void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function SearchBox({
|
|
11
|
-
value = '',
|
|
12
|
-
onSearch,
|
|
13
|
-
placeholder = 'Search...',
|
|
14
|
-
onClear,
|
|
15
|
-
}: SearchBoxProps) {
|
|
16
|
-
const [inputValue, setInputValue] = useState(value);
|
|
17
|
-
|
|
18
|
-
const handleSearch = () => {
|
|
19
|
-
onSearch(inputValue);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const handleClear = () => {
|
|
23
|
-
setInputValue('');
|
|
24
|
-
if (onClear) {
|
|
25
|
-
onClear();
|
|
26
|
-
} else {
|
|
27
|
-
onSearch('');
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
|
32
|
-
if (e.key === 'Enter') {
|
|
33
|
-
handleSearch();
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div className="ec-search-box">
|
|
39
|
-
<input
|
|
40
|
-
type="text"
|
|
41
|
-
value={inputValue}
|
|
42
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
43
|
-
placeholder={placeholder}
|
|
44
|
-
onKeyDown={handleKeyDown}
|
|
45
|
-
/>
|
|
46
|
-
<button type="button" onClick={handleSearch}>
|
|
47
|
-
Search
|
|
48
|
-
</button>
|
|
49
|
-
{inputValue && (
|
|
50
|
-
<button type="button" onClick={handleClear}>
|
|
51
|
-
Clear
|
|
52
|
-
</button>
|
|
53
|
-
)}
|
|
54
|
-
</div>
|
|
55
|
-
);
|
|
56
|
-
}
|
package/src/Tabs.tsx
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
export interface TabItem {
|
|
2
|
-
id: string;
|
|
3
|
-
label: string;
|
|
4
|
-
badge?: number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export interface TabsProps {
|
|
8
|
-
tabs: TabItem[];
|
|
9
|
-
active: string;
|
|
10
|
-
onChange: (id: string) => void;
|
|
11
|
-
classPrefix?: string;
|
|
12
|
-
className?: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function Tabs({
|
|
16
|
-
tabs = [],
|
|
17
|
-
active,
|
|
18
|
-
onChange,
|
|
19
|
-
classPrefix = 'ec-tabs',
|
|
20
|
-
className = '',
|
|
21
|
-
}: TabsProps) {
|
|
22
|
-
if (tabs.length === 0) {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const rootClass = [`${classPrefix}__tabs`, className].filter(Boolean).join(' ');
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<div className={rootClass} role="tablist" aria-orientation="horizontal">
|
|
30
|
-
{tabs.map((tab) => {
|
|
31
|
-
const isActive = active === tab.id;
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<button
|
|
35
|
-
key={tab.id}
|
|
36
|
-
type="button"
|
|
37
|
-
role="tab"
|
|
38
|
-
aria-selected={isActive}
|
|
39
|
-
className={`${classPrefix}__tab${isActive ? ' is-active' : ''}`}
|
|
40
|
-
onClick={() => onChange(tab.id)}
|
|
41
|
-
>
|
|
42
|
-
{tab.label}
|
|
43
|
-
{tab.badge != null && tab.badge > 0 && (
|
|
44
|
-
<span className={`${classPrefix}__tab-badge`}>{tab.badge}</span>
|
|
45
|
-
)}
|
|
46
|
-
</button>
|
|
47
|
-
);
|
|
48
|
-
})}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
}
|