@chiselandco/nexus 2.6.0 → 3.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 +30 -14
- package/dist/FilterSidebar.d.ts +1 -1
- package/dist/FilterSidebar.d.ts.map +1 -1
- package/dist/FilteredPortfolio.d.ts +10 -6
- package/dist/FilteredPortfolio.d.ts.map +1 -1
- package/dist/FilteredPortfolio.js +7 -3
- package/dist/GalleryCarousel.d.ts +2 -1
- package/dist/GalleryCarousel.d.ts.map +1 -1
- package/dist/GalleryCarousel.js +2 -0
- package/dist/ProjectCard.d.ts +2 -1
- package/dist/ProjectCard.d.ts.map +1 -1
- package/dist/ProjectDetail.d.ts +1 -1
- package/dist/ProjectDetail.d.ts.map +1 -1
- package/dist/ProjectMenu.d.ts +1 -1
- package/dist/ProjectMenu.d.ts.map +1 -1
- package/dist/ProjectMenuClient.d.ts +2 -1
- package/dist/ProjectMenuClient.d.ts.map +1 -1
- package/dist/ProjectPortfolio.d.ts +9 -6
- package/dist/ProjectPortfolio.d.ts.map +1 -1
- package/dist/ProjectPortfolio.js +7 -3
- package/dist/ProjectPortfolioClient.d.ts +10 -6
- package/dist/ProjectPortfolioClient.d.ts.map +1 -1
- package/dist/ProjectPortfolioClient.js +10 -6
- package/dist/SimilarProjects.d.ts +9 -6
- package/dist/SimilarProjects.d.ts.map +1 -1
- package/dist/SimilarProjects.js +8 -4
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +16 -3
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:**
|
|
5
|
+
**Version:** 3.0.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -150,7 +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
|
-
| `
|
|
153
|
+
| `filterBy` | `{ field: string; value: string }` | No | — | Pre-filter projects by any custom field value. See [Filtering by field](#filtering-by-field). |
|
|
154
154
|
|
|
155
155
|
#### URL param format
|
|
156
156
|
|
|
@@ -403,7 +403,7 @@ Use `variant="card"` to render baseball-card style instead of the default list s
|
|
|
403
403
|
| `font` | `string` | No | System font stack | Font family string |
|
|
404
404
|
| `revalidate` | `number` | No | `86400` | Cache revalidation period in seconds |
|
|
405
405
|
| `noCache` | `boolean` | No | `false` | Sets `cache: "no-store"` — useful during development |
|
|
406
|
-
| `
|
|
406
|
+
| `filterBy` | `{ field: string; value: string }` | No | — | Pre-filter projects by any custom field value. See [Filtering by field](#filtering-by-field). |
|
|
407
407
|
|
|
408
408
|
---
|
|
409
409
|
|
|
@@ -568,7 +568,7 @@ export default async function ProjectsPage({
|
|
|
568
568
|
| `searchParams` | `Record<string, string \| string[] \| undefined>` | No | `{}` | Filter params — pass Next.js `searchParams` directly |
|
|
569
569
|
| `revalidate` | `number` | No | `86400` | Cache revalidation period in seconds |
|
|
570
570
|
| `noCache` | `boolean` | No | `false` | Sets `cache: "no-store"` — useful during development |
|
|
571
|
-
| `
|
|
571
|
+
| `filterBy` | `{ field: string; value: string }` | No | — | Pre-filter projects by any custom field value. See [Filtering by field](#filtering-by-field). |
|
|
572
572
|
|
|
573
573
|
---
|
|
574
574
|
|
|
@@ -611,39 +611,55 @@ export default function ProjectsPage() {
|
|
|
611
611
|
| `filters` | `Record<string, string>` | No | `{}` | Active filters — filtering is instant, no API call on change |
|
|
612
612
|
| `columns` | `2 \| 3` | No | `3` | Number of grid columns |
|
|
613
613
|
| `font` | `string` | No | System font stack | Font family string |
|
|
614
|
-
| `
|
|
614
|
+
| `filterBy` | `{ field: string; value: string }` | No | — | Pre-filter projects by any custom field value. See [Filtering by field](#filtering-by-field). |
|
|
615
615
|
|
|
616
616
|
---
|
|
617
617
|
|
|
618
|
-
## Filtering by
|
|
618
|
+
## Filtering by field
|
|
619
619
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
The following components accept an optional `side` prop: `FilteredPortfolio`, `ProjectPortfolio`, `ProjectPortfolioClient`, and `SimilarProjects`.
|
|
620
|
+
`FilteredPortfolio`, `ProjectPortfolio`, `ProjectPortfolioClient`, and `SimilarProjects` all accept an optional `filterBy` prop. It pre-filters the project list by any custom field value before any user-driven filters are applied.
|
|
623
621
|
|
|
624
622
|
```tsx
|
|
625
|
-
//
|
|
623
|
+
// Only show projects where custom field "side" equals "architectural" or "both"
|
|
626
624
|
<FilteredPortfolio
|
|
627
625
|
clientSlug="hollaender"
|
|
628
626
|
apiBase="https://your-api.com"
|
|
629
627
|
apiKey={process.env.HOLLAENDER_API_KEY!}
|
|
630
628
|
basePath="/architectural/projects"
|
|
631
629
|
searchParams={searchParams}
|
|
632
|
-
|
|
630
|
+
filterBy={{ field: "side", value: "architectural" }}
|
|
633
631
|
/>
|
|
634
632
|
|
|
635
|
-
//
|
|
633
|
+
// Only show projects where custom field "side" equals "speedrail" or "both"
|
|
636
634
|
<FilteredPortfolio
|
|
637
635
|
clientSlug="hollaender"
|
|
638
636
|
apiBase="https://your-api.com"
|
|
639
637
|
apiKey={process.env.HOLLAENDER_API_KEY!}
|
|
640
638
|
basePath="/speedrail/projects"
|
|
641
639
|
searchParams={searchParams}
|
|
642
|
-
|
|
640
|
+
filterBy={{ field: "side", value: "speedrail" }}
|
|
641
|
+
/>
|
|
642
|
+
|
|
643
|
+
// Works with any field — not just "side"
|
|
644
|
+
<ProjectPortfolio
|
|
645
|
+
clientSlug="acme"
|
|
646
|
+
apiBase="https://your-api.com"
|
|
647
|
+
apiKey={process.env.ACME_API_KEY!}
|
|
648
|
+
filterBy={{ field: "region", value: "northeast" }}
|
|
643
649
|
/>
|
|
644
650
|
```
|
|
645
651
|
|
|
646
|
-
|
|
652
|
+
The `"both"` fallback is built in — if a project's field value is `"both"` it matches any `filterBy.value`. When `filterBy` is omitted all projects are shown. No extra API calls are made — filtering happens in memory after the standard fetch.
|
|
653
|
+
|
|
654
|
+
### Migration from v2 `side` prop
|
|
655
|
+
|
|
656
|
+
```tsx
|
|
657
|
+
// v2
|
|
658
|
+
<FilteredPortfolio side="architectural" />
|
|
659
|
+
|
|
660
|
+
// v3
|
|
661
|
+
<FilteredPortfolio filterBy={{ field: "side", value: "architectural" }} />
|
|
662
|
+
```
|
|
647
663
|
|
|
648
664
|
---
|
|
649
665
|
|
package/dist/FilterSidebar.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export interface FilterSidebarProps {
|
|
|
16
16
|
/** Label for the trigger link. Defaults to "Advanced Filters" */
|
|
17
17
|
triggerLabel?: string;
|
|
18
18
|
}
|
|
19
|
-
export declare function FilterSidebar({ schema, filterKeys, font, triggerLabel, }: FilterSidebarProps): import("react
|
|
19
|
+
export declare function FilterSidebar({ schema, filterKeys, font, triggerLabel, }: FilterSidebarProps): import("react").JSX.Element | null;
|
|
20
20
|
//# sourceMappingURL=FilterSidebar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterSidebar.d.ts","sourceRoot":"","sources":["../src/FilterSidebar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,IAAI,EACJ,YAAiC,GAClC,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"FilterSidebar.d.ts","sourceRoot":"","sources":["../src/FilterSidebar.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAEhD,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,UAAU,EACV,IAAI,EACJ,YAAiC,GAClC,EAAE,kBAAkB,sCAuXpB"}
|
|
@@ -20,12 +20,16 @@ export interface FilteredPortfolioProps {
|
|
|
20
20
|
noCache?: boolean;
|
|
21
21
|
font?: string;
|
|
22
22
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Pre-filter projects by any custom field value before rendering.
|
|
24
|
+
* Useful for splitting a portfolio by a routing field (e.g. site section).
|
|
25
|
+
* e.g. filterBy={{ field: "side", value: "architectural" }}
|
|
26
|
+
* Projects where the field value equals the given value OR "both" are shown.
|
|
27
|
+
* When omitted all projects are shown.
|
|
27
28
|
*/
|
|
28
|
-
|
|
29
|
+
filterBy?: {
|
|
30
|
+
field: string;
|
|
31
|
+
value: string;
|
|
32
|
+
};
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* FilteredPortfolio — server component.
|
|
@@ -48,5 +52,5 @@ export interface FilteredPortfolioProps {
|
|
|
48
52
|
* )
|
|
49
53
|
* }
|
|
50
54
|
*/
|
|
51
|
-
export declare function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams, filterKeys, basePath, revalidate, noCache, font,
|
|
55
|
+
export declare function FilteredPortfolio({ clientSlug, apiBase, apiKey, searchParams, filterKeys, basePath, revalidate, noCache, font, filterBy, }: FilteredPortfolioProps): Promise<import("react").JSX.Element>;
|
|
52
56
|
//# 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;IACb
|
|
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;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;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,QAAQ,GACT,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, filterBy, }) {
|
|
78
78
|
const fetchOpts = noCache
|
|
79
79
|
? { cache: "no-store" }
|
|
80
80
|
: { next: { revalidate } };
|
|
@@ -95,8 +95,12 @@ 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 =
|
|
99
|
-
? projects.filter((p) =>
|
|
98
|
+
const visible = filterBy
|
|
99
|
+
? projects.filter((p) => {
|
|
100
|
+
var _a;
|
|
101
|
+
const v = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a[filterBy.field];
|
|
102
|
+
return v === filterBy.value || v === "both";
|
|
103
|
+
})
|
|
100
104
|
: projects;
|
|
101
105
|
return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
|
|
102
106
|
.nxs-fp-wrap {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Media, CustomFieldSchema } from "./types";
|
|
2
3
|
export interface GalleryCarouselProps {
|
|
3
4
|
images: Media[];
|
|
@@ -10,5 +11,5 @@ export interface GalleryCarouselProps {
|
|
|
10
11
|
*/
|
|
11
12
|
schema?: CustomFieldSchema[];
|
|
12
13
|
}
|
|
13
|
-
export declare function GalleryCarousel({ images, projectTitle, schema }: GalleryCarouselProps):
|
|
14
|
+
export declare function GalleryCarousel({ images, projectTitle, schema }: GalleryCarouselProps): React.JSX.Element | null;
|
|
14
15
|
//# sourceMappingURL=GalleryCarousel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GalleryCarousel.d.ts","sourceRoot":"","sources":["../src/GalleryCarousel.tsx"],"names":[],"mappings":"
|
|
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
package/dist/ProjectCard.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Project, CustomFieldSchema } from "./types";
|
|
2
3
|
export type CardVariant = "card" | "compact";
|
|
3
4
|
interface ProjectCardProps {
|
|
@@ -10,6 +11,6 @@ interface ProjectCardProps {
|
|
|
10
11
|
/** Base path for project detail links. Defaults to "/projects" */
|
|
11
12
|
basePath?: string;
|
|
12
13
|
}
|
|
13
|
-
export declare function ProjectCard({ project, schema, fieldOptionsMap, priority, variant, basePath, }: ProjectCardProps):
|
|
14
|
+
export declare function ProjectCard({ project, schema, fieldOptionsMap, priority, variant, basePath, }: ProjectCardProps): React.JSX.Element;
|
|
14
15
|
export {};
|
|
15
16
|
//# sourceMappingURL=ProjectCard.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectCard.d.ts","sourceRoot":"","sources":["../src/ProjectCard.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectCard.d.ts","sourceRoot":"","sources":["../src/ProjectCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAmC,MAAM,SAAS,CAAA;AAE1F,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,CAAA;AAE5C,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B,2FAA2F;IAC3F,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAeD,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,MAAM,EACN,eAAoB,EACpB,QAAQ,EACR,OAAgB,EAChB,QAAsB,GACvB,EAAE,gBAAgB,qBA2QlB"}
|
package/dist/ProjectDetail.d.ts
CHANGED
|
@@ -25,5 +25,5 @@ export interface ProjectDetailProps {
|
|
|
25
25
|
*/
|
|
26
26
|
noCache?: boolean;
|
|
27
27
|
}
|
|
28
|
-
export declare function ProjectDetail({ slug: slugProp, projectSlug, clientSlug, apiBase, apiKey, backPath, backLabel, revalidate, noCache, }: ProjectDetailProps): Promise<import("react
|
|
28
|
+
export declare function ProjectDetail({ slug: slugProp, projectSlug, clientSlug, apiBase, apiKey, backPath, backLabel, revalidate, noCache, }: ProjectDetailProps): Promise<import("react").JSX.Element>;
|
|
29
29
|
//# sourceMappingURL=ProjectDetail.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectDetail.d.ts","sourceRoot":"","sources":["../src/ProjectDetail.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAsFD,wBAAsB,aAAa,CAAC,EAClC,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,SAA0B,EAC1B,UAAe,EACf,OAAe,GAChB,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"ProjectDetail.d.ts","sourceRoot":"","sources":["../src/ProjectDetail.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,iFAAiF;IACjF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAsFD,wBAAsB,aAAa,CAAC,EAClC,IAAI,EAAE,QAAQ,EACd,WAAW,EACX,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,SAA0B,EAC1B,UAAe,EACf,OAAe,GAChB,EAAE,kBAAkB,wCAiRpB"}
|
package/dist/ProjectMenu.d.ts
CHANGED
|
@@ -80,5 +80,5 @@ export declare function fetchProjectMenuData({ apiBase, clientSlug, apiKey, menu
|
|
|
80
80
|
filterFieldName: string;
|
|
81
81
|
fieldOptionsMap: Record<string, Record<string, string>>;
|
|
82
82
|
}>;
|
|
83
|
-
export declare function ProjectMenu({ clientSlug, apiBase, apiKey, menuId, basePath, viewAllPath, subtitle, font, maxProjects, revalidate, noCache, }: ProjectMenuProps): Promise<import("react
|
|
83
|
+
export declare function ProjectMenu({ clientSlug, apiBase, apiKey, menuId, basePath, viewAllPath, subtitle, font, maxProjects, revalidate, noCache, }: ProjectMenuProps): Promise<import("react").JSX.Element>;
|
|
84
84
|
//# sourceMappingURL=ProjectMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectMenu.d.ts","sourceRoot":"","sources":["../src/ProjectMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGzD,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAkB,GACnB,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,
|
|
1
|
+
{"version":3,"file":"ProjectMenu.d.ts","sourceRoot":"","sources":["../src/ProjectMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGzD,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,UAAU,EACV,OAAO,EACP,MAAM,EACN,MAAM,EACN,UAAkB,GACnB,EAAE;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,IAC2B,SAAS,OAAO,uBAmE3C;AAED,wBAAsB,oBAAoB,CAAC,EACzC,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,UAAkB,EAClB,OAAe,GAChB,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,GAAG,OAAO,CAAC;IACV,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,MAAM,EAAE,iBAAiB,EAAE,CAAA;IAC3B,aAAa,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC9C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACxD,CAAC,CAqBD;AAwDD,wBAAsB,WAAW,CAAC,EAChC,UAAU,EACV,OAAO,EACP,MAAM,EACN,MAAM,EACN,QAAsB,EACtB,WAAW,EACX,QAAQ,EACR,IAA0E,EAC1E,WAAe,EACf,UAAkB,EAClB,OAAe,GAChB,EAAE,gBAAgB,wCAiClB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
import type { Project, CustomFieldSchema } from "./types";
|
|
2
3
|
export interface ProjectMenuClientProps {
|
|
3
4
|
/**
|
|
@@ -42,5 +43,5 @@ export interface ProjectMenuClientProps {
|
|
|
42
43
|
font?: string;
|
|
43
44
|
maxProjects?: number;
|
|
44
45
|
}
|
|
45
|
-
export declare function ProjectMenuClient({ dataUrl, clientSlug, apiBase, apiKey, menuId, noCache, projects: projectsProp, schema: schemaProp, filterOptions: filterOptionsProp, filterFieldKey: filterFieldKeyProp, filterFieldName: filterFieldNameProp, fieldOptionsMap: fieldOptionsMapProp, subtitle, basePath, viewAllPath, font, maxProjects, }: ProjectMenuClientProps):
|
|
46
|
+
export declare function ProjectMenuClient({ dataUrl, clientSlug, apiBase, apiKey, menuId, noCache, projects: projectsProp, schema: schemaProp, filterOptions: filterOptionsProp, filterFieldKey: filterFieldKeyProp, filterFieldName: filterFieldNameProp, fieldOptionsMap: fieldOptionsMapProp, subtitle, basePath, viewAllPath, font, maxProjects, }: ProjectMenuClientProps): React.JSX.Element;
|
|
46
47
|
//# sourceMappingURL=ProjectMenuClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectMenuClient.d.ts","sourceRoot":"","sources":["../src/ProjectMenuClient.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectMenuClient.d.ts","sourceRoot":"","sources":["../src/ProjectMenuClient.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,SAAS,CAAA;AAa3E,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gFAAgF;IAChF,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC5B,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC/C,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAkBD,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,UAAU,EACV,OAAO,EACP,MAAM,EACN,MAAM,EACN,OAAe,EACf,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,UAAU,EAClB,aAAa,EAAE,iBAAiB,EAChC,cAAc,EAAE,kBAAkB,EAClC,eAAe,EAAE,mBAAoC,EACrD,eAAe,EAAE,mBAAwB,EACzC,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,IAAmB,EACnB,WAAe,GAChB,EAAE,sBAAsB,qBAqfxB"}
|
|
@@ -25,12 +25,15 @@ export interface ProjectPortfolioProps {
|
|
|
25
25
|
*/
|
|
26
26
|
noCache?: boolean;
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
28
|
+
* Pre-filter projects by any custom field value before rendering.
|
|
29
|
+
* e.g. filterBy={{ field: "side", value: "architectural" }}
|
|
30
|
+
* Projects where the field value equals the given value OR "both" are shown.
|
|
31
|
+
* When omitted all projects are shown.
|
|
32
32
|
*/
|
|
33
|
-
|
|
33
|
+
filterBy?: {
|
|
34
|
+
field: string;
|
|
35
|
+
value: string;
|
|
36
|
+
};
|
|
34
37
|
}
|
|
35
38
|
/**
|
|
36
39
|
* ProjectPortfolio — pure self-fetching card grid.
|
|
@@ -47,5 +50,5 @@ export interface ProjectPortfolioProps {
|
|
|
47
50
|
* apiBase="https://your-api.com"
|
|
48
51
|
* />
|
|
49
52
|
*/
|
|
50
|
-
export declare function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath, searchParams, revalidate, noCache,
|
|
53
|
+
export declare function ProjectPortfolio({ clientSlug, apiBase, apiKey, basePath, searchParams, revalidate, noCache, filterBy, }: ProjectPortfolioProps): Promise<import("react").JSX.Element>;
|
|
51
54
|
//# 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;IACjB;;;;;OAKG;IACH,
|
|
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,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;AA0ED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CAAC,EACrC,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,YAAiB,EACjB,UAAe,EACf,OAAe,EACf,QAAQ,GACT,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, filterBy, }) {
|
|
69
69
|
// Parse filter[key]=value from searchParams into { key: value }
|
|
70
70
|
const filters = {};
|
|
71
71
|
Object.entries(searchParams).forEach(([key, val]) => {
|
|
@@ -77,8 +77,12 @@ 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 =
|
|
81
|
-
? projects.filter((p) =>
|
|
80
|
+
const visible = filterBy
|
|
81
|
+
? projects.filter((p) => {
|
|
82
|
+
var _a;
|
|
83
|
+
const v = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a[filterBy.field];
|
|
84
|
+
return v === filterBy.value || v === "both";
|
|
85
|
+
})
|
|
82
86
|
: projects;
|
|
83
87
|
const hasFilters = Object.keys(filters).length > 0;
|
|
84
88
|
const activeFilterLabels = Object.entries(filters)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
1
2
|
export interface ProjectPortfolioClientProps {
|
|
2
3
|
/** Client slug identifying which client's projects to load */
|
|
3
4
|
clientSlug: string;
|
|
@@ -19,12 +20,15 @@ export interface ProjectPortfolioClientProps {
|
|
|
19
20
|
/** Max columns in the grid. 2 or 3. Defaults to 3 */
|
|
20
21
|
columns?: 2 | 3;
|
|
21
22
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Pre-filter projects by any custom field value before rendering.
|
|
24
|
+
* e.g. filterBy={{ field: "side", value: "architectural" }}
|
|
25
|
+
* Projects where the field value equals the given value OR "both" are shown.
|
|
26
|
+
* When omitted all projects are shown.
|
|
26
27
|
*/
|
|
27
|
-
|
|
28
|
+
filterBy?: {
|
|
29
|
+
field: string;
|
|
30
|
+
value: string;
|
|
31
|
+
};
|
|
28
32
|
}
|
|
29
|
-
export declare function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath, filters, font, columns,
|
|
33
|
+
export declare function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath, filters, font, columns, filterBy, }: ProjectPortfolioClientProps): React.JSX.Element;
|
|
30
34
|
//# sourceMappingURL=ProjectPortfolioClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectPortfolioClient.d.ts","sourceRoot":"","sources":["../src/ProjectPortfolioClient.tsx"],"names":[],"mappings":"
|
|
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,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;AAyDD,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAsB,EACtB,OAAY,EACZ,IAAmB,EACnB,OAAW,EACX,QAAQ,GACT,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, filterBy, }) {
|
|
43
43
|
const [data, setData] = useState(null);
|
|
44
44
|
useEffect(() => {
|
|
45
45
|
const cacheKey = `${clientSlug}:${apiBase}:${apiKey}`;
|
|
@@ -90,14 +90,18 @@ export function ProjectPortfolioClient({ clientSlug, apiBase, apiKey, basePath =
|
|
|
90
90
|
const filteredProjects = useMemo(() => {
|
|
91
91
|
if (!data)
|
|
92
92
|
return [];
|
|
93
|
-
const
|
|
94
|
-
? data.projects.filter((p) =>
|
|
93
|
+
const byField = filterBy
|
|
94
|
+
? data.projects.filter((p) => {
|
|
95
|
+
var _a;
|
|
96
|
+
const v = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a[filterBy.field];
|
|
97
|
+
return v === filterBy.value || v === "both";
|
|
98
|
+
})
|
|
95
99
|
: data.projects;
|
|
96
100
|
const hasActiveFilters = Object.values(filters).some(Boolean);
|
|
97
101
|
if (!hasActiveFilters)
|
|
98
|
-
return
|
|
99
|
-
return
|
|
100
|
-
}, [data, filters,
|
|
102
|
+
return byField;
|
|
103
|
+
return byField.filter((p) => matchesFilters(p, filters, data.schema, data.fieldOptionsMap));
|
|
104
|
+
}, [data, filters, filterBy]);
|
|
101
105
|
const gridCols = columns === 2
|
|
102
106
|
? "repeat(2, 1fr)"
|
|
103
107
|
: "repeat(3, 1fr)";
|
|
@@ -44,12 +44,15 @@ export interface SimilarProjectsProps {
|
|
|
44
44
|
/** Small label above the heading. Defaults to "More Work" */
|
|
45
45
|
subtitle?: string;
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
47
|
+
* Pre-filter projects by any custom field value before rendering.
|
|
48
|
+
* e.g. filterBy={{ field: "side", value: "architectural" }}
|
|
49
|
+
* Projects where the field value equals the given value OR "both" are shown.
|
|
50
|
+
* When omitted all projects are shown.
|
|
51
51
|
*/
|
|
52
|
-
|
|
52
|
+
filterBy?: {
|
|
53
|
+
field: string;
|
|
54
|
+
value: string;
|
|
55
|
+
};
|
|
53
56
|
}
|
|
54
|
-
export declare function SimilarProjects({ filters, excludeSlug, clientSlug, apiBase, apiKey, basePath, maxItems, revalidate, noCache, variant, projectSlugs, title, subtitle,
|
|
57
|
+
export declare function SimilarProjects({ filters, excludeSlug, clientSlug, apiBase, apiKey, basePath, maxItems, revalidate, noCache, variant, projectSlugs, title, subtitle, filterBy, }: SimilarProjectsProps): Promise<import("react").JSX.Element | null>;
|
|
55
58
|
//# 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;IACjB;;;;;OAKG;IACH,
|
|
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,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C;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,QAAQ,GACT,EAAE,oBAAoB,+CA4KtB"}
|
package/dist/SimilarProjects.js
CHANGED
|
@@ -49,11 +49,15 @@ 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",
|
|
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", filterBy, }) {
|
|
53
53
|
const { allProjects: allProjectsRaw, schema, fieldOptionsMap } = await fetchSimilarData(apiBase, clientSlug, apiKey, revalidate, noCache);
|
|
54
|
-
// Apply
|
|
55
|
-
const allProjects =
|
|
56
|
-
? allProjectsRaw.filter((p) =>
|
|
54
|
+
// Apply filterBy before any other filtering
|
|
55
|
+
const allProjects = filterBy
|
|
56
|
+
? allProjectsRaw.filter((p) => {
|
|
57
|
+
var _a;
|
|
58
|
+
const v = (_a = p.custom_field_values) === null || _a === void 0 ? void 0 : _a[filterBy.field];
|
|
59
|
+
return v === filterBy.value || v === "both";
|
|
60
|
+
})
|
|
57
61
|
: allProjectsRaw;
|
|
58
62
|
const badgeField = schema.find((f) => f.display_position === "badge_overlay");
|
|
59
63
|
const locationField = schema.find((f) => f.type === "location");
|
package/dist/types.d.ts
CHANGED
|
@@ -39,8 +39,6 @@ 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";
|
|
44
42
|
custom_field_values: Record<string, CustomFieldValue>;
|
|
45
43
|
created_at: string;
|
|
46
44
|
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
|
|
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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chiselandco/nexus",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
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
|
-
"keywords": [
|
|
5
|
+
"keywords": [
|
|
6
|
+
"nextjs",
|
|
7
|
+
"react",
|
|
8
|
+
"portfolio",
|
|
9
|
+
"projects",
|
|
10
|
+
"megamenu",
|
|
11
|
+
"gallery",
|
|
12
|
+
"filtering",
|
|
13
|
+
"chiselandco",
|
|
14
|
+
"nexus"
|
|
15
|
+
],
|
|
6
16
|
"license": "MIT",
|
|
7
17
|
"type": "module",
|
|
8
18
|
"main": "./dist/index.js",
|
|
@@ -14,7 +24,9 @@
|
|
|
14
24
|
"types": "./dist/index.d.ts"
|
|
15
25
|
}
|
|
16
26
|
},
|
|
17
|
-
"files": [
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
18
30
|
"scripts": {
|
|
19
31
|
"build": "tsc",
|
|
20
32
|
"prepublishOnly": "npm run build"
|
|
@@ -25,6 +37,7 @@
|
|
|
25
37
|
"react-dom": ">=18.0.0"
|
|
26
38
|
},
|
|
27
39
|
"devDependencies": {
|
|
40
|
+
"@types/node": "^26.0.0",
|
|
28
41
|
"@types/react": "^18.0.0",
|
|
29
42
|
"@types/react-dom": "^18.0.0",
|
|
30
43
|
"next": "^15.0.0",
|