@pro-laico/payload-dev-tools 0.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/LICENSE.md +22 -0
- package/README.md +9 -0
- package/dist/components/DevToolbar.d.ts +27 -0
- package/dist/components/DevToolbar.d.ts.map +1 -0
- package/dist/components/DevToolbar.js +32 -0
- package/dist/components/DevToolbar.js.map +1 -0
- package/dist/components/DevToolbarClient.d.ts +16 -0
- package/dist/components/DevToolbarClient.d.ts.map +1 -0
- package/dist/components/DevToolbarClient.js +983 -0
- package/dist/components/DevToolbarClient.js.map +1 -0
- package/dist/components/resolveDevChrome.d.ts +33 -0
- package/dist/components/resolveDevChrome.d.ts.map +1 -0
- package/dist/components/resolveDevChrome.js +42 -0
- package/dist/components/resolveDevChrome.js.map +1 -0
- package/dist/components/resolveDevChrome.spec.d.ts +2 -0
- package/dist/components/resolveDevChrome.spec.d.ts.map +1 -0
- package/dist/components/resolveDevChrome.spec.js +98 -0
- package/dist/components/resolveDevChrome.spec.js.map +1 -0
- package/dist/components/styles.d.ts +5 -0
- package/dist/components/styles.d.ts.map +1 -0
- package/dist/components/styles.js +110 -0
- package/dist/components/styles.js.map +1 -0
- package/dist/cookies.d.ts +12 -0
- package/dist/cookies.d.ts.map +1 -0
- package/dist/cookies.js +12 -0
- package/dist/cookies.js.map +1 -0
- package/dist/endpoints/activateIconSet.d.ts +10 -0
- package/dist/endpoints/activateIconSet.d.ts.map +1 -0
- package/dist/endpoints/activateIconSet.js +55 -0
- package/dist/endpoints/activateIconSet.js.map +1 -0
- package/dist/endpoints/dev.d.ts +12 -0
- package/dist/endpoints/dev.d.ts.map +1 -0
- package/dist/endpoints/dev.js +31 -0
- package/dist/endpoints/dev.js.map +1 -0
- package/dist/endpoints/stage.d.ts +14 -0
- package/dist/endpoints/stage.d.ts.map +1 -0
- package/dist/endpoints/stage.js +42 -0
- package/dist/endpoints/stage.js.map +1 -0
- package/dist/harness.d.ts +40 -0
- package/dist/harness.d.ts.map +1 -0
- package/dist/harness.js +30 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/getPayloadClient.d.ts +15 -0
- package/dist/lib/getPayloadClient.d.ts.map +1 -0
- package/dist/lib/getPayloadClient.js +29 -0
- package/dist/lib/getPayloadClient.js.map +1 -0
- package/dist/lib/snapshot.d.ts +89 -0
- package/dist/lib/snapshot.d.ts.map +1 -0
- package/dist/lib/snapshot.js +183 -0
- package/dist/lib/snapshot.js.map +1 -0
- package/dist/next/client.d.ts +27 -0
- package/dist/next/client.d.ts.map +1 -0
- package/dist/next/client.js +275 -0
- package/dist/next/client.js.map +1 -0
- package/dist/next/createDevPage.d.ts +37 -0
- package/dist/next/createDevPage.d.ts.map +1 -0
- package/dist/next/createDevPage.js +287 -0
- package/dist/next/createDevPage.js.map +1 -0
- package/dist/next/pageStyles.d.ts +5 -0
- package/dist/next/pageStyles.d.ts.map +1 -0
- package/dist/next/pageStyles.js +83 -0
- package/dist/next/pageStyles.js.map +1 -0
- package/dist/next/specimen.d.ts +24 -0
- package/dist/next/specimen.d.ts.map +1 -0
- package/dist/next/specimen.js +48 -0
- package/dist/next/specimen.js.map +1 -0
- package/dist/next/views.d.ts +31 -0
- package/dist/next/views.d.ts.map +1 -0
- package/dist/next/views.js +431 -0
- package/dist/next/views.js.map +1 -0
- package/dist/next.d.ts +5 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +6 -0
- package/dist/next.js.map +1 -0
- package/dist/options.d.ts +17 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +3 -0
- package/dist/options.js.map +1 -0
- package/dist/plugin.d.ts +20 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +51 -0
- package/dist/plugin.js.map +1 -0
- package/dist/toolbar.d.ts +8 -0
- package/dist/toolbar.d.ts.map +1 -0
- package/dist/toolbar.js +8 -0
- package/dist/toolbar.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { SeedSnapshot } from '../lib/snapshot';
|
|
2
|
+
import type { SpecimenStyle } from './specimen';
|
|
3
|
+
/** The `/dev` index's seed controls — same flow as the toolbar's Seed view: POST the seed
|
|
4
|
+
* plugin's own endpoint, two-click confirm when destructive, surface `{ error, issues }`. */
|
|
5
|
+
export declare function SeedCard({ seed, adminRoute }: {
|
|
6
|
+
seed: SeedSnapshot;
|
|
7
|
+
adminRoute: string;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
/** The `/dev/fonts` interactive specimen — the sample renders in the family's `--font-set*`
|
|
10
|
+
* variable at the clicked weight/style. Only weights and styles the typeface actually serves
|
|
11
|
+
* are offered. */
|
|
12
|
+
export declare function FontSpecimen({ familyKey, title, cssVar, styles, }: {
|
|
13
|
+
familyKey: string;
|
|
14
|
+
title: string | null;
|
|
15
|
+
cssVar: string;
|
|
16
|
+
styles: SpecimenStyle[];
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
/** The `/dev/icons` set switcher — activates a set via `POST /api/dev/icons/activate` and
|
|
19
|
+
* refreshes, so the grid (and the whole site) re-skins to the newly active set. */
|
|
20
|
+
export declare function IconSetSwitcher({ sets }: {
|
|
21
|
+
sets: {
|
|
22
|
+
id: string | number;
|
|
23
|
+
title: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
}[];
|
|
26
|
+
}): import("react").JSX.Element;
|
|
27
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/next/client.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAI/C;8FAC8F;AAC9F,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,+BAmFxF;AAED;;mBAEmB;AACnB,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,aAAa,EAAE,CAAA;CACxB,+BAkDA;AAED;oFACoF;AACpF,wBAAgB,eAAe,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,EAAE,CAAA;CAAE,+BA0C5G"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useRouter } from "next/navigation";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
/** The `/dev` index's seed controls — same flow as the toolbar's Seed view: POST the seed
|
|
6
|
+
* plugin's own endpoint, two-click confirm when destructive, surface `{ error, issues }`. */ export function SeedCard({ seed, adminRoute }) {
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const [running, setRunning] = useState(false);
|
|
9
|
+
const [confirming, setConfirming] = useState(false);
|
|
10
|
+
const [error, setError] = useState(null);
|
|
11
|
+
const runSeed = async ()=>{
|
|
12
|
+
setRunning(true);
|
|
13
|
+
setError(null);
|
|
14
|
+
try {
|
|
15
|
+
const res = await fetch('/api/seed', {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
credentials: 'include'
|
|
18
|
+
});
|
|
19
|
+
if (res.ok) {
|
|
20
|
+
setConfirming(false);
|
|
21
|
+
router.refresh();
|
|
22
|
+
} else {
|
|
23
|
+
const body = await res.json().catch(()=>null);
|
|
24
|
+
setError(body?.error ? body : {
|
|
25
|
+
error: `Seed failed (HTTP ${res.status}).`
|
|
26
|
+
});
|
|
27
|
+
setConfirming(false);
|
|
28
|
+
}
|
|
29
|
+
} catch {
|
|
30
|
+
setError({
|
|
31
|
+
error: 'Seed request failed — is the dev server running?'
|
|
32
|
+
});
|
|
33
|
+
setConfirming(false);
|
|
34
|
+
}
|
|
35
|
+
setRunning(false);
|
|
36
|
+
};
|
|
37
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
38
|
+
className: "pdtp-card",
|
|
39
|
+
children: [
|
|
40
|
+
/*#__PURE__*/ _jsxs("h2", {
|
|
41
|
+
children: [
|
|
42
|
+
seed.seeded ? `Seeded — ${seed.totalDocs} docs` : 'Not seeded',
|
|
43
|
+
!seed.enabled ? /*#__PURE__*/ _jsx("span", {
|
|
44
|
+
className: "pdtp-kind pdtp-warn",
|
|
45
|
+
children: "locked"
|
|
46
|
+
}) : /*#__PURE__*/ _jsx("span", {
|
|
47
|
+
className: "pdtp-kind",
|
|
48
|
+
children: "seed"
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
}),
|
|
52
|
+
/*#__PURE__*/ _jsx("table", {
|
|
53
|
+
className: "pdtp-table",
|
|
54
|
+
children: /*#__PURE__*/ _jsx("tbody", {
|
|
55
|
+
children: seed.definitions.map((d)=>/*#__PURE__*/ _jsxs("tr", {
|
|
56
|
+
children: [
|
|
57
|
+
/*#__PURE__*/ _jsxs("td", {
|
|
58
|
+
children: [
|
|
59
|
+
d.slug,
|
|
60
|
+
d.disabled ? /*#__PURE__*/ _jsx("span", {
|
|
61
|
+
className: "pdtp-warn",
|
|
62
|
+
children: " · skipped"
|
|
63
|
+
}) : null
|
|
64
|
+
]
|
|
65
|
+
}),
|
|
66
|
+
/*#__PURE__*/ _jsx("td", {
|
|
67
|
+
children: d.kind === 'global' ? 'global' : seed.counts[d.slug] ?? 0
|
|
68
|
+
})
|
|
69
|
+
]
|
|
70
|
+
}, d.slug))
|
|
71
|
+
})
|
|
72
|
+
}),
|
|
73
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
74
|
+
style: {
|
|
75
|
+
marginTop: 12,
|
|
76
|
+
display: 'flex',
|
|
77
|
+
gap: 8
|
|
78
|
+
},
|
|
79
|
+
children: [
|
|
80
|
+
/*#__PURE__*/ _jsx("button", {
|
|
81
|
+
type: "button",
|
|
82
|
+
className: `pdtp-btn ${seed.seeded ? 'pdtp-btn-danger' : 'pdtp-btn-primary'}`,
|
|
83
|
+
disabled: running,
|
|
84
|
+
onClick: ()=>seed.seeded && !confirming ? setConfirming(true) : void runSeed(),
|
|
85
|
+
children: running ? 'Seeding…' : confirming ? 'Destructive — click again' : seed.seeded ? 'Reseed' : 'Seed the database'
|
|
86
|
+
}),
|
|
87
|
+
confirming ? /*#__PURE__*/ _jsx("button", {
|
|
88
|
+
type: "button",
|
|
89
|
+
className: "pdtp-btn",
|
|
90
|
+
onClick: ()=>setConfirming(false),
|
|
91
|
+
children: "Cancel"
|
|
92
|
+
}) : null
|
|
93
|
+
]
|
|
94
|
+
}),
|
|
95
|
+
!seed.enabled ? /*#__PURE__*/ _jsxs("p", {
|
|
96
|
+
className: "pdtp-note",
|
|
97
|
+
children: [
|
|
98
|
+
"Set ",
|
|
99
|
+
/*#__PURE__*/ _jsx("span", {
|
|
100
|
+
className: "pdtp-code",
|
|
101
|
+
children: "ENABLE_SEED=true"
|
|
102
|
+
}),
|
|
103
|
+
" in ",
|
|
104
|
+
/*#__PURE__*/ _jsx("span", {
|
|
105
|
+
className: "pdtp-code",
|
|
106
|
+
children: ".env.local"
|
|
107
|
+
}),
|
|
108
|
+
" — the seed wipes seeded collections, so it's off by default."
|
|
109
|
+
]
|
|
110
|
+
}) : null,
|
|
111
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
112
|
+
className: "pdtp-note",
|
|
113
|
+
children: [
|
|
114
|
+
"Needs a logged-in ",
|
|
115
|
+
/*#__PURE__*/ _jsx("a", {
|
|
116
|
+
href: adminRoute,
|
|
117
|
+
children: "admin"
|
|
118
|
+
}),
|
|
119
|
+
" user · CLI: ",
|
|
120
|
+
/*#__PURE__*/ _jsx("span", {
|
|
121
|
+
className: "pdtp-code",
|
|
122
|
+
children: "ENABLE_SEED=true pnpm seed"
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
}),
|
|
126
|
+
error ? /*#__PURE__*/ _jsxs("div", {
|
|
127
|
+
className: "pdtp-error",
|
|
128
|
+
children: [
|
|
129
|
+
error.error,
|
|
130
|
+
error.issues?.length ? /*#__PURE__*/ _jsx("ul", {
|
|
131
|
+
children: error.issues.map((issue)=>/*#__PURE__*/ _jsx("li", {
|
|
132
|
+
children: issue
|
|
133
|
+
}, issue))
|
|
134
|
+
}) : null
|
|
135
|
+
]
|
|
136
|
+
}) : null
|
|
137
|
+
]
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/** The `/dev/fonts` interactive specimen — the sample renders in the family's `--font-set*`
|
|
141
|
+
* variable at the clicked weight/style. Only weights and styles the typeface actually serves
|
|
142
|
+
* are offered. */ export function FontSpecimen({ familyKey, title, cssVar, styles }) {
|
|
143
|
+
const [styleIdx, setStyleIdx] = useState(0);
|
|
144
|
+
const current = styles[Math.min(styleIdx, styles.length - 1)];
|
|
145
|
+
const [weight, setWeight] = useState(current?.weights.includes(400) ? 400 : current?.weights[0] ?? 400);
|
|
146
|
+
const pickStyle = (idx)=>{
|
|
147
|
+
setStyleIdx(idx);
|
|
148
|
+
const next = styles[idx];
|
|
149
|
+
if (next && !next.weights.includes(weight)) setWeight(next.weights.includes(400) ? 400 : next.weights[0] ?? 400);
|
|
150
|
+
};
|
|
151
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
152
|
+
className: "pdtp-specimen",
|
|
153
|
+
children: [
|
|
154
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
155
|
+
className: "pdtp-specimen-head",
|
|
156
|
+
children: [
|
|
157
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
158
|
+
children: [
|
|
159
|
+
/*#__PURE__*/ _jsx("span", {
|
|
160
|
+
className: "pdtp-code",
|
|
161
|
+
children: familyKey
|
|
162
|
+
}),
|
|
163
|
+
' ',
|
|
164
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
165
|
+
className: "pdtp-kind",
|
|
166
|
+
style: {
|
|
167
|
+
marginLeft: 6
|
|
168
|
+
},
|
|
169
|
+
children: [
|
|
170
|
+
title ?? 'slot unset — fallback stack',
|
|
171
|
+
current ? ` · ${current.label}` : ''
|
|
172
|
+
]
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
}),
|
|
176
|
+
styles.length > 1 ? /*#__PURE__*/ _jsx("span", {
|
|
177
|
+
className: "pdtp-seg",
|
|
178
|
+
children: styles.map((s, idx)=>/*#__PURE__*/ _jsx("button", {
|
|
179
|
+
type: "button",
|
|
180
|
+
className: idx === styleIdx ? 'pdtp-active' : '',
|
|
181
|
+
onClick: ()=>pickStyle(idx),
|
|
182
|
+
children: s.style === 'normal' ? 'upright' : 'italic'
|
|
183
|
+
}, s.style))
|
|
184
|
+
}) : current ? /*#__PURE__*/ _jsx("span", {
|
|
185
|
+
className: "pdtp-kind",
|
|
186
|
+
children: current.style === 'normal' ? 'upright only' : 'italic only'
|
|
187
|
+
}) : null
|
|
188
|
+
]
|
|
189
|
+
}),
|
|
190
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
191
|
+
style: {
|
|
192
|
+
fontFamily: cssVar,
|
|
193
|
+
fontWeight: weight,
|
|
194
|
+
fontStyle: current?.style ?? 'normal'
|
|
195
|
+
},
|
|
196
|
+
children: [
|
|
197
|
+
/*#__PURE__*/ _jsx("p", {
|
|
198
|
+
className: "pdtp-specimen-big",
|
|
199
|
+
children: "The quick brown fox jumps over the lazy dog."
|
|
200
|
+
}),
|
|
201
|
+
/*#__PURE__*/ _jsx("p", {
|
|
202
|
+
className: "pdtp-specimen-body",
|
|
203
|
+
children: "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 — 1,234.56 · «fi ffi» ?!&"
|
|
204
|
+
})
|
|
205
|
+
]
|
|
206
|
+
}),
|
|
207
|
+
current ? /*#__PURE__*/ _jsx("div", {
|
|
208
|
+
className: "pdtp-chips",
|
|
209
|
+
style: {
|
|
210
|
+
marginTop: 14
|
|
211
|
+
},
|
|
212
|
+
children: current.weights.map((w)=>/*#__PURE__*/ _jsx("button", {
|
|
213
|
+
type: "button",
|
|
214
|
+
className: `pdtp-chip ${w === weight ? 'pdtp-active' : ''}`,
|
|
215
|
+
onClick: ()=>setWeight(w),
|
|
216
|
+
children: w
|
|
217
|
+
}, w))
|
|
218
|
+
}) : null
|
|
219
|
+
]
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/** The `/dev/icons` set switcher — activates a set via `POST /api/dev/icons/activate` and
|
|
223
|
+
* refreshes, so the grid (and the whole site) re-skins to the newly active set. */ export function IconSetSwitcher({ sets }) {
|
|
224
|
+
const router = useRouter();
|
|
225
|
+
const [busy, setBusy] = useState(null);
|
|
226
|
+
const [error, setError] = useState(null);
|
|
227
|
+
const activate = async (id)=>{
|
|
228
|
+
setBusy(id);
|
|
229
|
+
setError(null);
|
|
230
|
+
try {
|
|
231
|
+
const res = await fetch('/api/dev/icons/activate', {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
credentials: 'include',
|
|
234
|
+
headers: {
|
|
235
|
+
'content-type': 'application/json'
|
|
236
|
+
},
|
|
237
|
+
body: JSON.stringify({
|
|
238
|
+
id
|
|
239
|
+
})
|
|
240
|
+
});
|
|
241
|
+
if (res.ok) router.refresh();
|
|
242
|
+
else setError((await res.json().catch(()=>null))?.error ?? `Failed (HTTP ${res.status}).`);
|
|
243
|
+
} catch {
|
|
244
|
+
setError('Request failed — is the dev server running?');
|
|
245
|
+
}
|
|
246
|
+
setBusy(null);
|
|
247
|
+
};
|
|
248
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
249
|
+
children: [
|
|
250
|
+
/*#__PURE__*/ _jsx("div", {
|
|
251
|
+
style: {
|
|
252
|
+
display: 'flex',
|
|
253
|
+
flexWrap: 'wrap',
|
|
254
|
+
gap: 8
|
|
255
|
+
},
|
|
256
|
+
children: sets.map((set)=>/*#__PURE__*/ _jsxs("button", {
|
|
257
|
+
type: "button",
|
|
258
|
+
className: `pdtp-btn ${set.active ? 'pdtp-btn-primary' : ''}`,
|
|
259
|
+
disabled: busy !== null || set.active,
|
|
260
|
+
onClick: ()=>void activate(set.id),
|
|
261
|
+
children: [
|
|
262
|
+
busy === set.id ? 'Activating…' : set.title,
|
|
263
|
+
set.active ? ' ✓' : ''
|
|
264
|
+
]
|
|
265
|
+
}, set.id))
|
|
266
|
+
}),
|
|
267
|
+
error ? /*#__PURE__*/ _jsx("div", {
|
|
268
|
+
className: "pdtp-error",
|
|
269
|
+
children: error
|
|
270
|
+
}) : null
|
|
271
|
+
]
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/client.tsx"],"sourcesContent":["'use client'\n\nimport { useRouter } from 'next/navigation'\nimport { useState } from 'react'\nimport type { SeedSnapshot } from '../lib/snapshot'\nimport type { SpecimenStyle } from './specimen'\n\ntype SeedError = { error: string; issues?: string[] }\n\n/** The `/dev` index's seed controls — same flow as the toolbar's Seed view: POST the seed\n * plugin's own endpoint, two-click confirm when destructive, surface `{ error, issues }`. */\nexport function SeedCard({ seed, adminRoute }: { seed: SeedSnapshot; adminRoute: string }) {\n const router = useRouter()\n const [running, setRunning] = useState(false)\n const [confirming, setConfirming] = useState(false)\n const [error, setError] = useState<SeedError | null>(null)\n\n const runSeed = async () => {\n setRunning(true)\n setError(null)\n try {\n const res = await fetch('/api/seed', { method: 'POST', credentials: 'include' })\n if (res.ok) {\n setConfirming(false)\n router.refresh()\n } else {\n const body = (await res.json().catch(() => null)) as SeedError | null\n setError(body?.error ? body : { error: `Seed failed (HTTP ${res.status}).` })\n setConfirming(false)\n }\n } catch {\n setError({ error: 'Seed request failed — is the dev server running?' })\n setConfirming(false)\n }\n setRunning(false)\n }\n\n return (\n <div className=\"pdtp-card\">\n <h2>\n {seed.seeded ? `Seeded — ${seed.totalDocs} docs` : 'Not seeded'}\n {!seed.enabled ? <span className=\"pdtp-kind pdtp-warn\">locked</span> : <span className=\"pdtp-kind\">seed</span>}\n </h2>\n <table className=\"pdtp-table\">\n <tbody>\n {seed.definitions.map((d) => (\n <tr key={d.slug}>\n <td>\n {d.slug}\n {d.disabled ? <span className=\"pdtp-warn\"> · skipped</span> : null}\n </td>\n <td>{d.kind === 'global' ? 'global' : (seed.counts[d.slug] ?? 0)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n <div style={{ marginTop: 12, display: 'flex', gap: 8 }}>\n <button\n type=\"button\"\n className={`pdtp-btn ${seed.seeded ? 'pdtp-btn-danger' : 'pdtp-btn-primary'}`}\n disabled={running}\n onClick={() => (seed.seeded && !confirming ? setConfirming(true) : void runSeed())}\n >\n {running ? 'Seeding…' : confirming ? 'Destructive — click again' : seed.seeded ? 'Reseed' : 'Seed the database'}\n </button>\n {confirming ? (\n <button type=\"button\" className=\"pdtp-btn\" onClick={() => setConfirming(false)}>\n Cancel\n </button>\n ) : null}\n </div>\n {!seed.enabled ? (\n <p className=\"pdtp-note\">\n Set <span className=\"pdtp-code\">ENABLE_SEED=true</span> in <span className=\"pdtp-code\">.env.local</span> — the seed wipes seeded\n collections, so it's off by default.\n </p>\n ) : null}\n <p className=\"pdtp-note\">\n Needs a logged-in <a href={adminRoute}>admin</a> user · CLI: <span className=\"pdtp-code\">ENABLE_SEED=true pnpm seed</span>\n </p>\n {error ? (\n <div className=\"pdtp-error\">\n {error.error}\n {error.issues?.length ? (\n <ul>\n {error.issues.map((issue) => (\n <li key={issue}>{issue}</li>\n ))}\n </ul>\n ) : null}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The `/dev/fonts` interactive specimen — the sample renders in the family's `--font-set*`\n * variable at the clicked weight/style. Only weights and styles the typeface actually serves\n * are offered. */\nexport function FontSpecimen({\n familyKey,\n title,\n cssVar,\n styles,\n}: {\n familyKey: string\n title: string | null\n cssVar: string\n styles: SpecimenStyle[]\n}) {\n const [styleIdx, setStyleIdx] = useState(0)\n const current = styles[Math.min(styleIdx, styles.length - 1)]\n const [weight, setWeight] = useState(current?.weights.includes(400) ? 400 : (current?.weights[0] ?? 400))\n\n const pickStyle = (idx: number) => {\n setStyleIdx(idx)\n const next = styles[idx]\n if (next && !next.weights.includes(weight)) setWeight(next.weights.includes(400) ? 400 : (next.weights[0] ?? 400))\n }\n\n return (\n <div className=\"pdtp-specimen\">\n <div className=\"pdtp-specimen-head\">\n <span>\n <span className=\"pdtp-code\">{familyKey}</span>{' '}\n <span className=\"pdtp-kind\" style={{ marginLeft: 6 }}>\n {title ?? 'slot unset — fallback stack'}\n {current ? ` · ${current.label}` : ''}\n </span>\n </span>\n {styles.length > 1 ? (\n <span className=\"pdtp-seg\">\n {styles.map((s, idx) => (\n <button key={s.style} type=\"button\" className={idx === styleIdx ? 'pdtp-active' : ''} onClick={() => pickStyle(idx)}>\n {s.style === 'normal' ? 'upright' : 'italic'}\n </button>\n ))}\n </span>\n ) : current ? (\n <span className=\"pdtp-kind\">{current.style === 'normal' ? 'upright only' : 'italic only'}</span>\n ) : null}\n </div>\n\n <div style={{ fontFamily: cssVar, fontWeight: weight, fontStyle: current?.style ?? 'normal' }}>\n <p className=\"pdtp-specimen-big\">The quick brown fox jumps over the lazy dog.</p>\n <p className=\"pdtp-specimen-body\">ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 — 1,234.56 · «fi ffi» ?!&</p>\n </div>\n\n {current ? (\n <div className=\"pdtp-chips\" style={{ marginTop: 14 }}>\n {current.weights.map((w) => (\n <button key={w} type=\"button\" className={`pdtp-chip ${w === weight ? 'pdtp-active' : ''}`} onClick={() => setWeight(w)}>\n {w}\n </button>\n ))}\n </div>\n ) : null}\n </div>\n )\n}\n\n/** The `/dev/icons` set switcher — activates a set via `POST /api/dev/icons/activate` and\n * refreshes, so the grid (and the whole site) re-skins to the newly active set. */\nexport function IconSetSwitcher({ sets }: { sets: { id: string | number; title: string; active: boolean }[] }) {\n const router = useRouter()\n const [busy, setBusy] = useState<string | number | null>(null)\n const [error, setError] = useState<string | null>(null)\n\n const activate = async (id: string | number) => {\n setBusy(id)\n setError(null)\n try {\n const res = await fetch('/api/dev/icons/activate', {\n method: 'POST',\n credentials: 'include',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n })\n if (res.ok) router.refresh()\n else setError(((await res.json().catch(() => null)) as { error?: string } | null)?.error ?? `Failed (HTTP ${res.status}).`)\n } catch {\n setError('Request failed — is the dev server running?')\n }\n setBusy(null)\n }\n\n return (\n <div>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}>\n {sets.map((set) => (\n <button\n key={set.id}\n type=\"button\"\n className={`pdtp-btn ${set.active ? 'pdtp-btn-primary' : ''}`}\n disabled={busy !== null || set.active}\n onClick={() => void activate(set.id)}\n >\n {busy === set.id ? 'Activating…' : set.title}\n {set.active ? ' ✓' : ''}\n </button>\n ))}\n </div>\n {error ? <div className=\"pdtp-error\">{error}</div> : null}\n </div>\n )\n}\n"],"names":["useRouter","useState","SeedCard","seed","adminRoute","router","running","setRunning","confirming","setConfirming","error","setError","runSeed","res","fetch","method","credentials","ok","refresh","body","json","catch","status","div","className","h2","seeded","totalDocs","enabled","span","table","tbody","definitions","map","d","tr","td","slug","disabled","kind","counts","style","marginTop","display","gap","button","type","onClick","p","a","href","issues","length","ul","issue","li","FontSpecimen","familyKey","title","cssVar","styles","styleIdx","setStyleIdx","current","Math","min","weight","setWeight","weights","includes","pickStyle","idx","next","marginLeft","label","s","fontFamily","fontWeight","fontStyle","w","IconSetSwitcher","sets","busy","setBusy","activate","id","headers","JSON","stringify","flexWrap","set","active"],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type Test } from '../harness';
|
|
2
|
+
export type CreateDevPageOptions = {
|
|
3
|
+
/** Component tests (from `defineTest`) — each gets ONE page at `/dev/tests/<key>`; which
|
|
4
|
+
* version it shows is controlled from the dev toolbar (via the selection cookie). Pass the
|
|
5
|
+
* same array to `<DevToolbar tests>`. */
|
|
6
|
+
tests?: Test[];
|
|
7
|
+
/** Force the pages on/off. Defaults to `NODE_ENV === 'development'` (404 otherwise). */
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type DevPageProps = {
|
|
11
|
+
params: Promise<{
|
|
12
|
+
view?: string[];
|
|
13
|
+
}>;
|
|
14
|
+
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The `/dev` pages — real routes inside your app, one drop-in file:
|
|
18
|
+
*
|
|
19
|
+
* // app/(frontend)/dev/[[...view]]/page.tsx
|
|
20
|
+
* import { createDevPage } from '@pro-laico/payload-dev-tools/next'
|
|
21
|
+
* import { devTests } from '@/dev/tests'
|
|
22
|
+
* export const dynamic = 'force-dynamic'
|
|
23
|
+
* export default createDevPage({ tests: devTests })
|
|
24
|
+
*
|
|
25
|
+
* Views: `/dev` (overview + seed controls), `/dev/icons` (grid + active-set switcher),
|
|
26
|
+
* `/dev/fonts` (specimens in the real served fonts), `/dev/images`, `/dev/mux`, and
|
|
27
|
+
* `/dev/tests/<key>` (one page per test; the shown version is toggled from the toolbar). The
|
|
28
|
+
* pages render content only — navigation lives in the `<DevToolbar>`, which stays open while you
|
|
29
|
+
* browse between them. Because the file lives in your `(frontend)` group, everything inherits
|
|
30
|
+
* your layout — header, fonts, globals — which is the point: visual confirmation happens in the
|
|
31
|
+
* app, not a facsimile of it. The component resolves Payload itself (config stash → the
|
|
32
|
+
* `@payload-config` alias), so it takes no config prop. Your own labs coexist: a static route
|
|
33
|
+
* like `app/(frontend)/dev/blocks/page.tsx` always beats this catch-all.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createDevPage(options?: CreateDevPageOptions): ({ params, searchParams }: DevPageProps) => Promise<import("react").JSX.Element>;
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=createDevPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createDevPage.d.ts","sourceRoot":"","sources":["../../src/next/createDevPage.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAc,KAAK,IAAI,EAAE,MAAM,YAAY,CAAA;AAOlD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;8CAE0C;IAC1C,KAAK,CAAC,EAAE,IAAI,EAAE,CAAA;IACd,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA;AAED,KAAK,YAAY,GAAG;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAA;CAAE,CAAA;AAEnI;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,IAGhC,0BAA0B,YAAY,0CAyDrE"}
|