@chiselandco/nexus 2.5.2 → 2.6.1
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 +37 -1
- package/dist/FilteredPortfolio.d.ts +8 -1
- package/dist/FilteredPortfolio.d.ts.map +1 -1
- package/dist/FilteredPortfolio.js +9 -2
- package/dist/GalleryCarousel.d.ts.map +1 -1
- package/dist/GalleryCarousel.js +2 -0
- package/dist/ProjectPortfolio.d.ts +8 -1
- package/dist/ProjectPortfolio.d.ts.map +1 -1
- package/dist/ProjectPortfolio.js +9 -2
- package/dist/ProjectPortfolioClient.d.ts +8 -1
- package/dist/ProjectPortfolioClient.d.ts.map +1 -1
- package/dist/ProjectPortfolioClient.js +11 -4
- package/dist/SimilarProjects.d.ts +8 -1
- package/dist/SimilarProjects.d.ts.map +1 -1
- package/dist/SimilarProjects.js +10 -2
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Self-contained project portfolio components for Next.js App Router. Pass a `clientSlug`, `apiBase`, and `apiKey` — each component fetches, caches, and renders everything it needs with no client-side waterfall requests.
|
|
4
4
|
|
|
5
|
-
**Version:** 2.
|
|
5
|
+
**Version:** 2.6.1
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -150,6 +150,7 @@ export default async function ProjectsPage({
|
|
|
150
150
|
| `font` | `string` | No | System font | Font family string |
|
|
151
151
|
| `noCache` | `boolean` | No | `false` | Sets `cache: "no-store"` — useful during development |
|
|
152
152
|
| `revalidate` | `number` | No | `86400` | Cache revalidation period in seconds |
|
|
153
|
+
| `side` | `"architectural" \| "speedrail"` | No | — | Filter projects by website side. When omitted all projects are shown. See [Filtering by side](#filtering-by-side). |
|
|
153
154
|
|
|
154
155
|
#### URL param format
|
|
155
156
|
|
|
@@ -402,6 +403,7 @@ Use `variant="card"` to render baseball-card style instead of the default list s
|
|
|
402
403
|
| `font` | `string` | No | System font stack | Font family string |
|
|
403
404
|
| `revalidate` | `number` | No | `86400` | Cache revalidation period in seconds |
|
|
404
405
|
| `noCache` | `boolean` | No | `false` | Sets `cache: "no-store"` — useful during development |
|
|
406
|
+
| `side` | `"architectural" \| "speedrail"` | No | — | Filter projects by website side. When omitted all projects are shown. |
|
|
405
407
|
|
|
406
408
|
---
|
|
407
409
|
|
|
@@ -566,6 +568,7 @@ export default async function ProjectsPage({
|
|
|
566
568
|
| `searchParams` | `Record<string, string \| string[] \| undefined>` | No | `{}` | Filter params — pass Next.js `searchParams` directly |
|
|
567
569
|
| `revalidate` | `number` | No | `86400` | Cache revalidation period in seconds |
|
|
568
570
|
| `noCache` | `boolean` | No | `false` | Sets `cache: "no-store"` — useful during development |
|
|
571
|
+
| `side` | `"architectural" \| "speedrail"` | No | — | Filter projects by website side. When omitted all projects are shown. |
|
|
569
572
|
|
|
570
573
|
---
|
|
571
574
|
|
|
@@ -608,6 +611,39 @@ export default function ProjectsPage() {
|
|
|
608
611
|
| `filters` | `Record<string, string>` | No | `{}` | Active filters — filtering is instant, no API call on change |
|
|
609
612
|
| `columns` | `2 \| 3` | No | `3` | Number of grid columns |
|
|
610
613
|
| `font` | `string` | No | System font stack | Font family string |
|
|
614
|
+
| `side` | `"architectural" \| "speedrail"` | No | — | Filter projects by website side. When omitted all projects are shown. |
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
## Filtering by side
|
|
619
|
+
|
|
620
|
+
Every project returned by the API includes a `side` field: `"architectural"`, `"speedrail"`, or `"both"`. This reflects which section of the client's website a project belongs to.
|
|
621
|
+
|
|
622
|
+
The following components accept an optional `side` prop: `FilteredPortfolio`, `ProjectPortfolio`, `ProjectPortfolioClient`, and `SimilarProjects`.
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
// Architectural side of the site — only shows architectural + both projects
|
|
626
|
+
<FilteredPortfolio
|
|
627
|
+
clientSlug="hollaender"
|
|
628
|
+
apiBase="https://your-api.com"
|
|
629
|
+
apiKey={process.env.HOLLAENDER_API_KEY!}
|
|
630
|
+
basePath="/architectural/projects"
|
|
631
|
+
searchParams={searchParams}
|
|
632
|
+
side="architectural"
|
|
633
|
+
/>
|
|
634
|
+
|
|
635
|
+
// Speed-Rail side of the site — only shows speedrail + both projects
|
|
636
|
+
<FilteredPortfolio
|
|
637
|
+
clientSlug="hollaender"
|
|
638
|
+
apiBase="https://your-api.com"
|
|
639
|
+
apiKey={process.env.HOLLAENDER_API_KEY!}
|
|
640
|
+
basePath="/speedrail/projects"
|
|
641
|
+
searchParams={searchParams}
|
|
642
|
+
side="speedrail"
|
|
643
|
+
/>
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
When `side` is omitted the component behaves exactly as before — all projects are shown. The client controls which value to pass based on the current route or context. No extra API calls are made — the filtering happens in memory after the standard fetch.
|
|
611
647
|
|
|
612
648
|
---
|
|
613
649
|
|
|
@@ -19,6 +19,13 @@ export interface FilteredPortfolioProps {
|
|
|
19
19
|
revalidate?: number;
|
|
20
20
|
noCache?: boolean;
|
|
21
21
|
font?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Filter projects by website side.
|
|
24
|
+
* - "architectural" — shows projects with side "architectural" or "both"
|
|
25
|
+
* - "speedrail" — shows projects with side "speedrail" or "both"
|
|
26
|
+
* - omit — shows all projects regardless of side
|
|
27
|
+
*/
|
|
28
|
+
side?: "architectural" | "speedrail";
|
|
22
29
|
}
|
|
23
30
|
/**
|
|
24
31
|
* FilteredPortfolio — server component.
|
|
@@ -41,5 +48,5 @@ export interface FilteredPortfolioProps {
|
|
|
41
48
|
* )
|
|
42
49
|
* }
|
|
43
50
|
*/
|
|
44
|
-
export declare function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams, filterKeys, basePath, revalidate, noCache, font, }: FilteredPortfolioProps): Promise<import("react").JSX.Element>;
|
|
51
|
+
export declare function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams, filterKeys, basePath, revalidate, noCache, font, side, }: FilteredPortfolioProps): Promise<import("react").JSX.Element>;
|
|
45
52
|
//# sourceMappingURL=FilteredPortfolio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilteredPortfolio.d.ts","sourceRoot":"","sources":["../src/FilteredPortfolio.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IAC5D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"FilteredPortfolio.d.ts","sourceRoot":"","sources":["../src/FilteredPortfolio.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IAC5D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,WAAW,CAAA;CACrC;AA8ED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,UAAU,EACV,OAAO,EACP,MAAM,EACN,YAAiB,EACjB,UAAU,EACV,QAAsB,EACtB,UAAe,EACf,OAAe,EACf,IAAI,EACJ,IAAI,GACL,EAAE,sBAAsB,wCAqGxB"}
|
|
@@ -74,7 +74,7 @@ async function fetchSchema(apiBase, clientSlug, apiKey, fetchOpts) {
|
|
|
74
74
|
* )
|
|
75
75
|
* }
|
|
76
76
|
*/
|
|
77
|
-
export async function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams = {}, filterKeys, basePath = "/projects", revalidate = 60, noCache = false, font, }) {
|
|
77
|
+
export async function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams = {}, filterKeys, basePath = "/projects", revalidate = 60, noCache = false, font, side, }) {
|
|
78
78
|
const fetchOpts = noCache
|
|
79
79
|
? { cache: "no-store" }
|
|
80
80
|
: { next: { revalidate } };
|
|
@@ -95,6 +95,13 @@ export async function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchPar
|
|
|
95
95
|
fetchSchema(apiBase, clientSlug, apiKey, fetchOpts),
|
|
96
96
|
]);
|
|
97
97
|
const activeCount = Object.values(activeFilters).reduce((n, ids) => n + ids.length, 0);
|
|
98
|
+
const visible = side
|
|
99
|
+
? projects.filter((p) => {
|
|
100
|
+
var _a;
|
|
101
|
+
const s = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a["side"];
|
|
102
|
+
return s === side || s === "both";
|
|
103
|
+
})
|
|
104
|
+
: projects;
|
|
98
105
|
return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
|
|
99
106
|
.nxs-fp-wrap {
|
|
100
107
|
width: 100%;
|
|
@@ -130,5 +137,5 @@ export async function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchPar
|
|
|
130
137
|
.chisel-project-card-img { height: 180px; }
|
|
131
138
|
@media (min-width: 640px) { .chisel-project-card-img { height: 200px; } }
|
|
132
139
|
@media (min-width: 1024px) { .chisel-project-card-img { height: 220px; } }
|
|
133
|
-
` }), _jsxs("div", { className: "nxs-fp-wrap", children: [_jsxs("div", { className: "nxs-fp-toolbar", children: [_jsxs("p", { className: "nxs-fp-count", children: ["Showing ", _jsx("strong", { children: projects.length }), total > projects.length ? ` of ${total}` : "", " project", projects.length !== 1 ? "s" : "", activeCount > 0 && ` (${activeCount} filter${activeCount !== 1 ? "s" : ""} active)`] }), _jsx(FilterSidebar, { schema: schema, filterKeys: filterKeys, font: font })] }), projects.length === 0 ? (_jsx("div", { style: { padding: "4rem 0", textAlign: "center" }, children: _jsx("p", { style: { color: "#71717a" }, children: "No projects match the selected filters." }) })) : (_jsx("div", { className: "nxs-fp-grid", children:
|
|
140
|
+
` }), _jsxs("div", { className: "nxs-fp-wrap", children: [_jsxs("div", { className: "nxs-fp-toolbar", children: [_jsxs("p", { className: "nxs-fp-count", children: ["Showing ", _jsx("strong", { children: projects.length }), total > projects.length ? ` of ${total}` : "", " project", projects.length !== 1 ? "s" : "", activeCount > 0 && ` (${activeCount} filter${activeCount !== 1 ? "s" : ""} active)`] }), _jsx(FilterSidebar, { schema: schema, filterKeys: filterKeys, font: font })] }), projects.length === 0 ? (_jsx("div", { style: { padding: "4rem 0", textAlign: "center" }, children: _jsx("p", { style: { color: "#71717a" }, children: "No projects match the selected filters." }) })) : (_jsx("div", { className: "nxs-fp-grid", children: visible.map((project, index) => (_jsx(ProjectCard, { project: project, schema: schema, fieldOptionsMap: fieldOptionsMap, basePath: basePath, priority: index === 0 }, project.id))) }))] })] }));
|
|
134
141
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GalleryCarousel.d.ts","sourceRoot":"","sources":["../src/GalleryCarousel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAA;AAEhF,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAe,MAAM,SAAS,CAAA;AASpE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC7B;
|
|
1
|
+
{"version":3,"file":"GalleryCarousel.d.ts","sourceRoot":"","sources":["../src/GalleryCarousel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4D,MAAM,OAAO,CAAA;AAEhF,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAe,MAAM,SAAS,CAAA;AASpE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAC7B;AAgOD,wBAAgB,eAAe,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,MAAW,EAAE,EAAE,oBAAoB,4BA2V1F"}
|
package/dist/GalleryCarousel.js
CHANGED
|
@@ -24,6 +24,13 @@ export interface ProjectPortfolioProps {
|
|
|
24
24
|
* Useful for debugging — do not use in production.
|
|
25
25
|
*/
|
|
26
26
|
noCache?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Filter projects by website side.
|
|
29
|
+
* - "architectural" — shows projects with side "architectural" or "both"
|
|
30
|
+
* - "speedrail" — shows projects with side "speedrail" or "both"
|
|
31
|
+
* - omit — shows all projects regardless of side
|
|
32
|
+
*/
|
|
33
|
+
side?: "architectural" | "speedrail";
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
36
|
* ProjectPortfolio — pure self-fetching card grid.
|
|
@@ -40,5 +47,5 @@ export interface ProjectPortfolioProps {
|
|
|
40
47
|
* apiBase="https://your-api.com"
|
|
41
48
|
* />
|
|
42
49
|
*/
|
|
43
|
-
export declare function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath, searchParams, revalidate, noCache, }: ProjectPortfolioProps): Promise<import("react").JSX.Element>;
|
|
50
|
+
export declare function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath, searchParams, revalidate, noCache, side, }: ProjectPortfolioProps): Promise<import("react").JSX.Element>;
|
|
44
51
|
//# sourceMappingURL=ProjectPortfolio.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectPortfolio.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolio.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IAC5D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"ProjectPortfolio.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolio.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;IAC5D;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,WAAW,CAAA;CACrC;AA0ED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,YAAiB,EACjB,UAAe,EACf,OAAe,EACf,IAAI,GACL,EAAE,qBAAqB,wCAsIvB"}
|
package/dist/ProjectPortfolio.js
CHANGED
|
@@ -65,7 +65,7 @@ const fetchPortfolioData = cache(async (apiBase, clientSlug, apiKey, revalidate,
|
|
|
65
65
|
* apiBase="https://your-api.com"
|
|
66
66
|
* />
|
|
67
67
|
*/
|
|
68
|
-
export async function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath = "/projects", searchParams = {}, revalidate = 60, noCache = false, }) {
|
|
68
|
+
export async function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath = "/projects", searchParams = {}, revalidate = 60, noCache = false, side, }) {
|
|
69
69
|
// Parse filter[key]=value from searchParams into { key: value }
|
|
70
70
|
const filters = {};
|
|
71
71
|
Object.entries(searchParams).forEach(([key, val]) => {
|
|
@@ -77,6 +77,13 @@ export async function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath =
|
|
|
77
77
|
});
|
|
78
78
|
const filtersKey = JSON.stringify(filters);
|
|
79
79
|
const { projects, schema, fieldOptionsMap } = await fetchPortfolioData(apiBase, clientSlug, apiKey, revalidate, filtersKey, noCache);
|
|
80
|
+
const visible = side
|
|
81
|
+
? projects.filter((p) => {
|
|
82
|
+
var _a;
|
|
83
|
+
const s = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a["side"];
|
|
84
|
+
return s === side || s === "both";
|
|
85
|
+
})
|
|
86
|
+
: projects;
|
|
80
87
|
const hasFilters = Object.keys(filters).length > 0;
|
|
81
88
|
const activeFilterLabels = Object.entries(filters)
|
|
82
89
|
.map(([key, val]) => {
|
|
@@ -149,5 +156,5 @@ export async function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath =
|
|
|
149
156
|
height: 220px;
|
|
150
157
|
}
|
|
151
158
|
}
|
|
152
|
-
` }), _jsx("div", { className: "chisel-project-grid", children:
|
|
159
|
+
` }), _jsx("div", { className: "chisel-project-grid", children: visible.map((project, index) => (_jsx(ProjectCard, { project: project, schema: schema, fieldOptionsMap: fieldOptionsMap, basePath: basePath, priority: index === 0 }, project.id))) })] }));
|
|
153
160
|
}
|
|
@@ -19,6 +19,13 @@ export interface ProjectPortfolioClientProps {
|
|
|
19
19
|
font?: string;
|
|
20
20
|
/** Max columns in the grid. 2 or 3. Defaults to 3 */
|
|
21
21
|
columns?: 2 | 3;
|
|
22
|
+
/**
|
|
23
|
+
* Filter projects by website side.
|
|
24
|
+
* - "architectural" — shows projects with side "architectural" or "both"
|
|
25
|
+
* - "speedrail" — shows projects with side "speedrail" or "both"
|
|
26
|
+
* - omit — shows all projects regardless of side
|
|
27
|
+
*/
|
|
28
|
+
side?: "architectural" | "speedrail";
|
|
22
29
|
}
|
|
23
|
-
export declare function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath, filters, font, columns, }: ProjectPortfolioClientProps): React.JSX.Element;
|
|
30
|
+
export declare function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath, filters, font, columns, side, }: ProjectPortfolioClientProps): React.JSX.Element;
|
|
24
31
|
//# sourceMappingURL=ProjectPortfolioClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectPortfolioClient.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolioClient.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAuC,MAAM,OAAO,CAAA;AAM3D,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"ProjectPortfolioClient.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolioClient.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAuC,MAAM,OAAO,CAAA;AAM3D,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qDAAqD;IACrD,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,WAAW,CAAA;CACrC;AAyDD,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,OAAY,EACZ,IAAmB,EACnB,OAAW,EACX,IAAI,GACL,EAAE,2BAA2B,qBAyJ7B"}
|
|
@@ -39,7 +39,7 @@ function matchesFilters(project, filters, schema, fieldOptionsMap) {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
// ─── Component ───────────────────────────────────────────────────────────────
|
|
42
|
-
export function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath = "/projects", filters = {}, font = DEFAULT_FONT, columns = 3, }) {
|
|
42
|
+
export function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath = "/projects", filters = {}, font = DEFAULT_FONT, columns = 3, side, }) {
|
|
43
43
|
const [data, setData] = useState(null);
|
|
44
44
|
useEffect(() => {
|
|
45
45
|
const cacheKey = `${clientSlug}:${apiBase}:${apiKey}`;
|
|
@@ -90,11 +90,18 @@ export function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath =
|
|
|
90
90
|
const filteredProjects = useMemo(() => {
|
|
91
91
|
if (!data)
|
|
92
92
|
return [];
|
|
93
|
+
const bySide = side
|
|
94
|
+
? data.projects.filter((p) => {
|
|
95
|
+
var _a;
|
|
96
|
+
const s = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a["side"];
|
|
97
|
+
return s === side || s === "both";
|
|
98
|
+
})
|
|
99
|
+
: data.projects;
|
|
93
100
|
const hasActiveFilters = Object.values(filters).some(Boolean);
|
|
94
101
|
if (!hasActiveFilters)
|
|
95
|
-
return
|
|
96
|
-
return
|
|
97
|
-
}, [data, filters]);
|
|
102
|
+
return bySide;
|
|
103
|
+
return bySide.filter((p) => matchesFilters(p, filters, data.schema, data.fieldOptionsMap));
|
|
104
|
+
}, [data, filters, side]);
|
|
98
105
|
const gridCols = columns === 2
|
|
99
106
|
? "repeat(2, 1fr)"
|
|
100
107
|
: "repeat(3, 1fr)";
|
|
@@ -43,6 +43,13 @@ export interface SimilarProjectsProps {
|
|
|
43
43
|
title?: string;
|
|
44
44
|
/** Small label above the heading. Defaults to "More Work" */
|
|
45
45
|
subtitle?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Filter projects by website side.
|
|
48
|
+
* - "architectural" — shows projects with side "architectural" or "both"
|
|
49
|
+
* - "speedrail" — shows projects with side "speedrail" or "both"
|
|
50
|
+
* - omit — shows all projects regardless of side
|
|
51
|
+
*/
|
|
52
|
+
side?: "architectural" | "speedrail";
|
|
46
53
|
}
|
|
47
|
-
export declare function SimilarProjects({ filters, excludeSlug, clientSlug, apiBase, apiKey, basePath, maxItems, revalidate, noCache, variant, projectSlugs, title, subtitle, }: SimilarProjectsProps): Promise<import("react").JSX.Element | null>;
|
|
54
|
+
export declare function SimilarProjects({ filters, excludeSlug, clientSlug, apiBase, apiKey, basePath, maxItems, revalidate, noCache, variant, projectSlugs, title, subtitle, side, }: SimilarProjectsProps): Promise<import("react").JSX.Element | null>;
|
|
48
55
|
//# sourceMappingURL=SimilarProjects.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimilarProjects.d.ts","sourceRoot":"","sources":["../src/SimilarProjects.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"SimilarProjects.d.ts","sourceRoot":"","sources":["../src/SimilarProjects.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,mEAAmE;IACnE,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,eAAe,GAAG,WAAW,CAAA;CACrC;AA6DD,wBAAsB,eAAe,CAAC,EACpC,OAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,QAAY,EACZ,UAAe,EACf,OAAe,EACf,OAAgB,EAChB,YAAY,EACZ,KAA0B,EAC1B,QAAsB,EACtB,IAAI,GACL,EAAE,oBAAoB,+CA4KtB"}
|
package/dist/SimilarProjects.js
CHANGED
|
@@ -49,8 +49,16 @@ async function fetchSimilarData(apiBase, clientSlug, apiKey, revalidate, noCache
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
// ─── Component ────────────────────────────────────────────────────────────────
|
|
52
|
-
export async function SimilarProjects({ filters = {}, excludeSlug, clientSlug, apiBase, apiKey, basePath = "/projects", maxItems = 3, revalidate = 60, noCache = false, variant = "list", projectSlugs, title = "Similar Projects", subtitle = "More Work", }) {
|
|
53
|
-
const { allProjects, schema, fieldOptionsMap } = await fetchSimilarData(apiBase, clientSlug, apiKey, revalidate, noCache);
|
|
52
|
+
export async function SimilarProjects({ filters = {}, excludeSlug, clientSlug, apiBase, apiKey, basePath = "/projects", maxItems = 3, revalidate = 60, noCache = false, variant = "list", projectSlugs, title = "Similar Projects", subtitle = "More Work", side, }) {
|
|
53
|
+
const { allProjects: allProjectsRaw, schema, fieldOptionsMap } = await fetchSimilarData(apiBase, clientSlug, apiKey, revalidate, noCache);
|
|
54
|
+
// Apply side filter before any other filtering
|
|
55
|
+
const allProjects = side
|
|
56
|
+
? allProjectsRaw.filter((p) => {
|
|
57
|
+
var _a;
|
|
58
|
+
const s = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a["side"];
|
|
59
|
+
return s === side || s === "both";
|
|
60
|
+
})
|
|
61
|
+
: allProjectsRaw;
|
|
54
62
|
const badgeField = schema.find((f) => f.display_position === "badge_overlay");
|
|
55
63
|
const locationField = schema.find((f) => f.type === "location");
|
|
56
64
|
const font = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
package/dist/types.d.ts
CHANGED
|
@@ -39,6 +39,8 @@ export interface Project {
|
|
|
39
39
|
image_url: string | null;
|
|
40
40
|
is_featured: boolean;
|
|
41
41
|
is_published?: boolean;
|
|
42
|
+
/** Which website side this project belongs to. Omitted = show on all sides. */
|
|
43
|
+
side?: "architectural" | "speedrail" | "both";
|
|
42
44
|
custom_field_values: Record<string, CustomFieldValue>;
|
|
43
45
|
created_at: string;
|
|
44
46
|
updated_at: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAA;IAChE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,aAAa,EAAE,OAAO,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAA;CACpE;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,aAAa,GAAG,IAAI,CAAA;AAEhF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,KAAK,EAAE,CAAA;CACf"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAA;IAChE,OAAO,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,aAAa,EAAE,OAAO,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAA;CACpE;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,+FAA+F;IAC/F,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,CAAA;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,aAAa,GAAG,IAAI,CAAA;AAEhF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,eAAe,GAAG,WAAW,GAAG,MAAM,CAAA;IAC7C,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IACrD,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,KAAK,EAAE,CAAA;CACf"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chiselandco/nexus",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"description": "Self-contained project portfolio components for Next.js App Router. Includes ProjectPortfolio, ProjectPortfolioClient, ProjectDetail, SimilarProjects, ProjectMenu, ProjectMenuClient, GalleryCarousel, FilterSidebar, and FilteredPortfolio. Pass a clientSlug and apiBase — done.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nextjs",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"react-dom": ">=18.0.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@types/node": "^
|
|
40
|
+
"@types/node": "^26.0.0",
|
|
41
41
|
"@types/react": "^18.0.0",
|
|
42
42
|
"@types/react-dom": "^18.0.0",
|
|
43
43
|
"next": "^15.0.0",
|