@chiselandco/nexus 2.2.6 → 2.2.7
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 +18 -18
- package/dist/ProjectDetail.d.ts.map +1 -1
- package/dist/ProjectDetail.js +13 -2
- package/dist/ProjectMenu.d.ts +1 -1
- package/dist/ProjectMenu.js +1 -1
- package/dist/ProjectPortfolio.d.ts +1 -1
- package/dist/ProjectPortfolio.js +1 -1
- package/dist/SimilarProjects.d.ts.map +1 -1
- package/package.json +2 -5
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @chiselandco/nexus
|
|
2
2
|
|
|
3
3
|
A suite of self-contained project portfolio components for Next.js App Router. Drop in a `clientSlug` and `apiBase` — each component fetches, caches, and renders everything it needs with zero client-side waterfall requests.
|
|
4
4
|
|
|
@@ -12,7 +12,7 @@ No other dependencies required.
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
npm install
|
|
15
|
+
npm install @chiselandco/nexus
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
---
|
|
@@ -23,7 +23,7 @@ Here is the most common full setup — a projects grid page, a detail page with
|
|
|
23
23
|
|
|
24
24
|
```tsx
|
|
25
25
|
// app/projects/page.tsx
|
|
26
|
-
import { ProjectPortfolio } from "
|
|
26
|
+
import { ProjectPortfolio } from "@chiselandco/nexus"
|
|
27
27
|
|
|
28
28
|
export default async function ProjectsPage({
|
|
29
29
|
searchParams,
|
|
@@ -43,7 +43,7 @@ export default async function ProjectsPage({
|
|
|
43
43
|
|
|
44
44
|
```tsx
|
|
45
45
|
// app/projects/[slug]/page.tsx
|
|
46
|
-
import { ProjectDetail, SimilarProjects } from "
|
|
46
|
+
import { ProjectDetail, SimilarProjects } from "@chiselandco/nexus"
|
|
47
47
|
|
|
48
48
|
export default async function ProjectPage({ params }: { params: { slug: string } }) {
|
|
49
49
|
return (
|
|
@@ -74,7 +74,7 @@ export default async function ProjectPage({ params }: { params: { slug: string }
|
|
|
74
74
|
|
|
75
75
|
```ts
|
|
76
76
|
// app/api/chisel-menu/route.ts
|
|
77
|
-
import { createMenuHandler } from "
|
|
77
|
+
import { createMenuHandler } from "@chiselandco/nexus"
|
|
78
78
|
|
|
79
79
|
export const GET = createMenuHandler({
|
|
80
80
|
clientSlug: "your-client-slug",
|
|
@@ -85,7 +85,7 @@ export const GET = createMenuHandler({
|
|
|
85
85
|
```tsx
|
|
86
86
|
// components/Nav.tsx — "use client" component in your header
|
|
87
87
|
"use client"
|
|
88
|
-
import { ProjectMenuClient } from "
|
|
88
|
+
import { ProjectMenuClient } from "@chiselandco/nexus"
|
|
89
89
|
|
|
90
90
|
export function Nav() {
|
|
91
91
|
return (
|
|
@@ -111,7 +111,7 @@ A full server-rendered project grid page. Fetches all projects for a client and
|
|
|
111
111
|
|
|
112
112
|
```tsx
|
|
113
113
|
// app/projects/page.tsx
|
|
114
|
-
import { ProjectPortfolio } from "
|
|
114
|
+
import { ProjectPortfolio } from "@chiselandco/nexus"
|
|
115
115
|
|
|
116
116
|
export default async function ProjectsPage({
|
|
117
117
|
searchParams,
|
|
@@ -158,7 +158,7 @@ A `"use client"` version of the project grid. Fetches all projects once on mount
|
|
|
158
158
|
|
|
159
159
|
```tsx
|
|
160
160
|
// Works in any component — no RSC required
|
|
161
|
-
import { ProjectPortfolioClient } from "
|
|
161
|
+
import { ProjectPortfolioClient } from "@chiselandco/nexus"
|
|
162
162
|
|
|
163
163
|
export default function ProjectsPage() {
|
|
164
164
|
return (
|
|
@@ -178,7 +178,7 @@ Wire up your own dropdowns, buttons, or search inputs using the `filters` prop.
|
|
|
178
178
|
```tsx
|
|
179
179
|
"use client"
|
|
180
180
|
import { useState } from "react"
|
|
181
|
-
import { ProjectPortfolioClient } from "
|
|
181
|
+
import { ProjectPortfolioClient } from "@chiselandco/nexus"
|
|
182
182
|
|
|
183
183
|
export default function ProjectsPage() {
|
|
184
184
|
const [filters, setFilters] = useState<Record<string, string>>({})
|
|
@@ -220,7 +220,7 @@ A full server-rendered project detail page. Fetches a single project by slug and
|
|
|
220
220
|
|
|
221
221
|
```tsx
|
|
222
222
|
// app/projects/[slug]/page.tsx
|
|
223
|
-
import { ProjectDetail } from "
|
|
223
|
+
import { ProjectDetail } from "@chiselandco/nexus"
|
|
224
224
|
|
|
225
225
|
export default async function ProjectPage({ params }: { params: { slug: string } }) {
|
|
226
226
|
return (
|
|
@@ -283,7 +283,7 @@ A `"use client"` image carousel with previous/next arrows, a counter badge, and
|
|
|
283
283
|
|
|
284
284
|
```tsx
|
|
285
285
|
"use client"
|
|
286
|
-
import { GalleryCarousel } from "
|
|
286
|
+
import { GalleryCarousel } from "@chiselandco/nexus"
|
|
287
287
|
|
|
288
288
|
// `media` is the array of image objects returned by the projects API
|
|
289
289
|
export function ProjectGallery({ media, title }: { media: Media[]; title: string }) {
|
|
@@ -311,7 +311,7 @@ A server-rendered similar projects section. Fetches all projects for a client, f
|
|
|
311
311
|
|
|
312
312
|
```tsx
|
|
313
313
|
// app/projects/[slug]/page.tsx
|
|
314
|
-
import { ProjectDetail, SimilarProjects } from "
|
|
314
|
+
import { ProjectDetail, SimilarProjects } from "@chiselandco/nexus"
|
|
315
315
|
|
|
316
316
|
export default async function ProjectPage({ params }: { params: { slug: string } }) {
|
|
317
317
|
return (
|
|
@@ -339,7 +339,7 @@ In most real-world cases you want to match similar projects based on the current
|
|
|
339
339
|
|
|
340
340
|
```tsx
|
|
341
341
|
// app/projects/[slug]/page.tsx
|
|
342
|
-
import { ProjectDetail, SimilarProjects } from "
|
|
342
|
+
import { ProjectDetail, SimilarProjects } from "@chiselandco/nexus"
|
|
343
343
|
|
|
344
344
|
async function getProject(slug: string, clientSlug: string, apiBase: string) {
|
|
345
345
|
const res = await fetch(
|
|
@@ -378,7 +378,7 @@ This is the recommended approach for most client sites. The slugs are hardcoded
|
|
|
378
378
|
|
|
379
379
|
```tsx
|
|
380
380
|
// app/projects/[slug]/page.tsx
|
|
381
|
-
import { ProjectDetail, SimilarProjects } from "
|
|
381
|
+
import { ProjectDetail, SimilarProjects } from "@chiselandco/nexus"
|
|
382
382
|
|
|
383
383
|
export default async function ProjectPage({ params }: { params: { slug: string } }) {
|
|
384
384
|
return (
|
|
@@ -451,7 +451,7 @@ A server-rendered megamenu component. Shows featured projects as compact cards o
|
|
|
451
451
|
|
|
452
452
|
```tsx
|
|
453
453
|
// components/MegaMenu.tsx
|
|
454
|
-
import { ProjectMenu } from "
|
|
454
|
+
import { ProjectMenu } from "@chiselandco/nexus"
|
|
455
455
|
|
|
456
456
|
// Must be a Server Component — do NOT add "use client"
|
|
457
457
|
export async function ProjectsMegaMenu() {
|
|
@@ -509,7 +509,7 @@ Create one API route once. The data is server-cached for 24 hours — most users
|
|
|
509
509
|
|
|
510
510
|
```ts
|
|
511
511
|
// app/api/chisel-menu/route.ts
|
|
512
|
-
import { createMenuHandler } from "
|
|
512
|
+
import { createMenuHandler } from "@chiselandco/nexus"
|
|
513
513
|
|
|
514
514
|
export const GET = createMenuHandler({
|
|
515
515
|
clientSlug: "your-client-slug",
|
|
@@ -533,7 +533,7 @@ Then pass `dataUrl` to the component:
|
|
|
533
533
|
```tsx
|
|
534
534
|
// components/Nav.tsx
|
|
535
535
|
"use client"
|
|
536
|
-
import { ProjectMenuClient } from "
|
|
536
|
+
import { ProjectMenuClient } from "@chiselandco/nexus"
|
|
537
537
|
|
|
538
538
|
export function Nav() {
|
|
539
539
|
return (
|
|
@@ -556,7 +556,7 @@ No API route needed. The component fetches directly from the upstream API on fir
|
|
|
556
556
|
|
|
557
557
|
```tsx
|
|
558
558
|
"use client"
|
|
559
|
-
import { ProjectMenuClient } from "
|
|
559
|
+
import { ProjectMenuClient } from "@chiselandco/nexus"
|
|
560
560
|
|
|
561
561
|
export function Nav() {
|
|
562
562
|
return (
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectDetail.d.ts","sourceRoot":"","sources":["../src/ProjectDetail.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectDetail.d.ts","sourceRoot":"","sources":["../src/ProjectDetail.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAA;IAClB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,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;AAoED,wBAAsB,aAAa,CAAC,EAClC,IAAI,EACJ,UAAU,EACV,OAAO,EACP,QAAsB,EACtB,SAA0B,EAC1B,UAAe,EACf,OAAe,GAChB,EAAE,kBAAkB,oDAgRpB"}
|
package/dist/ProjectDetail.js
CHANGED
|
@@ -133,7 +133,18 @@ export async function ProjectDetail({ slug, clientSlug, apiBase, backPath = "/pr
|
|
|
133
133
|
.map((key) => schema.find((f) => f.key === key))
|
|
134
134
|
.filter((f) => f !== undefined);
|
|
135
135
|
const font = "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif";
|
|
136
|
-
return (_jsxs("main", { style: { minHeight: "100vh", backgroundColor: "#fff", fontFamily: font }, children: [_jsxs("section", { className: "chisel-hero-img", style: { position: "relative", width: "100%", overflow: "hidden" }, children: [imageUrl ? (_jsx("img", { src: imageUrl, alt: project.title, style: { width: "100%", height: "100%", objectFit: "cover", display: "block" } })) : (_jsx("div", { style: { position: "absolute", inset: 0, backgroundColor: "#27272a" } })), _jsx("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to
|
|
136
|
+
return (_jsxs("main", { style: { minHeight: "100vh", backgroundColor: "#fff", fontFamily: font }, children: [_jsxs("section", { className: "chisel-hero-img", style: { position: "relative", width: "100%", overflow: "hidden" }, children: [imageUrl ? (_jsx("img", { src: imageUrl, alt: project.title, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover", display: "block" } })) : (_jsx("div", { style: { position: "absolute", inset: 0, backgroundColor: "#27272a" } })), _jsx("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to right, rgba(0,0,0,0.82) 0%, rgba(0,0,0,0.55) 45%, rgba(0,0,0,0.15) 100%)" } }), _jsx("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to top, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 60%)" } }), _jsxs("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: "0 clamp(1.5rem, 5vw, 5rem) clamp(2rem, 4vw, 3.5rem)", maxWidth: "760px", boxSizing: "border-box" }, children: [badgeValue && (_jsx("span", { style: {
|
|
137
|
+
display: "inline-block",
|
|
138
|
+
backgroundColor: "#f18a00",
|
|
139
|
+
color: "#fff",
|
|
140
|
+
fontSize: "11px",
|
|
141
|
+
fontWeight: 700,
|
|
142
|
+
textTransform: "uppercase",
|
|
143
|
+
letterSpacing: "0.1em",
|
|
144
|
+
padding: "5px 14px",
|
|
145
|
+
borderRadius: "4px",
|
|
146
|
+
marginBottom: "16px",
|
|
147
|
+
}, children: badgeValue })), _jsx("h1", { style: { color: "#fff", fontWeight: 700, fontSize: "clamp(28px, 4.5vw, 56px)", lineHeight: 1.05, margin: "0 0 16px 0", fontFamily: font, letterSpacing: "-0.02em" }, children: project.title }), locationString && (_jsxs("p", { style: { display: "flex", alignItems: "center", gap: "6px", color: "rgba(255,255,255,0.72)", fontSize: "15px", margin: 0 }, children: [_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", style: { flexShrink: 0 }, children: [_jsx("path", { d: "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z" }), _jsx("circle", { cx: "12", cy: "10", r: "3" })] }), locationString] }))] })] }), metadataStats.length > 0 && (_jsxs("section", { style: { borderBottom: "1px solid #e4e4e7", backgroundColor: "#fff" }, children: [_jsx("style", { children: `
|
|
137
148
|
.chisel-stats-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0; }
|
|
138
149
|
@media (min-width: 640px) { .chisel-stats-grid { grid-template-columns: repeat(3, 1fr); } }
|
|
139
150
|
@media (min-width: 1024px) { .chisel-stats-grid { grid-template-columns: repeat(${Math.min(metadataStats.length, 6)}, 1fr); } }
|
|
@@ -141,7 +152,7 @@ export async function ProjectDetail({ slug, clientSlug, apiBase, backPath = "/pr
|
|
|
141
152
|
.chisel-stat-item:last-child { border-right: none; }
|
|
142
153
|
.chisel-gallery-placeholder { display: grid; grid-template-columns: 1fr; gap: 12px; }
|
|
143
154
|
@media (min-width: 640px) { .chisel-gallery-placeholder { grid-template-columns: repeat(3, 1fr); } }
|
|
144
|
-
.chisel-hero-img { height:
|
|
155
|
+
.chisel-hero-img { height: 56vw; min-height: 340px; max-height: 680px; }
|
|
145
156
|
.chisel-overview-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; }
|
|
146
157
|
@media (min-width: 1024px) { .chisel-overview-grid { grid-template-columns: 1fr 300px; gap: 4rem; align-items: start; } }
|
|
147
158
|
` }), _jsx("div", { style: { maxWidth: "1280px", margin: "0 auto", boxSizing: "border-box", padding: "0 0 0 0" }, className: "chisel-stats-grid", children: metadataStats.map(({ label, value }) => (_jsxs("div", { className: "chisel-stat-item", children: [_jsx("p", { style: { fontSize: "10px", fontWeight: 700, textTransform: "uppercase", letterSpacing: "0.12em", color: "#a1a1aa", margin: "0 0 8px 0" }, children: label }), _jsx("p", { style: { color: "#18181b", fontWeight: 600, fontSize: "15px", margin: 0, lineHeight: 1.4 }, children: value })] }, label))) })] })), _jsxs("article", { style: { maxWidth: "1280px", margin: "0 auto", padding: "3rem 1.5rem", boxSizing: "border-box" }, children: [(project.blurb || project.description || specFields.length > 0) && (_jsxs("section", { style: { marginBottom: "3rem" }, children: [_jsx("div", { style: { borderBottom: "1px solid #e4e4e7", marginBottom: "2rem", paddingBottom: "1rem", display: "flex", alignItems: "baseline", justifyContent: "space-between" }, children: _jsx("h2", { style: { color: "#18181b", fontWeight: 700, fontSize: "20px", margin: 0, letterSpacing: "-0.01em", fontFamily: font }, children: "Project Overview" }) }), _jsxs("div", { className: "chisel-overview-grid", children: [_jsxs("div", { children: [project.blurb && (_jsx("p", { style: { color: "#3f3f46", fontSize: "16px", fontWeight: 400, lineHeight: 1.85, margin: "0 0 20px 0" }, children: project.blurb })), project.description && project.description !== project.blurb && (_jsx("p", { style: { color: "#3f3f46", fontSize: "16px", fontWeight: 400, lineHeight: 1.85, margin: 0 }, children: project.description }))] }), specFields.length > 0 && (_jsx("aside", { style: { borderLeft: "3px solid #f18a00", paddingLeft: "2rem" }, children: _jsx("div", { style: { display: "flex", flexDirection: "column", gap: "2rem" }, children: specFields.map((field) => {
|
package/dist/ProjectMenu.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export interface ProjectMenuProps {
|
|
|
41
41
|
*
|
|
42
42
|
* @example
|
|
43
43
|
* // app/api/chisel-menu/route.ts
|
|
44
|
-
* import { createMenuHandler } from "
|
|
44
|
+
* import { createMenuHandler } from "@chiselandco/nexus"
|
|
45
45
|
* export const GET = createMenuHandler({ clientSlug: "my-client", apiBase: "https://nexus.chiselandco.com" })
|
|
46
46
|
*
|
|
47
47
|
* // Bust the cache manually (one request):
|
package/dist/ProjectMenu.js
CHANGED
|
@@ -16,7 +16,7 @@ const API_KEY = "pk_live_crmsuTIm7NNfb9uEWBCyv88F6kj2YQUR";
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* // app/api/chisel-menu/route.ts
|
|
19
|
-
* import { createMenuHandler } from "
|
|
19
|
+
* import { createMenuHandler } from "@chiselandco/nexus"
|
|
20
20
|
* export const GET = createMenuHandler({ clientSlug: "my-client", apiBase: "https://nexus.chiselandco.com" })
|
|
21
21
|
*
|
|
22
22
|
* // Bust the cache manually (one request):
|
|
@@ -31,7 +31,7 @@ export interface ProjectPortfolioProps {
|
|
|
31
31
|
* - Production: next.revalidate caches across requests for `revalidate` seconds
|
|
32
32
|
*
|
|
33
33
|
* Usage:
|
|
34
|
-
* import { ProjectPortfolio } from "
|
|
34
|
+
* import { ProjectPortfolio } from "@chiselandco/nexus"
|
|
35
35
|
*
|
|
36
36
|
* <ProjectPortfolio
|
|
37
37
|
* clientSlug="my-client"
|
package/dist/ProjectPortfolio.js
CHANGED
|
@@ -58,7 +58,7 @@ const fetchPortfolioData = cache(async (apiBase, clientSlug, revalidate, filters
|
|
|
58
58
|
* - Production: next.revalidate caches across requests for `revalidate` seconds
|
|
59
59
|
*
|
|
60
60
|
* Usage:
|
|
61
|
-
* import { ProjectPortfolio } from "
|
|
61
|
+
* import { ProjectPortfolio } from "@chiselandco/nexus"
|
|
62
62
|
*
|
|
63
63
|
* <ProjectPortfolio
|
|
64
64
|
* clientSlug="my-client"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimilarProjects.d.ts","sourceRoot":"","sources":["../src/SimilarProjects.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SimilarProjects.d.ts","sourceRoot":"","sources":["../src/SimilarProjects.tsx"],"names":[],"mappings":"AAMA,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,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;CAClB;AA+DD,wBAAsB,eAAe,CAAC,EACpC,OAAY,EACZ,WAAW,EACX,UAAU,EACV,OAAO,EACP,QAAsB,EACtB,QAAY,EACZ,UAAe,EACf,OAAe,EACf,OAAgB,EAChB,YAAY,EACZ,KAA0B,EAC1B,QAAsB,GACvB,EAAE,oBAAoB,2DAiKtB"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chiselandco/nexus",
|
|
3
|
-
"version": "2.2.
|
|
4
|
-
"publishConfig": {
|
|
5
|
-
"access": "public"
|
|
6
|
-
},
|
|
3
|
+
"version": "2.2.7",
|
|
7
4
|
"description": "Self-contained project portfolio components for Next.js App Router. Includes ProjectPortfolio, ProjectPortfolioClient (with built-in filtering), ProjectDetail, SimilarProjects, ProjectMenu, ProjectMenuClient, and GalleryCarousel. Pass a clientSlug and apiBase — done.",
|
|
8
|
-
"keywords": ["nextjs", "react", "portfolio", "projects", "megamenu", "gallery", "filtering"],
|
|
5
|
+
"keywords": ["nextjs", "react", "portfolio", "projects", "megamenu", "gallery", "filtering", "chiselandco", "nexus"],
|
|
9
6
|
"license": "MIT",
|
|
10
7
|
"type": "module",
|
|
11
8
|
"main": "./dist/index.js",
|