@godxjp/ui 27.4.1 → 27.6.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/dist/components/data-display/range-timeline.js +9 -6
- package/dist/components/data-entry/upload-file-kind.d.ts +25 -0
- package/dist/components/data-entry/upload-file-kind.js +88 -0
- package/dist/components/data-entry/upload.d.ts +2 -2
- package/dist/components/data-entry/upload.js +10 -6
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +2 -0
- package/dist/components/ui/segmented.d.ts +7 -2
- package/dist/components/ui/toggle.d.ts +2 -2
- package/dist/components/ui/toggle.js +4 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/props/components/data-display.prop.d.ts +14 -0
- package/dist/props/components/data-entry.prop.d.ts +28 -2
- package/dist/props/registry.d.ts +6 -1
- package/dist/props/registry.js +6 -1
- package/dist/styles/control.css +18 -6
- package/dist/styles/data-display-layout.css +40 -8
- package/dist/styles/data-entry-layout.css +22 -0
- package/dist/tokens/components/control.css +1 -0
- package/dist/tokens/components/data-display.css +26 -0
- package/dist/tokens/components/segmented.css +4 -0
- package/dist/tokens/components/upload.css +4 -0
- package/docs/CUSTOMER-THEMING.md +26 -0
- package/docs/data-display/avatar.tsx +128 -11
- package/docs/data-display/prose.tsx +64 -0
- package/docs/data-display/timeline.tsx +36 -0
- package/docs/data-entry/calendar.tsx +2 -3
- package/docs/data-entry/segmented.tsx +55 -5
- package/docs/data-entry/toggle-group.tsx +15 -3
- package/docs/data-entry/toggle.tsx +39 -1
- package/docs/data-entry/upload.tsx +38 -0
- package/package.json +2 -2
- package/scripts/_agent-setup.mjs +80 -1
- package/scripts/cli.mjs +5 -1
- package/scripts/init-agent-kit.mjs +3 -0
- package/scripts/postinstall.mjs +5 -0
package/scripts/_agent-setup.mjs
CHANGED
|
@@ -16,12 +16,14 @@ import {
|
|
|
16
16
|
existsSync,
|
|
17
17
|
mkdirSync,
|
|
18
18
|
readFileSync,
|
|
19
|
+
realpathSync,
|
|
19
20
|
renameSync,
|
|
20
21
|
statSync,
|
|
21
22
|
unlinkSync,
|
|
22
23
|
writeFileSync,
|
|
23
24
|
} from "node:fs";
|
|
24
|
-
import {
|
|
25
|
+
import { homedir } from "node:os";
|
|
26
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
25
27
|
import { fileURLToPath } from "node:url";
|
|
26
28
|
|
|
27
29
|
/** This package's own root — the source of the version we stamp with. */
|
|
@@ -425,6 +427,83 @@ export function ensureMcpJson(root) {
|
|
|
425
427
|
return created ? "created" : "added";
|
|
426
428
|
}
|
|
427
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Registrations of the catalog server OUTSIDE the project — READ-ONLY (gh#722).
|
|
432
|
+
*
|
|
433
|
+
* `.mcp.json` is not the only place an agent's MCP servers come from. Claude Code keeps
|
|
434
|
+
* user-scoped servers in the top-level `mcpServers` of `~/.claude.json` (under
|
|
435
|
+
* `$CLAUDE_CONFIG_DIR` when that is set) and local-scoped ones — private to one checkout — under
|
|
436
|
+
* `projects[<absolute project path>].mcpServers` of the same file. Both are live beside the
|
|
437
|
+
* project's entry. Measured: a user-scoped `godxjp-ui` serving a ≤ 21.0.0 catalog answered next
|
|
438
|
+
* to the project's pinned `godx-ui`, and an agent took a removed component's page from it.
|
|
439
|
+
*
|
|
440
|
+
* That file belongs to the user, spans every project, and is not ours to edit: this only READS
|
|
441
|
+
* it. A missing, unreadable or malformed file yields nothing, silently. Returns
|
|
442
|
+
* `{ key, scope, pin }` per entry — never `env`, which is where secrets live.
|
|
443
|
+
*/
|
|
444
|
+
export function findOutOfProjectUiMcp(
|
|
445
|
+
root,
|
|
446
|
+
configDir = process.env.CLAUDE_CONFIG_DIR || homedir(),
|
|
447
|
+
) {
|
|
448
|
+
try {
|
|
449
|
+
const read = readJsonFile(join(configDir, ".claude.json"));
|
|
450
|
+
if (read.state !== "ok") return [];
|
|
451
|
+
const found = [];
|
|
452
|
+
const collect = (servers, scope) => {
|
|
453
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) return;
|
|
454
|
+
for (const [key, entry] of Object.entries(servers)) {
|
|
455
|
+
if (!runsUiMcp(entry)) continue;
|
|
456
|
+
const parts = [entry.command, ...(Array.isArray(entry.args) ? entry.args : [])];
|
|
457
|
+
const pin = parts.find(
|
|
458
|
+
(part) => typeof part === "string" && /(^|\/)@godxjp\/ui-mcp(@|$)/.test(part),
|
|
459
|
+
);
|
|
460
|
+
found.push({ key, scope, pin });
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
collect(read.json.mcpServers, "user");
|
|
464
|
+
const projects = read.json.projects;
|
|
465
|
+
if (projects && typeof projects === "object" && !Array.isArray(projects)) {
|
|
466
|
+
const paths = new Set([resolve(root)]);
|
|
467
|
+
try {
|
|
468
|
+
paths.add(realpathSync(root));
|
|
469
|
+
} catch {
|
|
470
|
+
// A root that cannot be resolved is looked up by its given path only.
|
|
471
|
+
}
|
|
472
|
+
for (const path of paths) collect(projects[path]?.mcpServers, "local");
|
|
473
|
+
}
|
|
474
|
+
return found;
|
|
475
|
+
} catch {
|
|
476
|
+
return [];
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
const shellWord = (word) => (/^[\w.@/-]+$/.test(word) ? word : `'${word.replace(/'/g, "'\\''")}'`);
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* What `sync-rules` and `init-agent` print about out-of-project registrations: key, pin, that it
|
|
484
|
+
* was left untouched, and the command that updates it. Empty string when there are none.
|
|
485
|
+
*/
|
|
486
|
+
export function outOfProjectUiMcpReport(root, configDir) {
|
|
487
|
+
const found = findOutOfProjectUiMcp(root, configDir);
|
|
488
|
+
if (found.length === 0) return "";
|
|
489
|
+
const expected = mcpServerFor(root).args[0];
|
|
490
|
+
let out =
|
|
491
|
+
`\n @godxjp/ui → @godxjp/ui-mcp is ALSO registered outside this project, in Claude Code's ` +
|
|
492
|
+
`.claude.json.\n It answers beside the project's .mcp.json entry (${expected}) and an agent ` +
|
|
493
|
+
`can call either — the tool names differ only by the key.\n`;
|
|
494
|
+
for (const { key, scope, pin } of found) {
|
|
495
|
+
const k = shellWord(key);
|
|
496
|
+
const runs = /@godxjp\/ui-mcp@\S+$/.test(pin ?? "")
|
|
497
|
+
? pin
|
|
498
|
+
: `${pin ?? "@godxjp/ui-mcp"} (unpinned: resolves the latest release)`;
|
|
499
|
+
out +=
|
|
500
|
+
` • "${key}" (${scope} scope) runs ${runs} — outside the project, left untouched.\n` +
|
|
501
|
+
` remove it: claude mcp remove ${k} -s ${scope}\n` +
|
|
502
|
+
` or re-pin: claude mcp remove ${k} -s ${scope} && claude mcp add ${k} -s ${scope} -- npx ${expected}\n`;
|
|
503
|
+
}
|
|
504
|
+
return out;
|
|
505
|
+
}
|
|
506
|
+
|
|
428
507
|
/** Ensure `.claude/settings.json` has the audit PostToolUse + workflow SessionStart hooks. */
|
|
429
508
|
export function ensureClaudeHooks(root) {
|
|
430
509
|
const path = join(root, ".claude", "settings.json");
|
package/scripts/cli.mjs
CHANGED
|
@@ -34,7 +34,11 @@ const HELP = {
|
|
|
34
34
|
Refresh the package-owned agent files for the installed @godxjp/ui version: the godx-ui entry in
|
|
35
35
|
.mcp.json, the managed CLAUDE.md block, .claude/godxjp-ui-workflow.md and .ai/rules/godxjp-ui.md.
|
|
36
36
|
It is the postinstall step, run by hand — use it when the app installs with ignore-scripts=true,
|
|
37
|
-
where postinstall never runs and the rules go stale. Silent no-op in CI and when opted out
|
|
37
|
+
where postinstall never runs and the rules go stale. Silent no-op in CI and when opted out.
|
|
38
|
+
|
|
39
|
+
It also READS Claude Code's ~/.claude.json and reports any @godxjp/ui-mcp registered there (user
|
|
40
|
+
scope, or local scope for this project): key, pin, and the claude mcp command that updates it.
|
|
41
|
+
That file is outside the project and is never written; env values are never printed.`,
|
|
38
42
|
audit: `godxjp-ui audit [dir …] [--changed] [--format json] [--quiet] [--rules]
|
|
39
43
|
|
|
40
44
|
Static UI-standardization audit over source (regex, no browser, fast). Exits non-zero on errors.
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ensureClaudeHooks,
|
|
5
5
|
ensureClaudeMd,
|
|
6
6
|
ensureMcpJson,
|
|
7
|
+
outOfProjectUiMcpReport,
|
|
7
8
|
shouldSkip,
|
|
8
9
|
writeWorkflowMd,
|
|
9
10
|
} from "./_agent-setup.mjs";
|
|
@@ -28,6 +29,8 @@ console.log(
|
|
|
28
29
|
);
|
|
29
30
|
console.log(` • .claude/godxjp-ui-workflow.md — ${md ? "created" : "already present"}`);
|
|
30
31
|
console.log(` • CLAUDE.md — godxjp-ui mandate (${claudeMd})`);
|
|
32
|
+
const outside = outOfProjectUiMcpReport(root);
|
|
33
|
+
if (outside) console.log(outside);
|
|
31
34
|
console.log(`
|
|
32
35
|
The auto-audit hook now runs on every Write/Edit of a .tsx file and feeds findings
|
|
33
36
|
back to the agent — it cannot skip the audit. Restart your agent to load the MCP + hooks.
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ensureClaudeMd,
|
|
9
9
|
ensureMcpJson,
|
|
10
10
|
ensureConsumerRules,
|
|
11
|
+
outOfProjectUiMcpReport,
|
|
11
12
|
refreshGuineaPigSkill,
|
|
12
13
|
shouldSkip,
|
|
13
14
|
writeWorkflowMd,
|
|
@@ -25,6 +26,10 @@ try {
|
|
|
25
26
|
if (r.startsWith("left untouched") || r.startsWith("present (custom godx-ui")) {
|
|
26
27
|
console.log(`\n @godxjp/ui → .mcp.json ${r}\n`);
|
|
27
28
|
}
|
|
29
|
+
// A registration outside the project is reported whatever the project file says, before any of
|
|
30
|
+
// the quiet exits below: it is live beside ours and nothing here will ever change it (gh#722).
|
|
31
|
+
const outside = outOfProjectUiMcpReport(root);
|
|
32
|
+
if (outside) console.log(outside);
|
|
28
33
|
// The mandate is plain text the agent reads every turn (CLAUDE.md block + workflow file). It
|
|
29
34
|
// changes nothing in the dev loop, so it is installed by default: an agent that never saw the
|
|
30
35
|
// but no mandate). Only the hooks — which DO change the loop — stay behind `init-agent`.
|