@godxjp/ui-mcp 0.17.0 → 0.18.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
@@ -950,6 +950,99 @@ export default function InvoiceList({
950
950
  storyPath: "data-display/DataTable.stories.tsx",
951
951
  rules: [24, 31, 35, 37]
952
952
  },
953
+ {
954
+ name: "DataGrid",
955
+ group: "data-display",
956
+ tagline: "Full-feature data grid \u2014 the TanStack Table adapter on `@godxjp/ui/data-grid` (NOT the data-display barrel). Adds column sort, global search, column visibility ('set view'), per-page + numbered pagination, row selection + bulk actions, and density over the styled Table* primitives. Defaults to SERVER/manual mode: wire sorting/columnFilters/globalFilter/pagination to your AJAX query (pass rowCount). Use DataTable instead for a lean server-driven list that must NOT pull TanStack. Requires the `@tanstack/react-table` peer dependency.",
957
+ props: [
958
+ {
959
+ name: "columns",
960
+ type: "ColumnDef<T, unknown>[]",
961
+ required: true,
962
+ description: "TanStack column definitions ({ accessorKey, header, cell, enableSorting, enableHiding, meta:{label} }). Set enableHiding:false to keep a column out of the ViewOptions menu; meta.label gives a human label there when header is JSX."
963
+ },
964
+ {
965
+ name: "data",
966
+ type: "T[]",
967
+ required: true,
968
+ description: "Row data. Empty + loading=false renders a built-in EmptyState in the body."
969
+ },
970
+ {
971
+ name: "getRowId",
972
+ type: "(row: T) => string",
973
+ description: "Stable row id (defaults to row[rowIdKey], rowIdKey defaults to 'id')."
974
+ },
975
+ {
976
+ name: "enableRowSelection",
977
+ type: "boolean",
978
+ defaultValue: "false",
979
+ description: "Adds a checkbox column + header select-all; pair with DataGrid.BulkActions."
980
+ },
981
+ {
982
+ name: "sorting / onSortingChange",
983
+ type: "SortingState / OnChangeFn<SortingState>",
984
+ description: "Server sort: pass both and sort in your query (manualSorting defaults true). Omit both for client sort."
985
+ },
986
+ {
987
+ name: "globalFilter / onGlobalFilterChange",
988
+ type: "string / OnChangeFn<string>",
989
+ description: "Global search term, surfaced by DataGrid.Search. Server or client like sorting."
990
+ },
991
+ {
992
+ name: "pagination / onPaginationChange / rowCount",
993
+ type: "PaginationState / OnChangeFn / number",
994
+ description: "Server pagination: pass pagination + onPaginationChange + rowCount (total). Omit for client pagination."
995
+ },
996
+ {
997
+ name: "columnVisibility / onColumnVisibilityChange",
998
+ type: "VisibilityState / OnChangeFn<VisibilityState>",
999
+ description: "Column show/hide state surfaced by DataGrid.ViewOptions ('set view'). Internal if omitted."
1000
+ },
1001
+ {
1002
+ name: "manualSorting / manualFiltering / manualPagination",
1003
+ type: "boolean",
1004
+ defaultValue: "true",
1005
+ description: "Default true (server/AJAX). Set false to let TanStack sort/filter/paginate in-browser."
1006
+ },
1007
+ {
1008
+ name: "loading / density / onRowClick / empty",
1009
+ type: "boolean / 'compact'|'comfortable' / (row:T)=>void / ReactNode",
1010
+ description: "Loading row, controlled density, clickable rows, custom empty content."
1011
+ }
1012
+ ],
1013
+ usage: [
1014
+ "Import from `@godxjp/ui/data-grid` \u2014 it lives on its own subpath because it pulls @tanstack/react-table; it is NOT in the runtime-neutral root or the data-display barrel.",
1015
+ "Compose the compound parts as children: <DataGrid.Toolbar> (holds <DataGrid.BulkActions>, <DataGrid.Search>, <DataGrid.ViewOptions>, <DataGrid.DensityToggle>), then <DataGrid.Content> (auto-included if omitted) and <DataGrid.Pagination pageSizeOptions=[...]>.",
1016
+ "Server mode (default): drive sorting/globalFilter/pagination from useQuery and pass rowCount. Client mode: set manualSorting/manualFiltering/manualPagination={false} and the grid handles it on the data array."
1017
+ ],
1018
+ related: ["DataTable", "Table", "DataState", "Select", "DropdownMenu"],
1019
+ example: `import { DataGrid, type ColumnDef } from "@godxjp/ui/data-grid";
1020
+ import { Flex } from "@godxjp/ui/layout";
1021
+
1022
+ type Row = { id: string; name: string; amount: number };
1023
+ const columns: ColumnDef<Row, unknown>[] = [
1024
+ { accessorKey: "name", header: "Name", meta: { label: "Name" } },
1025
+ { accessorKey: "amount", header: "Amount", meta: { label: "Amount" } },
1026
+ ];
1027
+
1028
+ export function Grid({ rows }: { rows: Row[] }) {
1029
+ return (
1030
+ <DataGrid columns={columns} data={rows} getRowId={(r) => r.id} enableRowSelection manualSorting={false} manualFiltering={false} manualPagination={false}>
1031
+ <DataGrid.Toolbar>
1032
+ <Flex direction="row" align="center" gap="sm" className="ms-auto">
1033
+ <DataGrid.Search />
1034
+ <DataGrid.ViewOptions />
1035
+ <DataGrid.DensityToggle />
1036
+ </Flex>
1037
+ </DataGrid.Toolbar>
1038
+ <DataGrid.Content />
1039
+ <DataGrid.Pagination pageSizeOptions={[10, 20, 50]} />
1040
+ </DataGrid>
1041
+ );
1042
+ }`,
1043
+ storyPath: "data-display/DataGrid.stories.tsx",
1044
+ rules: [24, 31, 35, 37]
1045
+ },
953
1046
  {
954
1047
  name: "Card",
955
1048
  group: "data-display",
@@ -6508,6 +6601,11 @@ var CARDINAL_RULES = [
6508
6601
  number: 40,
6509
6602
  title: "Pages are mobile-first",
6510
6603
  body: "Author and verify every page at 320\u2013390px FIRST. Spacing comes only from `Stack` / `Inline` `gap` + `ResponsiveGrid columns={2|3|4}` (which collapse to a single column on narrow screens) \u2014 never raw `p-*` / `gap-*` / `space-*` utilities for page layout. Wide tables scroll horizontally on small screens (don't force-fit them); dialogs and sheets are full-height on mobile. Touch targets \u2265 44\xD744px."
6604
+ },
6605
+ {
6606
+ number: 41,
6607
+ title: "Drawer & dialog footer layout",
6608
+ body: 'Sheet/Dialog/AlertDialog footers are a pinned action bar (Ant Design Drawer footer): the footer sticks to the bottom, SheetFooter draws a full-bleed top border, and actions are RIGHT-aligned with the PRIMARY button rightmost (Cancel/secondary to its left). A destructive / clear / reset action goes far-LEFT \u2014 give that button `className="mr-auto"`. NEVER stack footer buttons full-width or center them.'
6511
6609
  }
6512
6610
  ];
6513
6611
  function findRule(num) {
@@ -7554,6 +7652,140 @@ XProp + XProp as XProps and register in props/registry. Then: add an MCP catalog
7554
7652
  real-screen docs page; verify typecheck/lint/audit/check:*/preview:build/test all green.`
7555
7653
  }
7556
7654
  ]
7655
+ },
7656
+ // ── design-to-page (consumer: handoff → real page) ─────────────
7657
+ {
7658
+ id: "design-to-page",
7659
+ name: "Design handoff \u2192 real page (consumer build guide)",
7660
+ whenToUse: "You (a consumer agent) received a Claude Design handoff \u2014 a bundle/mock/screenshot/HTML prototype or a written brief \u2014 and must build it as a REAL page with @godxjp/ui. Read this BEFORE writing any JSX. It teaches: read intent, map every block to a real primitive via this MCP, consume existing tokens, apply the dxs-kintai DNA, treat tables as the centerpiece, resolve gaps by extend-or-ask, and verify.",
7661
+ source: "@godxjp/ui .design/research (chats-intent, tables, atomic-components) + dxs-kintai SKILL/colors_and_type.css",
7662
+ sections: [
7663
+ {
7664
+ id: "read-intent",
7665
+ title: "Read the intent \u2014 chats before pixels",
7666
+ tagline: "A handoff is a prototype, not production code. Build the intent, not the markup.",
7667
+ body: `A Claude Design bundle is HTML/CSS/JS to LOOK AT \u2014 never transcribe its DOM.
7668
+ If the bundle has chats/*.md, read them FIRST: they hold what the user actually
7669
+ wanted after iterating, the directions rejected, and the explicit rules. The final
7670
+ HTML is just the last output; the chat is the intent. Then read the README/SKILL +
7671
+ colors_and_type.css for the DNA. Distil each screen to ONE primary question it
7672
+ answers (one-intent-per-screen) before choosing components. Honesty rules that
7673
+ recur in this DNA: render only VALID actions (no disabled-button noise \u2014 a punch
7674
+ card off-state shows Check-In only, never a greyed Check-Out); label = identity
7675
+ (never changes), helper row = state (error/help goes BELOW, never recolours the
7676
+ label); entry-point affordances live in chrome, not floating in content.`
7677
+ },
7678
+ {
7679
+ id: "map-to-primitives",
7680
+ title: "Map every block to a real primitive \u2014 MCP-first, never hand-roll",
7681
+ tagline: "For each visual block ask 'which @godxjp/ui component is this?' \u2014 list_primitives, then get_component.",
7682
+ body: `NEVER hand-roll a styled <div> that looks like a Card, or use raw
7683
+ <input>/<select>/<button>/<table>. Decompose each screen into a shopping list and
7684
+ resolve each item through THIS MCP: list_primitives to discover, get_component to
7685
+ confirm the exact prop/union before you write (never guess a prop). Typical map:
7686
+ page chrome \u2192 AppShell/Sidebar/Topbar/PageContainer; stat row \u2192 ResponsiveGrid +
7687
+ StatCard; data grid \u2192 DataTable; status pill \u2192 Badge tone=\u2026; filter row \u2192 Form
7688
+ inline + Select/Input; org\u2192branch \u2192 Cascader/TreeSelect; date/time \u2192 DatePicker/
7689
+ TimePicker; \u2318K \u2192 Command; bulk drawer/detail \u2192 Drawer/Sheet/Dialog; split list+
7690
+ detail \u2192 SplitPane/Resizable; empty \u2192 EmptyState; confirm \u2192 AlertDialog; toast \u2192
7691
+ Sonner. No duplication: Select (showSearch/loadOptions) is the ONLY searchable/
7692
+ async select (no Combobox/Autocomplete); the 4 i18n pickers are one AppSettingPicker
7693
+ kind=\u2026. A table = Card + CardContent-flush + DataTable (not PageContainer flush).`
7694
+ },
7695
+ {
7696
+ id: "tokens-exist",
7697
+ title: "Tokens already exist \u2014 consume var(--\u2026), never redeclare",
7698
+ tagline: "The design's colors_and_type.css is already implemented as foundation.css.",
7699
+ body: `The handoff's colors_and_type.css (SmartHR blue, wa-iro, M PLUS 2, the
7700
+ density scale) is ALREADY shipped as @godxjp/ui's foundation tokens. Never paste a
7701
+ hex, never redeclare a token, never invent a neutral. Consume var(--\u2026) and the
7702
+ semantic utilities. Use get_tokens (MCP) to find the right name \u2014 if a token seems
7703
+ missing it almost certainly exists under a different name. Soft tints come from
7704
+ color-mix(in oklch, var(--primary) 15%, transparent), NOT a new pale hex. Control
7705
+ heights come from the density scale (xs 24 / sm 28 / default 32 / lg 36 / xl 44),
7706
+ never a literal px. Radii: card 6px, control 4px, inner pill 2px.`
7707
+ },
7708
+ {
7709
+ id: "dna",
7710
+ title: "Apply the dxs-kintai DNA",
7711
+ tagline: "\u6E0B\u307F / \u9593 / \u7C21\u7D20 \u2014 fixed color signaling, dense, small headings, 14/1.7, no emoji.",
7712
+ body: `These rules survive when you drop the prototype's divs:
7713
+ \u2022 \u6E0B\u307F (restraint): primary chroma \u2264 0.18 \u2014 --primary is the single most-important
7714
+ action + brand surfaces ONLY, never status. No gradients, no pill cards, no
7715
+ saturated brand.
7716
+ \u2022 \u9593 (breathing): body 14px / 1.7 (NEVER 16/1.5); tabular-nums on every numeric
7717
+ column/stat so digits align under 1.7 leading.
7718
+ \u2022 \u7C21\u7D20 (simplicity): three weights only \u2014 400/500/700 (no 300, no 600). Headings
7719
+ stay SMALL: h1 = 20px, h2 = 18 (not 32) \u2014 JP enterprise is dense, big headings
7720
+ waste \u9593.
7721
+ \u2022 Color signaling is FIXED-mapping: success \u82E5\u7AF9 \xB7 warning \u5C71\u5439(yellow) \xB7 info \u7FA4\u9752
7722
+ \xB7 attention \u6731(orange \u2014 PREFER over red for non-destructive: \u9045\u523B/lateness) \xB7
7723
+ danger \u831C(destructive only). Wa-iro is decorative (charts/tags/tenant) \u2014 NEVER
7724
+ remap a wa-iro hue to a semantic role.
7725
+ \u2022 Density up front: compact 28 (heavy tables) \xB7 default 32 \xB7 comfortable 44 (login/
7726
+ mobile, 44px touch floor). Set on the container; don't mix mid-page.
7727
+ \u2022 Cards: 1px border, NO shadow at rest (shadows only on popover md / dialog xl).
7728
+ \u2022 Copy quiet & factual \u2014 \u300C\u627F\u8A8D\u3057\u307E\u3057\u305F\u300D not \u300C\u627F\u8A8D\u306B\u6210\u529F\u3057\u307E\u3057\u305F\u{1F389}\u300D. Empty state =
7729
+ one calm sentence, no illustration. NO emoji in product UI; Lucide 1.5px icons,
7730
+ currentColor, sized by context (14 table / 16 nav / 18 button / 20 header).
7731
+ \u2022 Multi-tenant: tenants override only --primary/--ring/--foreground; semantic
7732
+ colors stay shared (a "rejected" badge means the same everywhere).`
7733
+ },
7734
+ {
7735
+ id: "tables-central",
7736
+ title: "Tables are the centerpiece \u2014 DataTable + the variant catalogue",
7737
+ tagline: "Enterprise \u52E4\u6020/admin lives in tables; showcase the family broadly.",
7738
+ body: `Most of this DNA's real value is in tables \u2014 make DataTable the
7739
+ centerpiece. One shell: Card + CardContent-flush wrapping DataTable (1px border,
7740
+ 6px radius, no shadow). Region order: view tabs \xB7 toolbar (search + \u2318K + density +
7741
+ columns + import/export + primary CTA) \xB7 active-filter chip bar \xB7 table \xB7 footer
7742
+ totals \xB7 pagination \u2014 every region optional. Build each pattern as its own block:
7743
+ assembled CRUD list \xB7 bulk-action toolbar (selection REPLACES toolbar; cross-page
7744
+ "select all 1,284"; destructive isolated last) \xB7 column manager \xB7 advanced filter
7745
+ AND/OR \xB7 sort/resize \xB7 expandable detail row \xB7 inline editable row (row-level
7746
+ commit, dirty dot, "\u672A\u4FDD\u5B58" footer) \xB7 grouped rows w/ subtotals \xB7 tree rows \xB7 sticky
7747
+ columns + horizontal scroll \xB7 pagination \xD73 (numbered/load-more/cursor) \xB7 import/
7748
+ export stepper \xB7 empty/loading(Skeleton)/error/no-perm states \xB7 footer totals \xB7
7749
+ compact kintone grid \xB7 conditional row/cell formatting. Cells: status \u2192 Badge tone;
7750
+ identity \u2192 Avatar + two-line; numerics right-aligned tabular-nums with \u2014 for null;
7751
+ IDs mono. Confirmed (\u78BA\u5B9A\u6E08) rows are frozen \u2014 no edit, no destructive bulk. Row
7752
+ states change only background via color-mix, never height/padding. get_component
7753
+ DataTable + get_vocab ColumnDef/TableDensity/SortState before you build.`
7754
+ },
7755
+ {
7756
+ id: "gaps-extend-or-ask",
7757
+ title: "Gaps \u2192 extend or ask \u2014 never invent",
7758
+ tagline: "A block no primitive expresses is a decision, not a hand-roll.",
7759
+ body: `When a block has no clean primitive/prop/variant, do NOT bake a bespoke
7760
+ one-off into the page. First try to EXTEND: can an existing component take one more
7761
+ tone/size/variant/slot, or be composed from existing primitives (e.g. a punch-card
7762
+ FSM, a mobile selection-bar, an i18n locale-field are compositions over Button/Card/
7763
+ Badge/Tabs/Input, not new primitives)? If it's a genuine gap or you're unsure, STOP
7764
+ and ASK the user (or surface it as an ADR/decision) \u2014 name the gap, propose
7765
+ "new variant on <X> vs. app-level composition vs. new component", and converge
7766
+ before building. Known gaps to expect in this DNA (ask rather than invent): three-
7767
+ level table density (current is binary), multi-sort priority badges, column resize/
7768
+ manager, numbered/load-more pagination, expandable/editable/grouped/tree/sticky-col
7769
+ table modes, filter chip bar + AND/OR panel, saved-view tabs, week-timeline/staff\xD7
7770
+ time calendar, multilingual-field, no-code builders. Never silently fill a gap.`
7771
+ },
7772
+ {
7773
+ id: "verify",
7774
+ title: "Verify \u2014 states complete, a11y, build green",
7775
+ tagline: "Every state shown, WCAG 2.2 AA, typecheck/lint/audit clean, eyeballed at 3 widths.",
7776
+ body: `Before calling it done: every prop \xD7 union value \xD7 state is exercised
7777
+ (default/hover/focus/active/disabled/loading/empty/error) \u2014 Skeleton for INIT fetch,
7778
+ spinner/loading for active save, EmptyState for no-data, inline error near the field
7779
+ (not a disappearing toast). A11y: correct roles/landmarks, keyboard (arrows/Home/End/
7780
+ Enter/Esc, visible focus, no positive tabindex), \u226524px targets, never colour-only
7781
+ state (add sr-only text), icon-only buttons have a name; aim for 0 vitest-axe
7782
+ violations. i18n: zero hardcoded strings \u2014 every label + aria-label through t(),
7783
+ format numbers/dates via Intl. Then run the build: pnpm typecheck + pnpm lint +
7784
+ pnpm audit must be green, console clean, and eyeball the page at 390 / 768 / 1280
7785
+ (atoms never wrap, containers wrap with row-gap, tabs horizontal-scroll, grids
7786
+ minmax(0,1fr), heights never break).`
7787
+ }
7788
+ ]
7557
7789
  }
7558
7790
  ];
7559
7791
  function findSkill(id) {
@@ -7652,6 +7884,13 @@ function routeTask(task) {
7652
7884
  "workflow",
7653
7885
  "Generate design image first \u2192 analyze \u2192 implement."
7654
7886
  );
7887
+ route(
7888
+ ["handoff", "design bundle", "claude design", "prototype", "build the page", "implement the design", "build this screen", "mockup"],
7889
+ "design-to-page",
7890
+ "map-to-primitives",
7891
+ "Map every block to a real @godxjp/ui primitive (MCP-first), consume existing tokens, apply the dxs-kintai DNA, tables central, gaps \u2192 extend-or-ask, verify.",
7892
+ ["design-to-page/read-intent", "design-to-page/dna", "design-to-page/tables-central"]
7893
+ );
7655
7894
  if (matches.length === 0) {
7656
7895
  return [
7657
7896
  {
@@ -9155,12 +9394,71 @@ ${c.example}
9155
9394
  return out;
9156
9395
  }
9157
9396
 
9397
+ // package.json
9398
+ var package_default = {
9399
+ name: "@godxjp/ui-mcp",
9400
+ version: "0.18.0",
9401
+ 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, 34 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).",
9402
+ type: "module",
9403
+ main: "./dist/index.js",
9404
+ module: "./dist/index.js",
9405
+ types: "./dist/index.d.ts",
9406
+ bin: {
9407
+ "godx-ui-mcp": "./dist/index.js"
9408
+ },
9409
+ files: [
9410
+ "dist",
9411
+ "README.md"
9412
+ ],
9413
+ publishConfig: {
9414
+ registry: "https://registry.npmjs.org/",
9415
+ access: "public"
9416
+ },
9417
+ repository: {
9418
+ type: "git",
9419
+ url: "git+https://github.com/godx-jp/godxjp-ui.git",
9420
+ directory: "mcp"
9421
+ },
9422
+ homepage: "https://github.com/godx-jp/godxjp-ui/tree/main/mcp#readme",
9423
+ license: "Apache-2.0",
9424
+ scripts: {
9425
+ build: "tsup",
9426
+ dev: "tsup --watch",
9427
+ start: "node dist/index.js",
9428
+ inspect: "npx @modelcontextprotocol/inspector node dist/index.js",
9429
+ "type-check": "tsc --noEmit",
9430
+ test: "vitest run",
9431
+ prepublishOnly: "npm run build"
9432
+ },
9433
+ dependencies: {
9434
+ "@modelcontextprotocol/sdk": "^1.29.0",
9435
+ zod: "^4.4.3"
9436
+ },
9437
+ devDependencies: {
9438
+ "@types/node": "^22.10.0",
9439
+ tsup: "^8.5.1",
9440
+ typescript: "^6.0.3",
9441
+ vitest: "^4.1.6"
9442
+ },
9443
+ keywords: [
9444
+ "mcp",
9445
+ "model-context-protocol",
9446
+ "godxjp",
9447
+ "ui",
9448
+ "design-system",
9449
+ "react",
9450
+ "claude",
9451
+ "cursor"
9452
+ ]
9453
+ };
9454
+
9158
9455
  // src/index.ts
9159
9456
  async function main() {
9160
9457
  const server = new Server(
9161
9458
  {
9162
9459
  name: "godx-ui-mcp",
9163
- version: "0.1.0"
9460
+ // Track the package version — never hardcode (see server.test.ts guard).
9461
+ version: package_default.version
9164
9462
  },
9165
9463
  {
9166
9464
  capabilities: {