@godxjp/ui-mcp 0.21.5 → 0.22.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/index.js CHANGED
@@ -9535,6 +9535,84 @@ minimal repro, expected vs actual, the installed version, and env \u2014 enough
9535
9535
  reproduce in one paste.`
9536
9536
  }
9537
9537
  ]
9538
+ },
9539
+ // ── app-performance (consumer) ─────────────────────────────────
9540
+ {
9541
+ id: "app-performance",
9542
+ audience: "consumer",
9543
+ name: "App performance \u2014 measure-first React perf with @godxjp/ui",
9544
+ whenToUse: "A screen built on @godxjp/ui feels slow, Chrome logs [Violation] handler warnings, typing lags in a filter pane, a panel toggle blocks, or the bundle is questioned. Distilled from a real audit (orders screen: keystroke 165ms \u2192 5ms, panel open 270ms \u2192 18ms, app bundle \u221227%). Measure FIRST \u2014 the library's per-control cost is small (~3ms/field dev); page architecture is almost always the culprit.",
9545
+ source: "@godxjp/ui MCP (consumer surface) \u2014 2026-06 exseli audit, verified numbers",
9546
+ sections: [
9547
+ {
9548
+ id: "measure-first",
9549
+ title: "Measure before touching anything",
9550
+ tagline: "Long tasks + a temporary React Profiler tell you WHO is slow \u2014 never guess.",
9551
+ body: `Three probes, run in the page (devtools console / playwright evaluate):
9552
+ 1) Long tasks \u2014 anything >50ms in a handler triggers Chrome's [Violation]:
9553
+ const t=[]; new PerformanceObserver(l=>l.getEntries().forEach(e=>t.push(Math.round(e.duration))))
9554
+ .observe({type:"longtask",buffered:true});
9555
+ 2) Attribution \u2014 wrap suspect sections temporarily:
9556
+ <Profiler id="sec" onRender={(id,phase,d)=>(window.__perf??=[]).push([id,phase,Math.round(d)])}>
9557
+ Compare each section's actualDuration against the total long task. In the reference audit
9558
+ 25 @godxjp/ui composite fields mounted in 79ms \u2014 the other ~150ms was the PAGE re-rendering
9559
+ everything else. Indict with numbers, then fix only what they indict.
9560
+ 3) Dev-mode caveat: development React is 3\u20135\xD7 slower; a one-off 60ms task at popup-open is
9561
+ normal. Re-measure AFTER the fix with the same probes and paste before/after numbers.`
9562
+ },
9563
+ {
9564
+ id: "filter-pane-memo",
9565
+ title: "Filter panes: per-field memo + stable setters",
9566
+ tagline: "Page-root state with no memo boundaries = the whole pane re-renders per keystroke.",
9567
+ body: `The classic failure: all search state lives at the page root, every field reads it
9568
+ inline \u2192 one keystroke re-renders ~30 fields + the results table (165ms/key measured).
9569
+ The proven fix shape:
9570
+ - module-level memo field units: const FText = memo(function FText({ id, label, k, value, onSet }) {
9571
+ return <FormField id={id} label={label}><Input id={id} value={value}
9572
+ onChange={(e) => onSet(k, e.target.value)} /></FormField>; });
9573
+ - ONE stable setter per state map: const setField = useCallback((key, value) =>
9574
+ setCond(c => ({ ...c, [key]: value })), []);
9575
+ - the results table in its OWN memo component; pagination pages WITHIN the submitted query
9576
+ (setSubmitted(prev => ({ ...prev, page }))) so its handler stays identity-stable.
9577
+ After: a keystroke re-renders exactly one field (5ms). Don't memo cheap leaves that re-render
9578
+ rarely \u2014 over-memoization is real overhead. react-compiler lint traps: no ref writes during
9579
+ render, no sync setState in effect bodies; the sanctioned latch is the guarded render-time set
9580
+ (if (cond && !state) setState(true)).`
9581
+ },
9582
+ {
9583
+ id: "heavy-panels",
9584
+ title: "Heavy hidden panels: defer, keep mounted, pre-mount at idle",
9585
+ tagline: "Never mount a 25-field subtree synchronously inside a click handler.",
9586
+ body: `A \u8A73\u7D30\u6761\u4EF6-style toggle that conditionally renders a large subtree blocks the click
9587
+ (~230ms measured). Three-layer fix, in order:
9588
+ 1) urgent state drives only the button chrome (chevron/aria-expanded);
9589
+ 2) const deferredOpen = useDeferredValue(open) gates the FIRST mount into a deferred lane;
9590
+ 3) keep it mounted afterwards and toggle visibility: <div className={open ? "contents" : "hidden"}>
9591
+ ("contents" keeps children in the parent flex/grid rhythm; field state lives in the page so
9592
+ hiding loses nothing);
9593
+ 4) optionally pre-mount during idle after first paint so even the FIRST open is instant:
9594
+ useEffect(() => { const idle = window.requestIdleCallback ?? (cb => setTimeout(cb, 300));
9595
+ const h = idle(() => setMounted(true)); return () => (window.cancelIdleCallback ?? clearTimeout)(h); }, []);
9596
+ Measured after: open 270ms \u2192 18ms, zero post-load long tasks.`
9597
+ },
9598
+ {
9599
+ id: "bundle-budget",
9600
+ title: "Code splitting + what an import costs",
9601
+ tagline: "lazy() every page; know the per-import budget before blaming the library.",
9602
+ body: `Route-level splitting is the default app shape: const Page = lazy(() => import("@/pages/Page"))
9603
+ behind ONE <Suspense fallback={<PageContainer title={<Skeleton \u2026/>}><Skeleton \u2026/></PageContainer>}>.
9604
+ Reference app: initial 929KB \u2192 675KB; the orders screen (day-picker + table stack, 122KB) and
9605
+ login (react-hook-form + zod, 93KB) load only when visited.
9606
+ Per-import minified budget of @godxjp/ui \u226513.10.0 (preserved-module dist \u2014 imports tree-shake
9607
+ for real): StatCard 30KB \xB7 Input 52 \xB7 Button 56 \xB7 DataTable 79 \xB7 Select 165 \xB7 DateRangePicker 207
9608
+ (genuinely needs react-day-picker + date-fns). A shared ~50KB floor is intrinsic (tailwind-merge
9609
+ + bundled 3-locale i18n) and amortizes across one vendor chunk. Virtualize lists only >100 rows \u2014
9610
+ DataTable at 50/page does not need it. The dist is bundler-oriented ESM (extensionless + JSON
9611
+ imports): fine for vite/webpack consumers; when testing against a local checkout run tests on an
9612
+ npm-pack TARBALL install, not a file: symlink (the symlink's nested node_modules creates a
9613
+ dual-React artifact under vitest).`
9614
+ }
9615
+ ]
9538
9616
  }
9539
9617
  ];
9540
9618
  function findSkill(id) {
@@ -9686,6 +9764,29 @@ function routeTask(task, opts) {
9686
9764
  "If @godxjp/ui itself is at fault, don't fake a workaround \u2014 file a detailed gh issue (use draft_bug_report).",
9687
9765
  ["design-to-page/report-bug"]
9688
9766
  );
9767
+ route(
9768
+ [
9769
+ "slow",
9770
+ "performance",
9771
+ "perf",
9772
+ "violation",
9773
+ "long task",
9774
+ "lag",
9775
+ "janky",
9776
+ "re-render",
9777
+ "rerender",
9778
+ "bundle size",
9779
+ "code splitting",
9780
+ "tree-shak",
9781
+ "ch\u1EADm",
9782
+ "l\u1ED7i hi\u1EC7u n\u0103ng",
9783
+ "\u91CD\u3044"
9784
+ ],
9785
+ "app-performance",
9786
+ "measure-first",
9787
+ "Measure FIRST (longtask + temporary Profiler), then apply the matching proven fix \u2014 page architecture, not the library, is almost always the culprit.",
9788
+ ["app-performance/filter-pane-memo", "app-performance/heavy-panels", "app-performance/bundle-budget"]
9789
+ );
9689
9790
  const filtered = opts?.consumerOnly ? matches.filter((m) => {
9690
9791
  const sk = findSkill(m.skill);
9691
9792
  return !sk || sk.audience !== "core";
@@ -11467,7 +11568,7 @@ ${c.example}
11467
11568
  // package.json
11468
11569
  var package_default = {
11469
11570
  name: "@godxjp/ui-mcp",
11470
- version: "0.21.5",
11571
+ version: "0.22.0",
11471
11572
  description: "Model Context Protocol server for @godxjp/ui \u2014 gives Claude Code / Codex CLI / Cursor / any MCP-aware agent live access to the component catalog, prop vocabulary, design tokens, 45 cardinal rules, copy-paste-ready patterns, 12 design / taste skills synthesised from Leonxlnx/taste-skill, 20+ anti-AI-tell patterns, and a 50-check redesign audit \u2014 token-efficient (list \u2192 drill-down).",
11472
11573
  type: "module",
11473
11574
  main: "./dist/index.js",