mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 14:16:28 +03:00
Add screen 02 palette picker: cue deck, sampling rings, band tools
Deck of cue cards + seed palettes with scroll-snap browsing, draggable color-sampling rings with loupe, four-band panel (copy hex+OKLCH, tint strip, native custom color, card-local reset), /palettes.json route. AI-assisted (agent-implemented, maintainer-directed). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,6 +10,8 @@ import { readFile, mkdir, stat, writeFile } from 'node:fs/promises';
|
||||
import net from 'node:net';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { extractRegister } from './context.mjs';
|
||||
import { SEEDS } from './palette.mjs';
|
||||
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const pickerDir = path.join(scriptDir, 'picker');
|
||||
const answersPath = path.resolve(process.cwd(), '.impeccable/design-interview/answers.json');
|
||||
@@ -168,6 +170,14 @@ if (options.help) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
let register = 'brand';
|
||||
try {
|
||||
const product = await readFile(path.resolve(process.cwd(), 'PRODUCT.md'), 'utf8');
|
||||
register = extractRegister(product) || register;
|
||||
} catch {
|
||||
// A missing or unreadable PRODUCT.md keeps the brand preview default.
|
||||
}
|
||||
|
||||
const port = await findOpenPort(options.port);
|
||||
let completed = false;
|
||||
let timeout;
|
||||
@@ -212,6 +222,16 @@ async function handleRequest(request, response) {
|
||||
await serveFile(response, options.cuesDir, 'cues.json', ['.json']);
|
||||
return;
|
||||
}
|
||||
if (requestPath === '/palettes.json') {
|
||||
sendJson(response, 200, {
|
||||
seeds: SEEDS.map(({ id, oklch, mood }) => ({ id, oklch, mood })),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (requestPath === '/context.json') {
|
||||
sendJson(response, 200, { register });
|
||||
return;
|
||||
}
|
||||
if (requestPath.startsWith('/cues/')) {
|
||||
const cueName = requestPath.slice('/cues/'.length);
|
||||
if (!cueName || cueName.includes('/')) {
|
||||
|
||||
Reference in New Issue
Block a user