project-portfolio 1.0.1 → 1.0.2
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectGrid.d.ts","sourceRoot":"","sources":["../src/ProjectGrid.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectGrid.d.ts","sourceRoot":"","sources":["../src/ProjectGrid.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEzD,UAAU,gBAAgB;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAsB,EAAE,EAAE,gBAAgB,2CAsBzF"}
|
package/dist/ProjectGrid.js
CHANGED
|
@@ -1,64 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useState, useMemo } from "react";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
2
|
import { ProjectCard } from "./ProjectCard";
|
|
5
|
-
import { ProjectFilters } from "./ProjectFilters";
|
|
6
3
|
export function ProjectGrid({ projects, schema, basePath = "/projects" }) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return projects.filter((project) => Object.entries(filters).every(([key, filterValue]) => {
|
|
12
|
-
if (!filterValue)
|
|
13
|
-
return true;
|
|
14
|
-
const field = schema.find((f) => f.key === key);
|
|
15
|
-
if (!field)
|
|
16
|
-
return true;
|
|
17
|
-
const projectValue = project.custom_field_values[key];
|
|
18
|
-
const parseVal = (v) => {
|
|
19
|
-
if (Array.isArray(v))
|
|
20
|
-
return v.map(String).map((s) => s.replace(/`/g, "").trim());
|
|
21
|
-
if (typeof v === "string")
|
|
22
|
-
return v.replace(/`/g, "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
23
|
-
return [String(v !== null && v !== void 0 ? v : "")];
|
|
24
|
-
};
|
|
25
|
-
if (field.type === "multi-select")
|
|
26
|
-
return parseVal(projectValue).includes(filterValue);
|
|
27
|
-
if (field.type === "select")
|
|
28
|
-
return parseVal(projectValue)[0] === filterValue;
|
|
29
|
-
if (field.type === "text")
|
|
30
|
-
return String(projectValue || "").toLowerCase().includes(filterValue.toLowerCase());
|
|
31
|
-
if (field.type === "location") {
|
|
32
|
-
const loc = projectValue;
|
|
33
|
-
if (!loc)
|
|
34
|
-
return false;
|
|
35
|
-
return `${loc.city || ""} ${loc.state || ""}`.toLowerCase().includes(filterValue.toLowerCase());
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}));
|
|
39
|
-
}, [projects, filters, schema]);
|
|
40
|
-
const handleFilterChange = (key, value) => setFilters((prev) => (Object.assign(Object.assign({}, prev), { [key]: value })));
|
|
41
|
-
const clearFilters = () => setFilters({});
|
|
42
|
-
const hasActiveFilters = Object.values(filters).some((v) => v);
|
|
43
|
-
return (_jsxs("div", { children: [filterableFields.length > 0 && (_jsx(ProjectFilters, { fields: filterableFields, filters: filters, onFilterChange: handleFilterChange, onClearFilters: clearFilters, hasActiveFilters: hasActiveFilters })), _jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "1.5rem" }, children: [_jsxs("p", { style: { fontSize: "14px", color: "#71717a", margin: 0 }, children: [filteredProjects.length, " ", filteredProjects.length === 1 ? "project" : "projects"] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "4px", border: "1px solid #e4e4e7", borderRadius: "8px", padding: "4px", backgroundColor: "#fff" }, children: [_jsx("button", { onClick: () => setVariant("card"), "aria-label": "Card view", style: {
|
|
44
|
-
padding: "6px",
|
|
45
|
-
border: "none",
|
|
46
|
-
borderRadius: "6px",
|
|
47
|
-
cursor: "pointer",
|
|
48
|
-
backgroundColor: variant === "card" ? "#18181b" : "transparent",
|
|
49
|
-
color: variant === "card" ? "#fff" : "#a1a1aa",
|
|
50
|
-
display: "flex",
|
|
51
|
-
alignItems: "center",
|
|
52
|
-
transition: "background-color 0.2s",
|
|
53
|
-
}, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "3", width: "7", height: "7" }), _jsx("rect", { x: "14", y: "3", width: "7", height: "7" }), _jsx("rect", { x: "3", y: "14", width: "7", height: "7" }), _jsx("rect", { x: "14", y: "14", width: "7", height: "7" })] }) }), _jsx("button", { onClick: () => setVariant("compact"), "aria-label": "Compact view", style: {
|
|
54
|
-
padding: "6px",
|
|
55
|
-
border: "none",
|
|
56
|
-
borderRadius: "6px",
|
|
57
|
-
cursor: "pointer",
|
|
58
|
-
backgroundColor: variant === "compact" ? "#18181b" : "transparent",
|
|
59
|
-
color: variant === "compact" ? "#fff" : "#a1a1aa",
|
|
60
|
-
display: "flex",
|
|
61
|
-
alignItems: "center",
|
|
62
|
-
transition: "background-color 0.2s",
|
|
63
|
-
}, children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("line", { x1: "3", y1: "6", x2: "21", y2: "6" }), _jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }), _jsx("line", { x1: "3", y1: "18", x2: "21", y2: "18" })] }) })] })] }), filteredProjects.length === 0 ? (_jsxs("div", { style: { textAlign: "center", padding: "4rem 0" }, children: [_jsx("p", { style: { color: "#71717a", fontSize: "18px" }, children: "No projects found matching your filters." }), hasActiveFilters && (_jsx("button", { onClick: clearFilters, style: { marginTop: "1rem", background: "none", border: "none", textDecoration: "underline", cursor: "pointer", fontSize: "14px" }, children: "Clear all filters" }))] })) : variant === "compact" ? (_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(340px, 1fr))", gap: "12px" }, children: filteredProjects.map((project, index) => (_jsx(ProjectCard, { project: project, schema: schema, priority: index === 0, variant: "compact", basePath: basePath }, project.id))) })) : (_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: "2rem" }, children: filteredProjects.map((project, index) => (_jsx(ProjectCard, { project: project, schema: schema, priority: index === 0, variant: "card", basePath: basePath }, project.id))) }))] }));
|
|
4
|
+
if (projects.length === 0) {
|
|
5
|
+
return (_jsx("div", { style: { textAlign: "center", padding: "4rem 0" }, children: _jsx("p", { style: { color: "#71717a" }, children: "No projects found." }) }));
|
|
6
|
+
}
|
|
7
|
+
return (_jsx("div", { style: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px, 1fr))", gap: "2rem" }, children: projects.map((project, index) => (_jsx(ProjectCard, { project: project, schema: schema, priority: index === 0, basePath: basePath }, project.id))) }));
|
|
64
8
|
}
|
|
@@ -27,9 +27,7 @@ export interface ProjectPortfolioProps {
|
|
|
27
27
|
/**
|
|
28
28
|
* ProjectPortfolio — pure card grid, no chrome.
|
|
29
29
|
*
|
|
30
|
-
* Fetches
|
|
31
|
-
* - React.cache() deduplicates within a single render (no double-fetch if used twice on one page)
|
|
32
|
-
* - next: { revalidate: 60 } caches at the Next.js Data Cache layer for 60s across requests
|
|
30
|
+
* Fetches client and project data directly from the API.
|
|
33
31
|
*
|
|
34
32
|
* Usage:
|
|
35
33
|
* import { ProjectPortfolio } from "chisel-project-portfolio"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectPortfolio.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolio.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectPortfolio.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolio.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAyDD;;;;;;;;;;;;;;;;;GAiBG;AACH;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,EACV,OAAO,EACP,QAAsB,GACvB,EAAE,qBAAqB,oDA8BvB"}
|
package/dist/ProjectPortfolio.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { cache } from "react";
|
|
3
2
|
import { ProjectCard } from "./ProjectCard";
|
|
4
|
-
|
|
5
|
-
// next: { revalidate: 60 } caches the fetch in Next.js Data Cache for 60s.
|
|
6
|
-
const fetchPortfolioData = cache(async (apiBase, clientSlug) => {
|
|
3
|
+
const fetchPortfolioData = async (apiBase, clientSlug) => {
|
|
7
4
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
8
|
-
// `next` is a Next.js-specific fetch option not present in the DOM RequestInit type.
|
|
9
|
-
const nextRevalidateInit = { next: { revalidate: 60 } };
|
|
10
5
|
const [clientRes, projectsRes] = await Promise.all([
|
|
11
|
-
fetch(`${apiBase}/api/v1/clients/${clientSlug}
|
|
12
|
-
fetch(`${apiBase}/api/v1/clients/${clientSlug}/projects
|
|
6
|
+
fetch(`${apiBase}/api/v1/clients/${clientSlug}`),
|
|
7
|
+
fetch(`${apiBase}/api/v1/clients/${clientSlug}/projects`),
|
|
13
8
|
]);
|
|
14
9
|
const clientJson = clientRes.ok
|
|
15
10
|
? await clientRes.json()
|
|
@@ -31,7 +26,7 @@ const fetchPortfolioData = cache(async (apiBase, clientSlug) => {
|
|
|
31
26
|
projects: (_j = projectsJson.data) !== null && _j !== void 0 ? _j : [],
|
|
32
27
|
schema,
|
|
33
28
|
};
|
|
34
|
-
}
|
|
29
|
+
};
|
|
35
30
|
/**
|
|
36
31
|
* ProjectPortfolio — self-contained async server component.
|
|
37
32
|
*
|
|
@@ -53,9 +48,7 @@ const fetchPortfolioData = cache(async (apiBase, clientSlug) => {
|
|
|
53
48
|
/**
|
|
54
49
|
* ProjectPortfolio — pure card grid, no chrome.
|
|
55
50
|
*
|
|
56
|
-
* Fetches
|
|
57
|
-
* - React.cache() deduplicates within a single render (no double-fetch if used twice on one page)
|
|
58
|
-
* - next: { revalidate: 60 } caches at the Next.js Data Cache layer for 60s across requests
|
|
51
|
+
* Fetches client and project data directly from the API.
|
|
59
52
|
*
|
|
60
53
|
* Usage:
|
|
61
54
|
* import { ProjectPortfolio } from "chisel-project-portfolio"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-portfolio",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Self-contained project portfolio component for Next.js App Router. Drop in one component, pass a clientSlug and apiBase, done.",
|
|
5
5
|
"keywords": ["nextjs", "react", "portfolio", "projects"],
|
|
6
6
|
"license": "MIT",
|