@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,287 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { cookies } from "next/headers";
|
|
3
|
+
import { notFound } from "next/navigation";
|
|
4
|
+
import { STAGE_COOKIE } from "../cookies.js";
|
|
5
|
+
import { parseStage } from "../harness.js";
|
|
6
|
+
import { getPayloadClient } from "../lib/getPayloadClient.js";
|
|
7
|
+
import { buildDevSnapshot } from "../lib/snapshot.js";
|
|
8
|
+
import { SeedCard } from "./client.js";
|
|
9
|
+
import { PDTP_CSS } from "./pageStyles.js";
|
|
10
|
+
import { FontsView, IconsView, ImagesView, MuxView } from "./views.js";
|
|
11
|
+
/**
|
|
12
|
+
* The `/dev` pages — real routes inside your app, one drop-in file:
|
|
13
|
+
*
|
|
14
|
+
* // app/(frontend)/dev/[[...view]]/page.tsx
|
|
15
|
+
* import { createDevPage } from '@pro-laico/payload-dev-tools/next'
|
|
16
|
+
* import { devTests } from '@/dev/tests'
|
|
17
|
+
* export const dynamic = 'force-dynamic'
|
|
18
|
+
* export default createDevPage({ tests: devTests })
|
|
19
|
+
*
|
|
20
|
+
* Views: `/dev` (overview + seed controls), `/dev/icons` (grid + active-set switcher),
|
|
21
|
+
* `/dev/fonts` (specimens in the real served fonts), `/dev/images`, `/dev/mux`, and
|
|
22
|
+
* `/dev/tests/<key>` (one page per test; the shown version is toggled from the toolbar). The
|
|
23
|
+
* pages render content only — navigation lives in the `<DevToolbar>`, which stays open while you
|
|
24
|
+
* browse between them. Because the file lives in your `(frontend)` group, everything inherits
|
|
25
|
+
* your layout — header, fonts, globals — which is the point: visual confirmation happens in the
|
|
26
|
+
* app, not a facsimile of it. The component resolves Payload itself (config stash → the
|
|
27
|
+
* `@payload-config` alias), so it takes no config prop. Your own labs coexist: a static route
|
|
28
|
+
* like `app/(frontend)/dev/blocks/page.tsx` always beats this catch-all.
|
|
29
|
+
*/ export function createDevPage(options = {}) {
|
|
30
|
+
const { tests = [], enabled } = options;
|
|
31
|
+
return async function DevPage({ params, searchParams }) {
|
|
32
|
+
if (!(enabled ?? process.env.NODE_ENV === 'development')) notFound();
|
|
33
|
+
const { view = [] } = await params;
|
|
34
|
+
const query = await searchParams ?? {};
|
|
35
|
+
const payload = await getPayloadClient();
|
|
36
|
+
const snapshot = await buildDevSnapshot(payload);
|
|
37
|
+
const [section, ...rest] = view;
|
|
38
|
+
switch(section){
|
|
39
|
+
case undefined:
|
|
40
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
41
|
+
snapshot: snapshot,
|
|
42
|
+
title: snapshot.devRoute,
|
|
43
|
+
children: /*#__PURE__*/ _jsx(DevIndex, {
|
|
44
|
+
snapshot: snapshot
|
|
45
|
+
})
|
|
46
|
+
});
|
|
47
|
+
case 'icons':
|
|
48
|
+
if (!snapshot.icons || rest.length) notFound();
|
|
49
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
50
|
+
snapshot: snapshot,
|
|
51
|
+
title: "Icons",
|
|
52
|
+
children: /*#__PURE__*/ _jsx(IconsView, {
|
|
53
|
+
payload: payload,
|
|
54
|
+
snapshot: snapshot
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
case 'fonts':
|
|
58
|
+
if (!snapshot.fonts || rest.length) notFound();
|
|
59
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
60
|
+
snapshot: snapshot,
|
|
61
|
+
title: "Fonts",
|
|
62
|
+
children: /*#__PURE__*/ _jsx(FontsView, {
|
|
63
|
+
payload: payload,
|
|
64
|
+
snapshot: snapshot
|
|
65
|
+
})
|
|
66
|
+
});
|
|
67
|
+
case 'images':
|
|
68
|
+
if (!snapshot.images || rest.length) notFound();
|
|
69
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
70
|
+
snapshot: snapshot,
|
|
71
|
+
title: "Images",
|
|
72
|
+
children: /*#__PURE__*/ _jsx(ImagesView, {
|
|
73
|
+
payload: payload,
|
|
74
|
+
snapshot: snapshot,
|
|
75
|
+
searchParams: query
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
case 'mux':
|
|
79
|
+
if (!snapshot.mux || rest.length) notFound();
|
|
80
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
81
|
+
snapshot: snapshot,
|
|
82
|
+
title: "Mux",
|
|
83
|
+
children: /*#__PURE__*/ _jsx(MuxView, {
|
|
84
|
+
payload: payload,
|
|
85
|
+
snapshot: snapshot
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
case 'tests':
|
|
89
|
+
{
|
|
90
|
+
if (!tests.length || rest.length > 1) notFound();
|
|
91
|
+
if (rest.length === 1) return /*#__PURE__*/ _jsx(TestPage, {
|
|
92
|
+
tests: tests,
|
|
93
|
+
testKey: rest[0] ?? ''
|
|
94
|
+
});
|
|
95
|
+
return /*#__PURE__*/ _jsx(Shell, {
|
|
96
|
+
snapshot: snapshot,
|
|
97
|
+
title: "Tests",
|
|
98
|
+
children: /*#__PURE__*/ _jsx(TestsIndex, {
|
|
99
|
+
tests: tests
|
|
100
|
+
})
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
default:
|
|
104
|
+
notFound();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Content chrome only — heading + env line. Navigation is the toolbar's job. */ const Shell = ({ snapshot, title, children })=>/*#__PURE__*/ _jsxs("div", {
|
|
109
|
+
className: "pdtp",
|
|
110
|
+
children: [
|
|
111
|
+
/*#__PURE__*/ _jsx("style", {
|
|
112
|
+
dangerouslySetInnerHTML: {
|
|
113
|
+
__html: PDTP_CSS
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
117
|
+
className: "pdtp-container",
|
|
118
|
+
children: [
|
|
119
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
120
|
+
className: "pdtp-head",
|
|
121
|
+
children: [
|
|
122
|
+
/*#__PURE__*/ _jsx("h1", {
|
|
123
|
+
children: title
|
|
124
|
+
}),
|
|
125
|
+
/*#__PURE__*/ _jsx("span", {
|
|
126
|
+
className: "pdtp-badge",
|
|
127
|
+
children: "dev only"
|
|
128
|
+
}),
|
|
129
|
+
/*#__PURE__*/ _jsxs("span", {
|
|
130
|
+
className: "pdtp-env",
|
|
131
|
+
children: [
|
|
132
|
+
snapshot.env.nodeEnv,
|
|
133
|
+
" · node ",
|
|
134
|
+
snapshot.env.nodeVersion,
|
|
135
|
+
" · navigate via the dev toolbar ↘"
|
|
136
|
+
]
|
|
137
|
+
})
|
|
138
|
+
]
|
|
139
|
+
}),
|
|
140
|
+
children
|
|
141
|
+
]
|
|
142
|
+
})
|
|
143
|
+
]
|
|
144
|
+
});
|
|
145
|
+
const DevIndex = ({ snapshot })=>/*#__PURE__*/ _jsxs(_Fragment, {
|
|
146
|
+
children: [
|
|
147
|
+
/*#__PURE__*/ _jsx("div", {
|
|
148
|
+
className: "pdtp-chips",
|
|
149
|
+
children: Object.entries(snapshot.plugins).map(([name, on])=>/*#__PURE__*/ _jsxs("span", {
|
|
150
|
+
children: [
|
|
151
|
+
/*#__PURE__*/ _jsx("span", {
|
|
152
|
+
className: `pdtp-dot ${on ? 'pdtp-dot-on' : 'pdtp-dot-off'}`
|
|
153
|
+
}),
|
|
154
|
+
"payload-",
|
|
155
|
+
name
|
|
156
|
+
]
|
|
157
|
+
}, name))
|
|
158
|
+
}),
|
|
159
|
+
/*#__PURE__*/ _jsx("div", {
|
|
160
|
+
className: "pdtp-section",
|
|
161
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
162
|
+
className: "pdtp-grid",
|
|
163
|
+
children: [
|
|
164
|
+
snapshot.seed ? /*#__PURE__*/ _jsx(SeedCard, {
|
|
165
|
+
seed: snapshot.seed,
|
|
166
|
+
adminRoute: snapshot.adminRoute
|
|
167
|
+
}) : null,
|
|
168
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
169
|
+
className: "pdtp-card",
|
|
170
|
+
children: [
|
|
171
|
+
/*#__PURE__*/ _jsxs("h2", {
|
|
172
|
+
children: [
|
|
173
|
+
"Collections ",
|
|
174
|
+
/*#__PURE__*/ _jsx("span", {
|
|
175
|
+
className: "pdtp-kind",
|
|
176
|
+
children: "docs"
|
|
177
|
+
})
|
|
178
|
+
]
|
|
179
|
+
}),
|
|
180
|
+
/*#__PURE__*/ _jsx("table", {
|
|
181
|
+
className: "pdtp-table",
|
|
182
|
+
children: /*#__PURE__*/ _jsx("tbody", {
|
|
183
|
+
children: snapshot.collections.map((c)=>/*#__PURE__*/ _jsxs("tr", {
|
|
184
|
+
children: [
|
|
185
|
+
/*#__PURE__*/ _jsx("td", {
|
|
186
|
+
children: c.slug
|
|
187
|
+
}),
|
|
188
|
+
/*#__PURE__*/ _jsx("td", {
|
|
189
|
+
className: "pdtp-mono",
|
|
190
|
+
children: c.count ?? '?'
|
|
191
|
+
})
|
|
192
|
+
]
|
|
193
|
+
}, c.slug))
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
]
|
|
197
|
+
})
|
|
198
|
+
]
|
|
199
|
+
})
|
|
200
|
+
}),
|
|
201
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
202
|
+
className: "pdtp-note",
|
|
203
|
+
children: [
|
|
204
|
+
"Machine-readable: ",
|
|
205
|
+
/*#__PURE__*/ _jsx("span", {
|
|
206
|
+
className: "pdtp-code",
|
|
207
|
+
children: "GET /api/dev"
|
|
208
|
+
}),
|
|
209
|
+
" serves this as JSON (browsers land here instead)."
|
|
210
|
+
]
|
|
211
|
+
})
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
const TestsIndex = ({ tests })=>/*#__PURE__*/ _jsxs(_Fragment, {
|
|
215
|
+
children: [
|
|
216
|
+
/*#__PURE__*/ _jsxs("table", {
|
|
217
|
+
className: "pdtp-table",
|
|
218
|
+
children: [
|
|
219
|
+
/*#__PURE__*/ _jsx("thead", {
|
|
220
|
+
children: /*#__PURE__*/ _jsxs("tr", {
|
|
221
|
+
children: [
|
|
222
|
+
/*#__PURE__*/ _jsx("th", {
|
|
223
|
+
children: "test"
|
|
224
|
+
}),
|
|
225
|
+
/*#__PURE__*/ _jsx("th", {
|
|
226
|
+
children: "kind"
|
|
227
|
+
}),
|
|
228
|
+
/*#__PURE__*/ _jsx("th", {
|
|
229
|
+
children: "versions"
|
|
230
|
+
})
|
|
231
|
+
]
|
|
232
|
+
})
|
|
233
|
+
}),
|
|
234
|
+
/*#__PURE__*/ _jsx("tbody", {
|
|
235
|
+
children: tests.map((t)=>/*#__PURE__*/ _jsxs("tr", {
|
|
236
|
+
children: [
|
|
237
|
+
/*#__PURE__*/ _jsx("td", {
|
|
238
|
+
children: t.label
|
|
239
|
+
}),
|
|
240
|
+
/*#__PURE__*/ _jsx("td", {
|
|
241
|
+
className: "pdtp-mono",
|
|
242
|
+
children: t.kind
|
|
243
|
+
}),
|
|
244
|
+
/*#__PURE__*/ _jsx("td", {
|
|
245
|
+
className: "pdtp-mono",
|
|
246
|
+
children: t.versions.map((v)=>v.label).join(' · ')
|
|
247
|
+
})
|
|
248
|
+
]
|
|
249
|
+
}, t.key))
|
|
250
|
+
})
|
|
251
|
+
]
|
|
252
|
+
}),
|
|
253
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
254
|
+
className: "pdtp-note",
|
|
255
|
+
children: [
|
|
256
|
+
"Each test is one page — open it (and toggle versions) from the toolbar's Tests view, or script it via",
|
|
257
|
+
' ',
|
|
258
|
+
/*#__PURE__*/ _jsx("span", {
|
|
259
|
+
className: "pdtp-code",
|
|
260
|
+
children: "/api/dev/stage?test=…&version=…"
|
|
261
|
+
})
|
|
262
|
+
]
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
});
|
|
266
|
+
/** One page per test. The shown version comes from the toolbar's selection cookie (defaulting to
|
|
267
|
+
* the first version) and renders inside your real frontend layout with NO extra chrome — the
|
|
268
|
+
* toolbar's Tests view names what you're looking at. The `display: contents` wrapper is
|
|
269
|
+
* layout-invisible; it exists only so screenshot tooling can assert `data-pdt-test` /
|
|
270
|
+
* `data-pdt-version`. */ const TestPage = async ({ tests, testKey })=>{
|
|
271
|
+
const test = tests.find((t)=>t.key === testKey);
|
|
272
|
+
if (!test) notFound();
|
|
273
|
+
const jar = await cookies();
|
|
274
|
+
const stage = parseStage(jar.get(STAGE_COOKIE)?.value, tests);
|
|
275
|
+
const version = (stage?.test.key === test.key ? stage.version : undefined) ?? test.versions[0];
|
|
276
|
+
if (!version) notFound();
|
|
277
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
278
|
+
style: {
|
|
279
|
+
display: 'contents'
|
|
280
|
+
},
|
|
281
|
+
"data-pdt-test": test.key,
|
|
282
|
+
"data-pdt-version": version.id,
|
|
283
|
+
children: await version.render()
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
//# sourceMappingURL=createDevPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/createDevPage.tsx"],"sourcesContent":["import { cookies } from 'next/headers'\nimport { notFound } from 'next/navigation'\nimport type { ReactNode } from 'react'\nimport { STAGE_COOKIE } from '../cookies'\nimport { parseStage, type Test } from '../harness'\nimport { getPayloadClient } from '../lib/getPayloadClient'\nimport { buildDevSnapshot, type DevSnapshot } from '../lib/snapshot'\nimport { SeedCard } from './client'\nimport { PDTP_CSS } from './pageStyles'\nimport { FontsView, IconsView, ImagesView, MuxView } from './views'\n\nexport type CreateDevPageOptions = {\n /** Component tests (from `defineTest`) — each gets ONE page at `/dev/tests/<key>`; which\n * version it shows is controlled from the dev toolbar (via the selection cookie). Pass the\n * same array to `<DevToolbar tests>`. */\n tests?: Test[]\n /** Force the pages on/off. Defaults to `NODE_ENV === 'development'` (404 otherwise). */\n enabled?: boolean\n}\n\ntype DevPageProps = { params: Promise<{ view?: string[] }>; searchParams?: Promise<Record<string, string | string[] | undefined>> }\n\n/**\n * The `/dev` pages — real routes inside your app, one drop-in file:\n *\n * // app/(frontend)/dev/[[...view]]/page.tsx\n * import { createDevPage } from '@pro-laico/payload-dev-tools/next'\n * import { devTests } from '@/dev/tests'\n * export const dynamic = 'force-dynamic'\n * export default createDevPage({ tests: devTests })\n *\n * Views: `/dev` (overview + seed controls), `/dev/icons` (grid + active-set switcher),\n * `/dev/fonts` (specimens in the real served fonts), `/dev/images`, `/dev/mux`, and\n * `/dev/tests/<key>` (one page per test; the shown version is toggled from the toolbar). The\n * pages render content only — navigation lives in the `<DevToolbar>`, which stays open while you\n * browse between them. Because the file lives in your `(frontend)` group, everything inherits\n * your layout — header, fonts, globals — which is the point: visual confirmation happens in the\n * app, not a facsimile of it. The component resolves Payload itself (config stash → the\n * `@payload-config` alias), so it takes no config prop. Your own labs coexist: a static route\n * like `app/(frontend)/dev/blocks/page.tsx` always beats this catch-all.\n */\nexport function createDevPage(options: CreateDevPageOptions = {}) {\n const { tests = [], enabled } = options\n\n return async function DevPage({ params, searchParams }: DevPageProps) {\n if (!(enabled ?? process.env.NODE_ENV === 'development')) notFound()\n\n const { view = [] } = await params\n const query = (await searchParams) ?? {}\n const payload = await getPayloadClient()\n const snapshot = await buildDevSnapshot(payload)\n\n const [section, ...rest] = view\n switch (section) {\n case undefined:\n return (\n <Shell snapshot={snapshot} title={snapshot.devRoute}>\n <DevIndex snapshot={snapshot} />\n </Shell>\n )\n case 'icons':\n if (!snapshot.icons || rest.length) notFound()\n return (\n <Shell snapshot={snapshot} title=\"Icons\">\n <IconsView payload={payload} snapshot={snapshot} />\n </Shell>\n )\n case 'fonts':\n if (!snapshot.fonts || rest.length) notFound()\n return (\n <Shell snapshot={snapshot} title=\"Fonts\">\n <FontsView payload={payload} snapshot={snapshot} />\n </Shell>\n )\n case 'images':\n if (!snapshot.images || rest.length) notFound()\n return (\n <Shell snapshot={snapshot} title=\"Images\">\n <ImagesView payload={payload} snapshot={snapshot} searchParams={query} />\n </Shell>\n )\n case 'mux':\n if (!snapshot.mux || rest.length) notFound()\n return (\n <Shell snapshot={snapshot} title=\"Mux\">\n <MuxView payload={payload} snapshot={snapshot} />\n </Shell>\n )\n case 'tests': {\n if (!tests.length || rest.length > 1) notFound()\n if (rest.length === 1) return <TestPage tests={tests} testKey={rest[0] ?? ''} />\n return (\n <Shell snapshot={snapshot} title=\"Tests\">\n <TestsIndex tests={tests} />\n </Shell>\n )\n }\n default:\n notFound()\n }\n }\n}\n\n/** Content chrome only — heading + env line. Navigation is the toolbar's job. */\nconst Shell = ({ snapshot, title, children }: { snapshot: DevSnapshot; title: string; children: ReactNode }) => (\n <div className=\"pdtp\">\n {/* dangerouslySetInnerHTML: our own static CSS — React would escape selector characters as a text child */}\n <style dangerouslySetInnerHTML={{ __html: PDTP_CSS }} />\n <div className=\"pdtp-container\">\n <div className=\"pdtp-head\">\n <h1>{title}</h1>\n <span className=\"pdtp-badge\">dev only</span>\n <span className=\"pdtp-env\">\n {snapshot.env.nodeEnv} · node {snapshot.env.nodeVersion} · navigate via the dev toolbar ↘\n </span>\n </div>\n {children}\n </div>\n </div>\n)\n\nconst DevIndex = ({ snapshot }: { snapshot: DevSnapshot }) => (\n <>\n <div className=\"pdtp-chips\">\n {Object.entries(snapshot.plugins).map(([name, on]) => (\n <span key={name}>\n <span className={`pdtp-dot ${on ? 'pdtp-dot-on' : 'pdtp-dot-off'}`} />\n payload-{name}\n </span>\n ))}\n </div>\n\n <div className=\"pdtp-section\">\n <div className=\"pdtp-grid\">\n {snapshot.seed ? <SeedCard seed={snapshot.seed} adminRoute={snapshot.adminRoute} /> : null}\n <div className=\"pdtp-card\">\n <h2>\n Collections <span className=\"pdtp-kind\">docs</span>\n </h2>\n <table className=\"pdtp-table\">\n <tbody>\n {snapshot.collections.map((c) => (\n <tr key={c.slug}>\n <td>{c.slug}</td>\n <td className=\"pdtp-mono\">{c.count ?? '?'}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n </div>\n\n <p className=\"pdtp-note\">\n Machine-readable: <span className=\"pdtp-code\">GET /api/dev</span> serves this as JSON (browsers land here instead).\n </p>\n </>\n)\n\nconst TestsIndex = ({ tests }: { tests: Test[] }) => (\n <>\n <table className=\"pdtp-table\">\n <thead>\n <tr>\n <th>test</th>\n <th>kind</th>\n <th>versions</th>\n </tr>\n </thead>\n <tbody>\n {tests.map((t) => (\n <tr key={t.key}>\n <td>{t.label}</td>\n <td className=\"pdtp-mono\">{t.kind}</td>\n <td className=\"pdtp-mono\">{t.versions.map((v) => v.label).join(' · ')}</td>\n </tr>\n ))}\n </tbody>\n </table>\n <p className=\"pdtp-note\">\n Each test is one page — open it (and toggle versions) from the toolbar's Tests view, or script it via{' '}\n <span className=\"pdtp-code\">/api/dev/stage?test=…&version=…</span>\n </p>\n </>\n)\n\n/** One page per test. The shown version comes from the toolbar's selection cookie (defaulting to\n * the first version) and renders inside your real frontend layout with NO extra chrome — the\n * toolbar's Tests view names what you're looking at. The `display: contents` wrapper is\n * layout-invisible; it exists only so screenshot tooling can assert `data-pdt-test` /\n * `data-pdt-version`. */\nconst TestPage = async ({ tests, testKey }: { tests: Test[]; testKey: string }) => {\n const test = tests.find((t) => t.key === testKey)\n if (!test) notFound()\n\n const jar = await cookies()\n const stage = parseStage(jar.get(STAGE_COOKIE)?.value, tests)\n const version = (stage?.test.key === test.key ? stage.version : undefined) ?? test.versions[0]\n if (!version) notFound()\n\n return (\n <div style={{ display: 'contents' }} data-pdt-test={test.key} data-pdt-version={version.id}>\n {await version.render()}\n </div>\n )\n}\n"],"names":["cookies","notFound","STAGE_COOKIE","parseStage","getPayloadClient","buildDevSnapshot","SeedCard","PDTP_CSS","FontsView","IconsView","ImagesView","MuxView","createDevPage","options","tests","enabled","DevPage","params","searchParams","process","env","NODE_ENV","view","query","payload","snapshot","section","rest","undefined","Shell","title","devRoute","DevIndex","icons","length","fonts","images","mux","TestPage","testKey","TestsIndex","children","div","className","style","dangerouslySetInnerHTML","__html","h1","span","nodeEnv","nodeVersion","Object","entries","plugins","map","name","on","seed","adminRoute","h2","table","tbody","collections","c","tr","td","slug","count","p","thead","th","t","label","kind","versions","v","join","key","test","find","jar","stage","get","value","version","display","data-pdt-test","data-pdt-version","id","render"],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The dev pages' stylesheet, injected once by the page shell. Scoped under `.pdtp` and
|
|
2
|
+
* self-contained (own dark theme) — the pages inherit the host's frontend layout (header,
|
|
3
|
+
* fonts, globals) but never depend on its utility classes. */
|
|
4
|
+
export declare const PDTP_CSS = "\n.pdtp { color-scheme: dark;\n --pdtp-accent: oklch(0.72 0.16 250); --pdtp-bg: oklch(0.145 0 0); --pdtp-card: oklch(0.2 0 0);\n --pdtp-fg: oklch(0.985 0 0); --pdtp-muted: oklch(0.708 0 0); --pdtp-border: oklch(1 0 0 / 12%);\n --pdtp-hover: oklch(1 0 0 / 7%); --pdtp-danger: oklch(0.65 0.18 25); --pdtp-warn: oklch(0.8 0.14 85);\n background: var(--pdtp-bg); color: var(--pdtp-fg); min-height: 60vh;\n font-family: ui-sans-serif, system-ui, sans-serif; font-size: 15px; line-height: 1.5; }\n.pdtp *, .pdtp *::before, .pdtp *::after { box-sizing: border-box; }\n.pdtp a { color: var(--pdtp-accent); text-decoration: none; }\n.pdtp a:hover { text-decoration: underline; }\n/* :where() keeps this reset at zero specificity so component classes below always win it. */\n:where(.pdtp) button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }\n\n.pdtp-container { max-width: 1000px; margin: 0 auto; padding: 40px 24px 80px; }\n.pdtp-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }\n.pdtp-head h1 { margin: 0; font-size: 1.5rem; letter-spacing: -0.02em; color: var(--pdtp-fg); }\n.pdtp-badge { font-family: ui-monospace, Consolas, monospace; font-size: 10px; text-transform: uppercase;\n letter-spacing: 0.08em; color: var(--pdtp-muted); border: 1px solid var(--pdtp-border); border-radius: 4px; padding: 2px 7px; }\n.pdtp-env { color: var(--pdtp-muted); font-size: 0.85rem; }\n\n.pdtp-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }\n.pdtp-card { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 16px; }\n.pdtp-card h2 { margin: 0 0 10px; font-size: 1rem; font-weight: 600; color: var(--pdtp-fg); display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }\n.pdtp-kind { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; text-transform: uppercase;\n letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 400; }\n.pdtp-section { margin: 32px 0 0; }\n.pdtp-section > h2 { margin: 0 0 12px; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 600; }\n\n.pdtp-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }\n.pdtp-table td, .pdtp-table th { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--pdtp-border); }\n.pdtp-table th { color: var(--pdtp-muted); font-weight: 500; font-size: 0.8rem; }\n.pdtp-table td:last-child, .pdtp-table th:last-child { text-align: right; }\n.pdtp-mono { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; }\n.pdtp-code { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; background: oklch(0.26 0 0); padding: 1px 6px; border-radius: 4px; }\n.pdtp-muted { color: var(--pdtp-muted); }\n.pdtp-warn { color: var(--pdtp-warn); }\n\n.pdtp-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; }\n.pdtp-dot-on { background: oklch(0.75 0.15 165); } .pdtp-dot-off { background: oklch(0.45 0 0); }\n.pdtp-chips { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.9rem; }\n\n.pdtp-chip { border: 1px solid var(--pdtp-border); border-radius: 999px; padding: 5px 14px; font-size: 0.85rem;\n background: oklch(0.26 0 0); transition: border-color 0.15s ease, background 0.15s ease; }\n.pdtp-chip:hover { background: oklch(0.31 0 0); border-color: oklch(0.45 0 0); }\n.pdtp-chip.pdtp-active { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n.pdtp-seg { display: inline-flex; overflow: hidden; border: 1px solid var(--pdtp-border); border-radius: 999px; }\n.pdtp-seg button { padding: 4px 13px; font-size: 0.8rem; }\n.pdtp-seg button:hover { background: var(--pdtp-hover); }\n.pdtp-seg button.pdtp-active { background: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n\n.pdtp-btn { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--pdtp-border);\n border-radius: 8px; padding: 7px 14px; font-size: 0.9rem; font-weight: 500; }\n.pdtp-btn:hover { background: var(--pdtp-hover); text-decoration: none; }\n.pdtp-btn:disabled { opacity: 0.55; cursor: default; }\n.pdtp-btn-primary { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n.pdtp-btn-danger { border-color: color-mix(in oklch, var(--pdtp-danger), transparent 45%); color: var(--pdtp-danger); }\n.pdtp-error { margin-top: 10px; border: 1px solid color-mix(in oklch, var(--pdtp-danger), transparent 55%);\n border-radius: 8px; padding: 10px 12px; font-size: 0.85rem; color: var(--pdtp-danger); }\n.pdtp-error ul { margin: 6px 0 0; padding-left: 18px; color: var(--pdtp-fg); }\n.pdtp-note { color: var(--pdtp-muted); font-size: 0.82rem; margin: 10px 0 0; }\n\n.pdtp-icon-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }\n.pdtp-icon-cell { display: flex; flex-direction: column; align-items: center; gap: 8px; border: 1px solid var(--pdtp-border);\n border-radius: 10px; padding: 14px 8px 10px; background: var(--pdtp-card); }\n.pdtp-icon-cell svg { width: 28px; height: 28px; color: var(--pdtp-fg); }\n.pdtp-icon-cell figcaption { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; color: var(--pdtp-muted);\n max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.pdtp-img-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }\n.pdtp-img-cell { border: 1px solid var(--pdtp-border); border-radius: 10px; overflow: hidden; background: var(--pdtp-card); }\n.pdtp-img-cell img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }\n.pdtp-img-cell figcaption { padding: 7px 10px; font-family: ui-monospace, Consolas, monospace; font-size: 10.5px;\n color: var(--pdtp-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.pdtp-specimen { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 20px; margin-bottom: 14px; }\n.pdtp-specimen-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; }\n.pdtp-specimen-big { font-size: 2.2rem; line-height: 1.15; margin: 0 0 8px; overflow-wrap: break-word; }\n.pdtp-specimen-body { margin: 0; color: var(--pdtp-muted); }\n";
|
|
5
|
+
//# sourceMappingURL=pageStyles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageStyles.d.ts","sourceRoot":"","sources":["../../src/next/pageStyles.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAC/D,eAAO,MAAM,QAAQ,21MA8EpB,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/** The dev pages' stylesheet, injected once by the page shell. Scoped under `.pdtp` and
|
|
2
|
+
* self-contained (own dark theme) — the pages inherit the host's frontend layout (header,
|
|
3
|
+
* fonts, globals) but never depend on its utility classes. */ export const PDTP_CSS = `
|
|
4
|
+
.pdtp { color-scheme: dark;
|
|
5
|
+
--pdtp-accent: oklch(0.72 0.16 250); --pdtp-bg: oklch(0.145 0 0); --pdtp-card: oklch(0.2 0 0);
|
|
6
|
+
--pdtp-fg: oklch(0.985 0 0); --pdtp-muted: oklch(0.708 0 0); --pdtp-border: oklch(1 0 0 / 12%);
|
|
7
|
+
--pdtp-hover: oklch(1 0 0 / 7%); --pdtp-danger: oklch(0.65 0.18 25); --pdtp-warn: oklch(0.8 0.14 85);
|
|
8
|
+
background: var(--pdtp-bg); color: var(--pdtp-fg); min-height: 60vh;
|
|
9
|
+
font-family: ui-sans-serif, system-ui, sans-serif; font-size: 15px; line-height: 1.5; }
|
|
10
|
+
.pdtp *, .pdtp *::before, .pdtp *::after { box-sizing: border-box; }
|
|
11
|
+
.pdtp a { color: var(--pdtp-accent); text-decoration: none; }
|
|
12
|
+
.pdtp a:hover { text-decoration: underline; }
|
|
13
|
+
/* :where() keeps this reset at zero specificity so component classes below always win it. */
|
|
14
|
+
:where(.pdtp) button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
|
|
15
|
+
|
|
16
|
+
.pdtp-container { max-width: 1000px; margin: 0 auto; padding: 40px 24px 80px; }
|
|
17
|
+
.pdtp-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }
|
|
18
|
+
.pdtp-head h1 { margin: 0; font-size: 1.5rem; letter-spacing: -0.02em; color: var(--pdtp-fg); }
|
|
19
|
+
.pdtp-badge { font-family: ui-monospace, Consolas, monospace; font-size: 10px; text-transform: uppercase;
|
|
20
|
+
letter-spacing: 0.08em; color: var(--pdtp-muted); border: 1px solid var(--pdtp-border); border-radius: 4px; padding: 2px 7px; }
|
|
21
|
+
.pdtp-env { color: var(--pdtp-muted); font-size: 0.85rem; }
|
|
22
|
+
|
|
23
|
+
.pdtp-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
|
|
24
|
+
.pdtp-card { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 16px; }
|
|
25
|
+
.pdtp-card h2 { margin: 0 0 10px; font-size: 1rem; font-weight: 600; color: var(--pdtp-fg); display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
|
|
26
|
+
.pdtp-kind { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; text-transform: uppercase;
|
|
27
|
+
letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 400; }
|
|
28
|
+
.pdtp-section { margin: 32px 0 0; }
|
|
29
|
+
.pdtp-section > h2 { margin: 0 0 12px; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 600; }
|
|
30
|
+
|
|
31
|
+
.pdtp-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
|
|
32
|
+
.pdtp-table td, .pdtp-table th { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--pdtp-border); }
|
|
33
|
+
.pdtp-table th { color: var(--pdtp-muted); font-weight: 500; font-size: 0.8rem; }
|
|
34
|
+
.pdtp-table td:last-child, .pdtp-table th:last-child { text-align: right; }
|
|
35
|
+
.pdtp-mono { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; }
|
|
36
|
+
.pdtp-code { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; background: oklch(0.26 0 0); padding: 1px 6px; border-radius: 4px; }
|
|
37
|
+
.pdtp-muted { color: var(--pdtp-muted); }
|
|
38
|
+
.pdtp-warn { color: var(--pdtp-warn); }
|
|
39
|
+
|
|
40
|
+
.pdtp-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; }
|
|
41
|
+
.pdtp-dot-on { background: oklch(0.75 0.15 165); } .pdtp-dot-off { background: oklch(0.45 0 0); }
|
|
42
|
+
.pdtp-chips { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.9rem; }
|
|
43
|
+
|
|
44
|
+
.pdtp-chip { border: 1px solid var(--pdtp-border); border-radius: 999px; padding: 5px 14px; font-size: 0.85rem;
|
|
45
|
+
background: oklch(0.26 0 0); transition: border-color 0.15s ease, background 0.15s ease; }
|
|
46
|
+
.pdtp-chip:hover { background: oklch(0.31 0 0); border-color: oklch(0.45 0 0); }
|
|
47
|
+
.pdtp-chip.pdtp-active { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }
|
|
48
|
+
.pdtp-seg { display: inline-flex; overflow: hidden; border: 1px solid var(--pdtp-border); border-radius: 999px; }
|
|
49
|
+
.pdtp-seg button { padding: 4px 13px; font-size: 0.8rem; }
|
|
50
|
+
.pdtp-seg button:hover { background: var(--pdtp-hover); }
|
|
51
|
+
.pdtp-seg button.pdtp-active { background: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }
|
|
52
|
+
|
|
53
|
+
.pdtp-btn { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--pdtp-border);
|
|
54
|
+
border-radius: 8px; padding: 7px 14px; font-size: 0.9rem; font-weight: 500; }
|
|
55
|
+
.pdtp-btn:hover { background: var(--pdtp-hover); text-decoration: none; }
|
|
56
|
+
.pdtp-btn:disabled { opacity: 0.55; cursor: default; }
|
|
57
|
+
.pdtp-btn-primary { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }
|
|
58
|
+
.pdtp-btn-danger { border-color: color-mix(in oklch, var(--pdtp-danger), transparent 45%); color: var(--pdtp-danger); }
|
|
59
|
+
.pdtp-error { margin-top: 10px; border: 1px solid color-mix(in oklch, var(--pdtp-danger), transparent 55%);
|
|
60
|
+
border-radius: 8px; padding: 10px 12px; font-size: 0.85rem; color: var(--pdtp-danger); }
|
|
61
|
+
.pdtp-error ul { margin: 6px 0 0; padding-left: 18px; color: var(--pdtp-fg); }
|
|
62
|
+
.pdtp-note { color: var(--pdtp-muted); font-size: 0.82rem; margin: 10px 0 0; }
|
|
63
|
+
|
|
64
|
+
.pdtp-icon-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }
|
|
65
|
+
.pdtp-icon-cell { display: flex; flex-direction: column; align-items: center; gap: 8px; border: 1px solid var(--pdtp-border);
|
|
66
|
+
border-radius: 10px; padding: 14px 8px 10px; background: var(--pdtp-card); }
|
|
67
|
+
.pdtp-icon-cell svg { width: 28px; height: 28px; color: var(--pdtp-fg); }
|
|
68
|
+
.pdtp-icon-cell figcaption { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; color: var(--pdtp-muted);
|
|
69
|
+
max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
70
|
+
|
|
71
|
+
.pdtp-img-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
|
|
72
|
+
.pdtp-img-cell { border: 1px solid var(--pdtp-border); border-radius: 10px; overflow: hidden; background: var(--pdtp-card); }
|
|
73
|
+
.pdtp-img-cell img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
|
|
74
|
+
.pdtp-img-cell figcaption { padding: 7px 10px; font-family: ui-monospace, Consolas, monospace; font-size: 10.5px;
|
|
75
|
+
color: var(--pdtp-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
76
|
+
|
|
77
|
+
.pdtp-specimen { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 20px; margin-bottom: 14px; }
|
|
78
|
+
.pdtp-specimen-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; }
|
|
79
|
+
.pdtp-specimen-big { font-size: 2.2rem; line-height: 1.15; margin: 0 0 8px; overflow-wrap: break-word; }
|
|
80
|
+
.pdtp-specimen-body { margin: 0; color: var(--pdtp-muted); }
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
//# sourceMappingURL=pageStyles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/pageStyles.ts"],"sourcesContent":["/** The dev pages' stylesheet, injected once by the page shell. Scoped under `.pdtp` and\n * self-contained (own dark theme) — the pages inherit the host's frontend layout (header,\n * fonts, globals) but never depend on its utility classes. */\nexport const PDTP_CSS = `\n.pdtp { color-scheme: dark;\n --pdtp-accent: oklch(0.72 0.16 250); --pdtp-bg: oklch(0.145 0 0); --pdtp-card: oklch(0.2 0 0);\n --pdtp-fg: oklch(0.985 0 0); --pdtp-muted: oklch(0.708 0 0); --pdtp-border: oklch(1 0 0 / 12%);\n --pdtp-hover: oklch(1 0 0 / 7%); --pdtp-danger: oklch(0.65 0.18 25); --pdtp-warn: oklch(0.8 0.14 85);\n background: var(--pdtp-bg); color: var(--pdtp-fg); min-height: 60vh;\n font-family: ui-sans-serif, system-ui, sans-serif; font-size: 15px; line-height: 1.5; }\n.pdtp *, .pdtp *::before, .pdtp *::after { box-sizing: border-box; }\n.pdtp a { color: var(--pdtp-accent); text-decoration: none; }\n.pdtp a:hover { text-decoration: underline; }\n/* :where() keeps this reset at zero specificity so component classes below always win it. */\n:where(.pdtp) button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }\n\n.pdtp-container { max-width: 1000px; margin: 0 auto; padding: 40px 24px 80px; }\n.pdtp-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 24px; }\n.pdtp-head h1 { margin: 0; font-size: 1.5rem; letter-spacing: -0.02em; color: var(--pdtp-fg); }\n.pdtp-badge { font-family: ui-monospace, Consolas, monospace; font-size: 10px; text-transform: uppercase;\n letter-spacing: 0.08em; color: var(--pdtp-muted); border: 1px solid var(--pdtp-border); border-radius: 4px; padding: 2px 7px; }\n.pdtp-env { color: var(--pdtp-muted); font-size: 0.85rem; }\n\n.pdtp-grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }\n.pdtp-card { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 16px; }\n.pdtp-card h2 { margin: 0 0 10px; font-size: 1rem; font-weight: 600; color: var(--pdtp-fg); display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }\n.pdtp-kind { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; text-transform: uppercase;\n letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 400; }\n.pdtp-section { margin: 32px 0 0; }\n.pdtp-section > h2 { margin: 0 0 12px; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--pdtp-muted); font-weight: 600; }\n\n.pdtp-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }\n.pdtp-table td, .pdtp-table th { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--pdtp-border); }\n.pdtp-table th { color: var(--pdtp-muted); font-weight: 500; font-size: 0.8rem; }\n.pdtp-table td:last-child, .pdtp-table th:last-child { text-align: right; }\n.pdtp-mono { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; }\n.pdtp-code { font-family: ui-monospace, Consolas, monospace; font-size: 0.85em; background: oklch(0.26 0 0); padding: 1px 6px; border-radius: 4px; }\n.pdtp-muted { color: var(--pdtp-muted); }\n.pdtp-warn { color: var(--pdtp-warn); }\n\n.pdtp-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; }\n.pdtp-dot-on { background: oklch(0.75 0.15 165); } .pdtp-dot-off { background: oklch(0.45 0 0); }\n.pdtp-chips { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 0.9rem; }\n\n.pdtp-chip { border: 1px solid var(--pdtp-border); border-radius: 999px; padding: 5px 14px; font-size: 0.85rem;\n background: oklch(0.26 0 0); transition: border-color 0.15s ease, background 0.15s ease; }\n.pdtp-chip:hover { background: oklch(0.31 0 0); border-color: oklch(0.45 0 0); }\n.pdtp-chip.pdtp-active { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n.pdtp-seg { display: inline-flex; overflow: hidden; border: 1px solid var(--pdtp-border); border-radius: 999px; }\n.pdtp-seg button { padding: 4px 13px; font-size: 0.8rem; }\n.pdtp-seg button:hover { background: var(--pdtp-hover); }\n.pdtp-seg button.pdtp-active { background: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n\n.pdtp-btn { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--pdtp-border);\n border-radius: 8px; padding: 7px 14px; font-size: 0.9rem; font-weight: 500; }\n.pdtp-btn:hover { background: var(--pdtp-hover); text-decoration: none; }\n.pdtp-btn:disabled { opacity: 0.55; cursor: default; }\n.pdtp-btn-primary { background: var(--pdtp-accent); border-color: var(--pdtp-accent); color: oklch(0.13 0 0); font-weight: 600; }\n.pdtp-btn-danger { border-color: color-mix(in oklch, var(--pdtp-danger), transparent 45%); color: var(--pdtp-danger); }\n.pdtp-error { margin-top: 10px; border: 1px solid color-mix(in oklch, var(--pdtp-danger), transparent 55%);\n border-radius: 8px; padding: 10px 12px; font-size: 0.85rem; color: var(--pdtp-danger); }\n.pdtp-error ul { margin: 6px 0 0; padding-left: 18px; color: var(--pdtp-fg); }\n.pdtp-note { color: var(--pdtp-muted); font-size: 0.82rem; margin: 10px 0 0; }\n\n.pdtp-icon-grid { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); }\n.pdtp-icon-cell { display: flex; flex-direction: column; align-items: center; gap: 8px; border: 1px solid var(--pdtp-border);\n border-radius: 10px; padding: 14px 8px 10px; background: var(--pdtp-card); }\n.pdtp-icon-cell svg { width: 28px; height: 28px; color: var(--pdtp-fg); }\n.pdtp-icon-cell figcaption { font-family: ui-monospace, Consolas, monospace; font-size: 10.5px; color: var(--pdtp-muted);\n max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.pdtp-img-grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }\n.pdtp-img-cell { border: 1px solid var(--pdtp-border); border-radius: 10px; overflow: hidden; background: var(--pdtp-card); }\n.pdtp-img-cell img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }\n.pdtp-img-cell figcaption { padding: 7px 10px; font-family: ui-monospace, Consolas, monospace; font-size: 10.5px;\n color: var(--pdtp-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n.pdtp-specimen { border: 1px solid var(--pdtp-border); background: var(--pdtp-card); border-radius: 12px; padding: 20px; margin-bottom: 14px; }\n.pdtp-specimen-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 12px; }\n.pdtp-specimen-big { font-size: 2.2rem; line-height: 1.15; margin: 0 0 8px; overflow-wrap: break-word; }\n.pdtp-specimen-body { margin: 0; color: var(--pdtp-muted); }\n`\n"],"names":["PDTP_CSS"],"mappings":"AAAA;;6DAE6D,GAC7D,OAAO,MAAMA,WAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8EzB,CAAC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A served face row from the `fontOptimized` collection (depth 0). */
|
|
2
|
+
export type OptimizedFace = {
|
|
3
|
+
font?: string | number | null;
|
|
4
|
+
weight?: string | null;
|
|
5
|
+
style?: 'normal' | 'italic' | null;
|
|
6
|
+
isVariable?: boolean | null;
|
|
7
|
+
/** payload-fonts marks an upright variable file whose axes also carry italics (ital/slnt). */
|
|
8
|
+
italCapable?: boolean | null;
|
|
9
|
+
};
|
|
10
|
+
/** One selectable style on the `/dev/fonts` specimen: a real served style with the weights it
|
|
11
|
+
* actually carries. Built server-side, so the controls never offer a synthesized face. */
|
|
12
|
+
export type SpecimenStyle = {
|
|
13
|
+
style: 'normal' | 'italic';
|
|
14
|
+
/** e.g. "variable · 100–900" or "3 weights" — shown next to the style toggle. */
|
|
15
|
+
label: string;
|
|
16
|
+
weights: number[];
|
|
17
|
+
};
|
|
18
|
+
/** The served faces of one typeface → selectable specimen styles. A variable face's range
|
|
19
|
+
* (`'100 900'`) becomes clickable stops at every 100 (range ends always included); static faces
|
|
20
|
+
* list their exact weights. An upright variable face flagged `italCapable` (ital/slnt axes)
|
|
21
|
+
* contributes an italic style from the same file — unless an explicit italic exists. Styles
|
|
22
|
+
* with no faces are omitted. */
|
|
23
|
+
export declare const facesToStyles: (faces: OptimizedFace[]) => SpecimenStyle[];
|
|
24
|
+
//# sourceMappingURL=specimen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specimen.d.ts","sourceRoot":"","sources":["../../src/next/specimen.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAA;IAClC,UAAU,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3B,8FAA8F;IAC9F,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;CAC7B,CAAA;AAED;2FAC2F;AAC3F,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC1B,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED;;;;iCAIiC;AACjC,eAAO,MAAM,aAAa,GAAI,OAAO,aAAa,EAAE,KAAG,aAAa,EAoBnE,CAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** A served face row from the `fontOptimized` collection (depth 0). */ /** The served faces of one typeface → selectable specimen styles. A variable face's range
|
|
2
|
+
* (`'100 900'`) becomes clickable stops at every 100 (range ends always included); static faces
|
|
3
|
+
* list their exact weights. An upright variable face flagged `italCapable` (ital/slnt axes)
|
|
4
|
+
* contributes an italic style from the same file — unless an explicit italic exists. Styles
|
|
5
|
+
* with no faces are omitted. */ export const facesToStyles = (faces)=>{
|
|
6
|
+
const hasExplicitItalic = faces.some((f)=>f.style === 'italic');
|
|
7
|
+
return [
|
|
8
|
+
'normal',
|
|
9
|
+
'italic'
|
|
10
|
+
].flatMap((style)=>{
|
|
11
|
+
const own = faces.filter((f)=>(f.style ?? 'normal') === style);
|
|
12
|
+
if (style === 'italic' && !hasExplicitItalic) own.push(...faces.filter((f)=>(f.style ?? 'normal') === 'normal' && f.italCapable));
|
|
13
|
+
if (!own.length) return [];
|
|
14
|
+
const variable = own.find((f)=>f.isVariable && f.weight?.includes(' '));
|
|
15
|
+
if (variable?.weight) {
|
|
16
|
+
const [rawMin, rawMax] = variable.weight.split(' ').map(Number);
|
|
17
|
+
const min = rawMin ?? 400;
|
|
18
|
+
const max = rawMax ?? min;
|
|
19
|
+
const stops = new Set([
|
|
20
|
+
min
|
|
21
|
+
]);
|
|
22
|
+
for(let w = Math.ceil(min / 100) * 100; w <= max; w += 100)stops.add(w);
|
|
23
|
+
stops.add(max);
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
style,
|
|
27
|
+
label: `variable · ${min}–${max}`,
|
|
28
|
+
weights: [
|
|
29
|
+
...stops
|
|
30
|
+
].sort((a, b)=>a - b)
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
const weights = [
|
|
35
|
+
...new Set(own.map((f)=>Number(f.weight)).filter((w)=>Number.isFinite(w)))
|
|
36
|
+
].sort((a, b)=>a - b);
|
|
37
|
+
if (!weights.length) return [];
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
style,
|
|
41
|
+
label: `${weights.length} weight${weights.length === 1 ? '' : 's'}`,
|
|
42
|
+
weights
|
|
43
|
+
}
|
|
44
|
+
];
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=specimen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/next/specimen.ts"],"sourcesContent":["/** A served face row from the `fontOptimized` collection (depth 0). */\nexport type OptimizedFace = {\n font?: string | number | null\n weight?: string | null\n style?: 'normal' | 'italic' | null\n isVariable?: boolean | null\n /** payload-fonts marks an upright variable file whose axes also carry italics (ital/slnt). */\n italCapable?: boolean | null\n}\n\n/** One selectable style on the `/dev/fonts` specimen: a real served style with the weights it\n * actually carries. Built server-side, so the controls never offer a synthesized face. */\nexport type SpecimenStyle = {\n style: 'normal' | 'italic'\n /** e.g. \"variable · 100–900\" or \"3 weights\" — shown next to the style toggle. */\n label: string\n weights: number[]\n}\n\n/** The served faces of one typeface → selectable specimen styles. A variable face's range\n * (`'100 900'`) becomes clickable stops at every 100 (range ends always included); static faces\n * list their exact weights. An upright variable face flagged `italCapable` (ital/slnt axes)\n * contributes an italic style from the same file — unless an explicit italic exists. Styles\n * with no faces are omitted. */\nexport const facesToStyles = (faces: OptimizedFace[]): SpecimenStyle[] => {\n const hasExplicitItalic = faces.some((f) => f.style === 'italic')\n return (['normal', 'italic'] as const).flatMap((style) => {\n const own = faces.filter((f) => (f.style ?? 'normal') === style)\n if (style === 'italic' && !hasExplicitItalic) own.push(...faces.filter((f) => (f.style ?? 'normal') === 'normal' && f.italCapable))\n if (!own.length) return []\n const variable = own.find((f) => f.isVariable && f.weight?.includes(' '))\n if (variable?.weight) {\n const [rawMin, rawMax] = variable.weight.split(' ').map(Number)\n const min = rawMin ?? 400\n const max = rawMax ?? min\n const stops = new Set<number>([min])\n for (let w = Math.ceil(min / 100) * 100; w <= max; w += 100) stops.add(w)\n stops.add(max)\n return [{ style, label: `variable · ${min}–${max}`, weights: [...stops].sort((a, b) => a - b) }]\n }\n const weights = [...new Set(own.map((f) => Number(f.weight)).filter((w) => Number.isFinite(w)))].sort((a, b) => a - b)\n if (!weights.length) return []\n return [{ style, label: `${weights.length} weight${weights.length === 1 ? '' : 's'}`, weights }]\n })\n}\n"],"names":["facesToStyles","faces","hasExplicitItalic","some","f","style","flatMap","own","filter","push","italCapable","length","variable","find","isVariable","weight","includes","rawMin","rawMax","split","map","Number","min","max","stops","Set","w","Math","ceil","add","label","weights","sort","a","b","isFinite"],"mappings":"AAAA,qEAAqE,GAmBrE;;;;+BAI+B,GAC/B,OAAO,MAAMA,gBAAgB,CAACC;IAC5B,MAAMC,oBAAoBD,MAAME,IAAI,CAAC,CAACC,IAAMA,EAAEC,KAAK,KAAK;IACxD,OAAO,AAAC;QAAC;QAAU;KAAS,CAAWC,OAAO,CAAC,CAACD;QAC9C,MAAME,MAAMN,MAAMO,MAAM,CAAC,CAACJ,IAAM,AAACA,CAAAA,EAAEC,KAAK,IAAI,QAAO,MAAOA;QAC1D,IAAIA,UAAU,YAAY,CAACH,mBAAmBK,IAAIE,IAAI,IAAIR,MAAMO,MAAM,CAAC,CAACJ,IAAM,AAACA,CAAAA,EAAEC,KAAK,IAAI,QAAO,MAAO,YAAYD,EAAEM,WAAW;QACjI,IAAI,CAACH,IAAII,MAAM,EAAE,OAAO,EAAE;QAC1B,MAAMC,WAAWL,IAAIM,IAAI,CAAC,CAACT,IAAMA,EAAEU,UAAU,IAAIV,EAAEW,MAAM,EAAEC,SAAS;QACpE,IAAIJ,UAAUG,QAAQ;YACpB,MAAM,CAACE,QAAQC,OAAO,GAAGN,SAASG,MAAM,CAACI,KAAK,CAAC,KAAKC,GAAG,CAACC;YACxD,MAAMC,MAAML,UAAU;YACtB,MAAMM,MAAML,UAAUI;YACtB,MAAME,QAAQ,IAAIC,IAAY;gBAACH;aAAI;YACnC,IAAK,IAAII,IAAIC,KAAKC,IAAI,CAACN,MAAM,OAAO,KAAKI,KAAKH,KAAKG,KAAK,IAAKF,MAAMK,GAAG,CAACH;YACvEF,MAAMK,GAAG,CAACN;YACV,OAAO;gBAAC;oBAAElB;oBAAOyB,OAAO,CAAC,WAAW,EAAER,IAAI,CAAC,EAAEC,KAAK;oBAAEQ,SAAS;2BAAIP;qBAAM,CAACQ,IAAI,CAAC,CAACC,GAAGC,IAAMD,IAAIC;gBAAG;aAAE;QAClG;QACA,MAAMH,UAAU;eAAI,IAAIN,IAAIlB,IAAIa,GAAG,CAAC,CAAChB,IAAMiB,OAAOjB,EAAEW,MAAM,GAAGP,MAAM,CAAC,CAACkB,IAAML,OAAOc,QAAQ,CAACT;SAAK,CAACM,IAAI,CAAC,CAACC,GAAGC,IAAMD,IAAIC;QACpH,IAAI,CAACH,QAAQpB,MAAM,EAAE,OAAO,EAAE;QAC9B,OAAO;YAAC;gBAAEN;gBAAOyB,OAAO,GAAGC,QAAQpB,MAAM,CAAC,OAAO,EAAEoB,QAAQpB,MAAM,KAAK,IAAI,KAAK,KAAK;gBAAEoB;YAAQ;SAAE;IAClG;AACF,EAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Payload } from 'payload';
|
|
2
|
+
import type { DevSnapshot } from '../lib/snapshot';
|
|
3
|
+
/** `/dev/icons` — every set as a switcher button (activating one re-skins the site), the active
|
|
4
|
+
* set's glyphs as a grid, and any runtime misses. */
|
|
5
|
+
export declare function IconsView({ payload, snapshot }: {
|
|
6
|
+
payload: Payload;
|
|
7
|
+
snapshot: DevSnapshot;
|
|
8
|
+
}): Promise<import("react").JSX.Element>;
|
|
9
|
+
/** `/dev/fonts` — one interactive specimen per family slot, rendered in the family's own
|
|
10
|
+
* `--font-set*` variable so the page shows the actual served fonts (the host layout loads them
|
|
11
|
+
* via extractFonts / DevFonts). The weight/style controls are built from the `fontOptimized`
|
|
12
|
+
* docs, so only faces that really exist are offered. */
|
|
13
|
+
export declare function FontsView({ payload, snapshot }: {
|
|
14
|
+
payload: Payload;
|
|
15
|
+
snapshot: DevSnapshot;
|
|
16
|
+
}): Promise<import("react").JSX.Element>;
|
|
17
|
+
/** `/dev/images` — every original through the on-demand transform endpoint (`?w=320`), so the
|
|
18
|
+
* grid itself exercises payload-images end-to-end. When the collection has Payload folders
|
|
19
|
+
* enabled, the folders render as filter chips (`?folder=<id>`, `?folder=none` for unfiled) so
|
|
20
|
+
* you can click through the library the way it's organized. */
|
|
21
|
+
export declare function ImagesView({ payload, snapshot, searchParams, }: {
|
|
22
|
+
payload: Payload;
|
|
23
|
+
snapshot: DevSnapshot;
|
|
24
|
+
searchParams?: Record<string, string | string[] | undefined>;
|
|
25
|
+
}): Promise<import("react").JSX.Element>;
|
|
26
|
+
/** `/dev/mux` — the videos with their persisted ingest status. */
|
|
27
|
+
export declare function MuxView({ payload, snapshot }: {
|
|
28
|
+
payload: Payload;
|
|
29
|
+
snapshot: DevSnapshot;
|
|
30
|
+
}): Promise<import("react").JSX.Element>;
|
|
31
|
+
//# sourceMappingURL=views.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/next/views.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA8B,OAAO,EAAE,MAAM,SAAS,CAAA;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAIlD;sDACsD;AACtD,wBAAsB,SAAS,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,wCA2EjG;AAID;;;yDAGyD;AACzD,wBAAsB,SAAS,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,wCAyDjG;AAKD;;;gEAGgE;AAChE,wBAAsB,UAAU,CAAC,EAC/B,OAAO,EACP,QAAQ,EACR,YAAiB,GAClB,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,WAAW,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAA;CAC7D,wCAqFA;AASD,kEAAkE;AAClE,wBAAsB,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,WAAW,CAAA;CAAE,wCAsC/F"}
|