@godxjp/ui-mcp 0.17.1 → 0.19.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/README.md +66 -29
- package/dist/index.js +616 -76
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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",
|
|
@@ -1511,10 +1604,79 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1511
1604
|
rules: []
|
|
1512
1605
|
},
|
|
1513
1606
|
// ─── data-entry ─────────────────────────────────────────────────────────
|
|
1607
|
+
{
|
|
1608
|
+
name: "Form",
|
|
1609
|
+
group: "data-entry",
|
|
1610
|
+
tagline: "Ant-style layout container \u2014 renders <form> and pushes layout (vertical/horizontal), labelWidth/controlWidth, label alignment, responsive collapse, and multi-column grid down to every FormField (overridable per field).",
|
|
1611
|
+
props: [
|
|
1612
|
+
{
|
|
1613
|
+
name: "layout",
|
|
1614
|
+
type: '"vertical" | "horizontal" | "inline"',
|
|
1615
|
+
defaultValue: '"vertical"',
|
|
1616
|
+
description: "Label position relative to control; applied to all FormFields."
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
name: "labelWidth",
|
|
1620
|
+
type: "number | string",
|
|
1621
|
+
description: "Label column width in horizontal layout (number\u2192px). e.g. 120 or '8rem'."
|
|
1622
|
+
},
|
|
1623
|
+
{
|
|
1624
|
+
name: "controlWidth",
|
|
1625
|
+
type: "number | string",
|
|
1626
|
+
description: "Cap the control width (number\u2192px). Omit to fill the column."
|
|
1627
|
+
},
|
|
1628
|
+
{
|
|
1629
|
+
name: "labelAlign",
|
|
1630
|
+
type: '"start" | "end"',
|
|
1631
|
+
defaultValue: '"end"',
|
|
1632
|
+
description: "Horizontal alignment of the label within its column."
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
name: "collapseBelow",
|
|
1636
|
+
type: '"sm" | "md" | "lg" | "xl" | false',
|
|
1637
|
+
defaultValue: '"md"',
|
|
1638
|
+
description: "Breakpoint below which horizontal collapses to vertical (mobile-first). false = always horizontal."
|
|
1639
|
+
},
|
|
1640
|
+
{
|
|
1641
|
+
name: "columns",
|
|
1642
|
+
type: "number | { sm?: number; md?: number; lg?: number }",
|
|
1643
|
+
description: "Lay fields out in a responsive grid (reuses ResponsiveGrid; 1 col on small)."
|
|
1644
|
+
},
|
|
1645
|
+
{
|
|
1646
|
+
name: "density",
|
|
1647
|
+
type: '"compact" | "default" | "comfortable"',
|
|
1648
|
+
description: "Apply a density to controls inside the form."
|
|
1649
|
+
}
|
|
1650
|
+
],
|
|
1651
|
+
usage: [
|
|
1652
|
+
"DO set `layout`, `labelWidth`, `controlWidth` ONCE on `<Form>` \u2014 every `<FormField>` inside inherits them. Override a single field by passing the same prop on that `<FormField>` (Form \u2192 FormField priority).",
|
|
1653
|
+
"DO rely on mobile-first collapse: `layout='horizontal'` automatically stacks to vertical below `collapseBelow` (default `md`). Pass `collapseBelow={false}` only when a field MUST stay label-beside-control even on phones.",
|
|
1654
|
+
"DO use `columns` for multi-field forms (e.g. `columns={2}`) \u2014 it reuses ResponsiveGrid (1 column on small screens, more on md/lg). Span a wide field across columns with `<FormField colSpan={2}>`.",
|
|
1655
|
+
"DON'T hand-roll a `<form>` + Flex stack for spacing \u2014 `<Form>` provides the vertical rhythm and the layout context FormField reads. Wire react-hook-form by spreading `onSubmit={handleSubmit(...)}` onto `<Form>`."
|
|
1656
|
+
],
|
|
1657
|
+
useCases: [
|
|
1658
|
+
"A settings page form where every label sits in a fixed 120px column to the left of its control (horizontal), collapsing to stacked labels on mobile.",
|
|
1659
|
+
"A two-column entity-edit form (`columns={2}`) where the address field spans both columns (`colSpan={2}`).",
|
|
1660
|
+
"A compact filter form (`layout='horizontal' density='compact'`) above a DataTable."
|
|
1661
|
+
],
|
|
1662
|
+
related: [
|
|
1663
|
+
"FormField \u2014 the per-field wrapper (label + control + helper/error) that reads Form's layout context; use one per control inside a Form.",
|
|
1664
|
+
"ResponsiveGrid \u2014 Form `columns` reuses it; use ResponsiveGrid directly for non-form card grids."
|
|
1665
|
+
],
|
|
1666
|
+
example: `import { Form, FormField, Input } from "@godxjp/ui/data-entry";
|
|
1667
|
+
|
|
1668
|
+
<Form layout="horizontal" labelWidth={120} columns={2} onSubmit={onSubmit}>
|
|
1669
|
+
<FormField id="first" label="\u59D3"><Input id="first" /></FormField>
|
|
1670
|
+
<FormField id="last" label="\u540D"><Input id="last" /></FormField>
|
|
1671
|
+
<FormField id="address" label="\u4F4F\u6240" colSpan={2}><Input id="address" /></FormField>
|
|
1672
|
+
</Form>`,
|
|
1673
|
+
storyPath: "data-entry/Form.stories.tsx",
|
|
1674
|
+
rules: [23, 24]
|
|
1675
|
+
},
|
|
1514
1676
|
{
|
|
1515
1677
|
name: "FormField",
|
|
1516
1678
|
group: "data-entry",
|
|
1517
|
-
tagline: "Wraps a control with label, helper, and error; injects aria-describedby/aria-invalid onto the child.",
|
|
1679
|
+
tagline: "Wraps a control with label, helper, and error; injects aria-describedby/aria-invalid onto the child. Reads the parent Form's layout (vertical/horizontal) \u2014 overridable per field.",
|
|
1518
1680
|
props: [
|
|
1519
1681
|
{
|
|
1520
1682
|
name: "id",
|
|
@@ -1540,6 +1702,26 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
|
|
|
1540
1702
|
type: "string",
|
|
1541
1703
|
description: "Destructive error message (role=alert); overrides helper."
|
|
1542
1704
|
},
|
|
1705
|
+
{
|
|
1706
|
+
name: "layout",
|
|
1707
|
+
type: '"vertical" | "horizontal" | "inline"',
|
|
1708
|
+
description: "Override the parent Form's layout for this field only."
|
|
1709
|
+
},
|
|
1710
|
+
{
|
|
1711
|
+
name: "labelWidth",
|
|
1712
|
+
type: "number | string",
|
|
1713
|
+
description: "Override the Form's label width for this field."
|
|
1714
|
+
},
|
|
1715
|
+
{
|
|
1716
|
+
name: "controlWidth",
|
|
1717
|
+
type: "number | string",
|
|
1718
|
+
description: "Override the Form's control width for this field."
|
|
1719
|
+
},
|
|
1720
|
+
{
|
|
1721
|
+
name: "colSpan",
|
|
1722
|
+
type: "number",
|
|
1723
|
+
description: "Span N columns when inside a `columns` Form grid."
|
|
1724
|
+
},
|
|
1543
1725
|
{
|
|
1544
1726
|
name: "children",
|
|
1545
1727
|
type: "ReactNode",
|
|
@@ -2249,7 +2431,8 @@ export function InvoiceDueDateField() {
|
|
|
2249
2431
|
usage: [
|
|
2250
2432
|
"Use `Dialog` for form-style or wizard-style modal flows that need freeform content and a close action.",
|
|
2251
2433
|
"DO always control open state via `open` + `onOpenChange`. Dialog has no uncontrolled shortcut \u2014 omitting `open` means the trigger alone drives state, which is fine for simple trigger-only cases, but any async submission flow must use controlled state so you can hold the dialog open while `pending=true` and close it only on success.",
|
|
2252
|
-
"DO include `DialogHeader` with `DialogTitle` (and optionally `DialogDescription`) inside every `DialogContent`. Radix requires an accessible title for screen readers; omitting it triggers a console warning and breaks a11y."
|
|
2434
|
+
"DO include `DialogHeader` with `DialogTitle` (and optionally `DialogDescription`) inside every `DialogContent`. Radix requires an accessible title for screen readers; omitting it triggers a console warning and breaks a11y.",
|
|
2435
|
+
"DO wrap tall/scrolling content in `DialogBody` (the ring-safe scroll slot, max-height ~60vh). It insets the content to match the dialog padding so a full-width control's focus ring never clips against the scroll container \u2014 mirror of SheetBody."
|
|
2253
2436
|
],
|
|
2254
2437
|
useCases: [
|
|
2255
2438
|
"Inline form dialog \u2014 create or edit a record (invoice line, supplier, coupon) without navigating away. Place `FormField`/`Input`/`Select` inside `DialogContent`, wire the submit button to your mutation, and hold `open` while `pending` to prevent double-submit.",
|
|
@@ -2376,20 +2559,33 @@ function CreateDialog() {
|
|
|
2376
2559
|
{
|
|
2377
2560
|
name: "Sheet",
|
|
2378
2561
|
group: "feedback",
|
|
2379
|
-
tagline: "Side-panel drawer (Radix Dialog). Parts: Sheet/SheetTrigger/SheetContent(side=right|left|top|bottom)/SheetHeader/SheetTitle/SheetFooter.",
|
|
2562
|
+
tagline: "Side-panel drawer (Radix Dialog). Parts: Sheet/SheetTrigger/SheetContent(side=right|left|top|bottom)/SheetHeader/SheetBody/SheetTitle/SheetFooter.",
|
|
2380
2563
|
props: [
|
|
2381
2564
|
{ name: "open", type: "boolean", description: "Controlled open state." },
|
|
2382
2565
|
{
|
|
2383
2566
|
name: "onOpenChange",
|
|
2384
2567
|
type: "(open: boolean) => void",
|
|
2385
2568
|
description: "Open-state change handler."
|
|
2569
|
+
},
|
|
2570
|
+
{
|
|
2571
|
+
name: "width",
|
|
2572
|
+
type: "number | string",
|
|
2573
|
+
description: "On SheetContent (side left/right): desired panel width (number\u2192px). Caps at the viewport \u2014 full-width on a small screen (min(width,100%)), NOT a hard fixed width. Default w-3/4 sm:max-w-md."
|
|
2574
|
+
},
|
|
2575
|
+
{
|
|
2576
|
+
name: "title / subtitle / extra / tone",
|
|
2577
|
+
type: "ReactNode / ReactNode / ReactNode / ToneProp",
|
|
2578
|
+
description: "On SheetHeader (Ant-style): title (\u2192 SheetTitle, accessible name), subtitle (\u2192 SheetDescription), right-aligned extra actions, and a soft semantic `tone` background band. Children still supported."
|
|
2386
2579
|
}
|
|
2387
2580
|
],
|
|
2388
2581
|
usage: [
|
|
2582
|
+
"DO build the panel with SheetHeader (pass `title`/`subtitle`/`extra`/`tone` OR children) > SheetBody (scrollable, ring-safe) > SheetFooter (pinned). SheetTitle is required for a11y \u2014 the `title` prop renders it for you. Never skip the title.",
|
|
2583
|
+
"DO set `width` on SheetContent for a wider/narrower panel (e.g. width={480}); it caps at the viewport so small screens still get a full-width panel.",
|
|
2389
2584
|
"DO use all named sub-parts in order: Sheet (root) > SheetTrigger (opener) > SheetContent (panel) > SheetHeader > SheetTitle (required for a11y \u2014 maps to Radix DialogPrimitive.Title, announced as the accessible name) > optional SheetDescription > body content > SheetFooter. Never skip SheetTitle inside an open SheetContent.",
|
|
2390
2585
|
"DO control state explicitly with open + onOpenChange on Sheet root when you need to close programmatically (e.g. after form submit). Uncontrolled (no props) works for simple trigger-only cases but gives you no hook to reset form state on close.",
|
|
2391
2586
|
"DO use SheetTrigger asChild to wrap a Button or other interactive element \u2014 this avoids a nested <button> in the DOM. Never render a raw <button> as a direct child of SheetTrigger.",
|
|
2392
|
-
"DO
|
|
2587
|
+
"DO wrap a long/scrolling body in SheetBody (between SheetHeader and a pinned SheetFooter). It is the ring-safe scroll slot: a hand-rolled <div className='overflow-y-auto'> clips the 3px focus ring of a full-width Input/Select at the scroll edges \u2014 SheetBody insets the content so the ring never clips.",
|
|
2588
|
+
"DO use SheetFooter (renders at the bottom via mt-auto, symmetric 16/24 padding, full-bleed top border) for primary/cancel action Buttons. Never float action Buttons inside the body \u2014 they will not stick to the panel bottom.",
|
|
2393
2589
|
"DON'T set showCloseButton={false} on SheetContent unless you provide your own SheetClose element; omitting both leaves users with no keyboard-accessible close path and breaks a11y.",
|
|
2394
2590
|
"DON'T put a Sheet inside a Dialog (nested Radix portals conflict). If you need a slide-over triggered from within a modal, close the Dialog first, then open the Sheet."
|
|
2395
2591
|
],
|
|
@@ -5697,51 +5893,6 @@ export default function PasswordBlock() {
|
|
|
5697
5893
|
storyPath: "data-entry/PasswordStrength.stories.tsx",
|
|
5698
5894
|
rules: [3, 6]
|
|
5699
5895
|
},
|
|
5700
|
-
{
|
|
5701
|
-
name: "Drawer",
|
|
5702
|
-
group: "feedback",
|
|
5703
|
-
tagline: "Bottom-sheet (vaul) \u2014 a draggable sheet that slides up from the screen edge. DISTINCT from Sheet (the side panel); use Drawer for mobile/touch bottom sheets.",
|
|
5704
|
-
props: [
|
|
5705
|
-
{ name: "open", type: "boolean", description: "Controlled open state." },
|
|
5706
|
-
{
|
|
5707
|
-
name: "onOpenChange",
|
|
5708
|
-
type: "(open: boolean) => void",
|
|
5709
|
-
description: "Open-state callback."
|
|
5710
|
-
},
|
|
5711
|
-
{
|
|
5712
|
-
name: "shouldScaleBackground",
|
|
5713
|
-
type: "boolean",
|
|
5714
|
-
defaultValue: "true",
|
|
5715
|
-
description: "Scale the page behind the sheet (iOS-style)."
|
|
5716
|
-
}
|
|
5717
|
-
],
|
|
5718
|
-
usage: [
|
|
5719
|
-
"DO compose Drawer > DrawerTrigger > DrawerContent (> DrawerHeader/DrawerTitle + body + DrawerFooter).",
|
|
5720
|
-
"DO use Drawer for mobile/touch bottom sheets; use Sheet for a desktop side panel and Dialog for a centered modal.",
|
|
5721
|
-
"DON'T confuse with Sheet \u2014 Sheet slides from a side edge, Drawer is the draggable bottom sheet."
|
|
5722
|
-
],
|
|
5723
|
-
useCases: [
|
|
5724
|
-
"Mobile action sheet / menu",
|
|
5725
|
-
"Filter panel on small screens",
|
|
5726
|
-
"Quick-create form on touch",
|
|
5727
|
-
"Detail peek that drags up"
|
|
5728
|
-
],
|
|
5729
|
-
related: [
|
|
5730
|
-
"Sheet (side panel, same Radix Dialog base, different placement)",
|
|
5731
|
-
"Dialog (centered modal)"
|
|
5732
|
-
],
|
|
5733
|
-
example: `import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle } from "@godxjp/ui/feedback";
|
|
5734
|
-
|
|
5735
|
-
<Drawer>
|
|
5736
|
-
<DrawerTrigger>\u7D5E\u308A\u8FBC\u307F</DrawerTrigger>
|
|
5737
|
-
<DrawerContent>
|
|
5738
|
-
<DrawerHeader><DrawerTitle>\u7D5E\u308A\u8FBC\u307F</DrawerTitle></DrawerHeader>
|
|
5739
|
-
{/* filters */}
|
|
5740
|
-
</DrawerContent>
|
|
5741
|
-
</Drawer>`,
|
|
5742
|
-
storyPath: "feedback/Drawer.stories.tsx",
|
|
5743
|
-
rules: [3, 6, 24]
|
|
5744
|
-
},
|
|
5745
5896
|
{
|
|
5746
5897
|
name: "InputOTP",
|
|
5747
5898
|
group: "data-entry",
|
|
@@ -5991,7 +6142,7 @@ export default function PasswordBlock() {
|
|
|
5991
6142
|
{
|
|
5992
6143
|
name: "Carousel",
|
|
5993
6144
|
group: "data-display",
|
|
5994
|
-
tagline: "Embla-backed carousel primitives
|
|
6145
|
+
tagline: "Embla-backed carousel primitives: previous/next controls, CarouselDots indicators, and a context API.",
|
|
5995
6146
|
props: [
|
|
5996
6147
|
{
|
|
5997
6148
|
name: "opts",
|
|
@@ -6012,15 +6163,17 @@ export default function PasswordBlock() {
|
|
|
6012
6163
|
useCases: ["Feature cards", "Image galleries", "Horizontal stepping lists"],
|
|
6013
6164
|
storyPath: "data-display/Carousel.stories.tsx",
|
|
6014
6165
|
rules: [3, 6],
|
|
6015
|
-
example: `import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from "@godxjp/ui/data-display";
|
|
6166
|
+
example: `import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselDots } from "@godxjp/ui/data-display";
|
|
6016
6167
|
|
|
6017
|
-
|
|
6168
|
+
// CarouselDots reads the Embla api from context \u2014 no setApi wiring needed.
|
|
6169
|
+
<Carousel opts={{ loop: true }}>
|
|
6018
6170
|
<CarouselContent>
|
|
6019
6171
|
<CarouselItem>1</CarouselItem>
|
|
6020
6172
|
<CarouselItem>2</CarouselItem>
|
|
6021
6173
|
</CarouselContent>
|
|
6022
6174
|
<CarouselPrevious />
|
|
6023
6175
|
<CarouselNext />
|
|
6176
|
+
<CarouselDots />
|
|
6024
6177
|
</Carousel>`
|
|
6025
6178
|
},
|
|
6026
6179
|
{
|
|
@@ -6508,6 +6661,11 @@ var CARDINAL_RULES = [
|
|
|
6508
6661
|
number: 40,
|
|
6509
6662
|
title: "Pages are mobile-first",
|
|
6510
6663
|
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."
|
|
6664
|
+
},
|
|
6665
|
+
{
|
|
6666
|
+
number: 41,
|
|
6667
|
+
title: "Drawer & dialog footer layout",
|
|
6668
|
+
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
6669
|
}
|
|
6512
6670
|
];
|
|
6513
6671
|
function findRule(num) {
|
|
@@ -6963,10 +7121,14 @@ function searchPatterns(query) {
|
|
|
6963
7121
|
}
|
|
6964
7122
|
|
|
6965
7123
|
// src/data/skills-index.ts
|
|
7124
|
+
function isConsumerSkill(s) {
|
|
7125
|
+
return s.audience !== "core";
|
|
7126
|
+
}
|
|
6966
7127
|
var SKILLS = [
|
|
6967
7128
|
// ── taste (foundational) ───────────────────────────────────────
|
|
6968
7129
|
{
|
|
6969
7130
|
id: "taste",
|
|
7131
|
+
audience: "both",
|
|
6970
7132
|
name: "Taste baseline \u2014 Senior UI/UX engineering",
|
|
6971
7133
|
whenToUse: "Default for any production app screen. Metric-based rules, strict component architecture, CSS hardware acceleration, balanced design engineering.",
|
|
6972
7134
|
source: "Leonxlnx/taste-skill (root) + @godxjp/ui design-thinking.ts",
|
|
@@ -7046,6 +7208,7 @@ broken). Spinner during init is wrong (nothing to spin over).`
|
|
|
7046
7208
|
// ── soft (Awwwards / premium agency) ───────────────────────────
|
|
7047
7209
|
{
|
|
7048
7210
|
id: "soft",
|
|
7211
|
+
audience: "consumer",
|
|
7049
7212
|
name: "Awwwards-tier \u2014 $150k agency build",
|
|
7050
7213
|
whenToUse: "Premium agency brief \u2014 marketing site, hero pages, product showcase. NOT every internal SaaS screen. Apply when the brief asks for 'Linear-tier', 'Apple-esque', 'Awwwards-style'.",
|
|
7051
7214
|
source: "Leonxlnx/taste-skill/soft-skill",
|
|
@@ -7165,6 +7328,7 @@ or Framer Motion's whileInView. NEVER window.addEventListener("scroll")
|
|
|
7165
7328
|
// ── minimalist (editorial workspace) ───────────────────────────
|
|
7166
7329
|
{
|
|
7167
7330
|
id: "minimalist",
|
|
7331
|
+
audience: "consumer",
|
|
7168
7332
|
name: "Minimalist \u2014 editorial workspace",
|
|
7169
7333
|
whenToUse: "Document-style apps (Notion-clone, knowledge base, blog admin). Warm monochrome + spot pastels. Bento grids. Editorial serif headings + sans body + monospace for data.",
|
|
7170
7334
|
source: "Leonxlnx/taste-skill/minimalist-skill",
|
|
@@ -7248,6 +7412,7 @@ position:fixed pointer-events-none layer.`
|
|
|
7248
7412
|
// ── brutalist ──────────────────────────────────────────────────
|
|
7249
7413
|
{
|
|
7250
7414
|
id: "brutalist",
|
|
7415
|
+
audience: "consumer",
|
|
7251
7416
|
name: "Brutalist \u2014 Swiss print + military terminal",
|
|
7252
7417
|
whenToUse: "Data-heavy dashboards, declassified-blueprint feel, portfolios needing raw mechanical aesthetic. Rigid grids, extreme type scale contrast, utilitarian color, analog degradation effects.",
|
|
7253
7418
|
source: "Leonxlnx/taste-skill/brutalist-skill",
|
|
@@ -7270,6 +7435,7 @@ portfolios.`
|
|
|
7270
7435
|
// ── gpt-tasteskill ─────────────────────────────────────────────
|
|
7271
7436
|
{
|
|
7272
7437
|
id: "gpt-tasteskill",
|
|
7438
|
+
audience: "consumer",
|
|
7273
7439
|
name: "GPT taste \u2014 editorial + advanced GSAP motion",
|
|
7274
7440
|
whenToUse: "Long-scroll marketing pages with cinematic scroll choreography. Pins, stacks, scrubbed timelines. AIDA structure. Wide editorial typography. Bans 6-line wraps. Gapless bento grids.",
|
|
7275
7441
|
source: "Leonxlnx/taste-skill/gpt-tasteskill",
|
|
@@ -7292,6 +7458,7 @@ over current), scrubbing (animation tied to scroll progress).`
|
|
|
7292
7458
|
// ── redesign ───────────────────────────────────────────────────
|
|
7293
7459
|
{
|
|
7294
7460
|
id: "redesign",
|
|
7461
|
+
audience: "both",
|
|
7295
7462
|
name: "Redesign \u2014 audit + upgrade existing UI",
|
|
7296
7463
|
whenToUse: "Working on an existing project (not greenfield). Find generic patterns, weak points, missing states. Apply fixes in priority order \u2014 font swap first, palette cleanup second, etc.",
|
|
7297
7464
|
source: "Leonxlnx/taste-skill/redesign-skill + redesign-audit.ts",
|
|
@@ -7339,6 +7506,7 @@ no skip-to-content.`
|
|
|
7339
7506
|
// ── output (full-output enforcement) ───────────────────────────
|
|
7340
7507
|
{
|
|
7341
7508
|
id: "output",
|
|
7509
|
+
audience: "both",
|
|
7342
7510
|
name: "Full-output enforcement",
|
|
7343
7511
|
whenToUse: "Always. Bans the // ... / // TODO / 'I'll leave this as an exercise' patterns. Treat every task as production-critical.",
|
|
7344
7512
|
source: "Leonxlnx/taste-skill/output-skill + output-quality.ts",
|
|
@@ -7378,6 +7546,7 @@ of writing it.`
|
|
|
7378
7546
|
// ── brandkit ───────────────────────────────────────────────────
|
|
7379
7547
|
{
|
|
7380
7548
|
id: "brandkit",
|
|
7549
|
+
audience: "consumer",
|
|
7381
7550
|
name: "Brandkit \u2014 identity guidelines boards",
|
|
7382
7551
|
whenToUse: "Designing a brand identity board first (before screens). Logo system, color palette, typography lockup, icon system, photography direction, brand voice.",
|
|
7383
7552
|
source: "Leonxlnx/taste-skill/brandkit",
|
|
@@ -7399,6 +7568,7 @@ imagery. Flexible grid layouts.`
|
|
|
7399
7568
|
// ── stitch ─────────────────────────────────────────────────────
|
|
7400
7569
|
{
|
|
7401
7570
|
id: "stitch",
|
|
7571
|
+
audience: "consumer",
|
|
7402
7572
|
name: "Stitch \u2014 semantic DESIGN.md for Google Stitch",
|
|
7403
7573
|
whenToUse: "Pairing with Google Stitch (or similar AI UI generator). Generate DESIGN.md files that enforce premium standards \u2014 strict typography, calibrated color, asymmetric layouts, perpetual micro-motion.",
|
|
7404
7574
|
source: "Leonxlnx/taste-skill/stitch-skill",
|
|
@@ -7420,6 +7590,7 @@ expressive.`
|
|
|
7420
7590
|
// ── imagegen-mobile ────────────────────────────────────────────
|
|
7421
7591
|
{
|
|
7422
7592
|
id: "imagegen-mobile",
|
|
7593
|
+
audience: "consumer",
|
|
7423
7594
|
name: "Imagegen mobile \u2014 app screen reference images",
|
|
7424
7595
|
whenToUse: "Pre-code phase. Generate mobile screen mockups before implementing. Onboarding flows, auth, home dashboards, profile, settings, chat, ecommerce, fintech, health, productivity.",
|
|
7425
7596
|
source: "Leonxlnx/taste-skill/imagegen-frontend-mobile",
|
|
@@ -7446,6 +7617,7 @@ screens in flows.`
|
|
|
7446
7617
|
// ── imagegen-web ───────────────────────────────────────────────
|
|
7447
7618
|
{
|
|
7448
7619
|
id: "imagegen-web",
|
|
7620
|
+
audience: "consumer",
|
|
7449
7621
|
name: "Imagegen web \u2014 landing page section images",
|
|
7450
7622
|
whenToUse: "Pre-code phase for landing / marketing sites. Generate ONE image per section (8 sections \u2192 8 images). Hero composition variety (NOT always left-text/right-image).",
|
|
7451
7623
|
source: "Leonxlnx/taste-skill/imagegen-frontend-web",
|
|
@@ -7482,6 +7654,7 @@ for the brand.`
|
|
|
7482
7654
|
// ── image-to-code ──────────────────────────────────────────────
|
|
7483
7655
|
{
|
|
7484
7656
|
id: "image-to-code",
|
|
7657
|
+
audience: "consumer",
|
|
7485
7658
|
name: "Image-to-code \u2014 generate design first, then implement",
|
|
7486
7659
|
whenToUse: "Visual-first brief in Codex. First generate the design image yourself, deeply analyze, THEN implement code matching it.",
|
|
7487
7660
|
source: "Leonxlnx/taste-skill/image-to-code-skill",
|
|
@@ -7506,6 +7679,7 @@ visible on a small laptop.`
|
|
|
7506
7679
|
// ── component discipline (hard contract) ───────────────────────
|
|
7507
7680
|
{
|
|
7508
7681
|
id: "component-discipline",
|
|
7682
|
+
audience: "core",
|
|
7509
7683
|
name: "Component discipline \u2014 international standards (hard contract)",
|
|
7510
7684
|
whenToUse: "MANDATORY before creating or changing ANY @godxjp/ui component, recipe, doc, or example. Enforces real primitives only, no duplication, i18n (Intl/CLDR/ISO/IANA/BCP-47), WAI-ARIA APG + WCAG 2.2 AA, RTL, and the controlled-vocabulary API.",
|
|
7511
7685
|
source: "@godxjp/ui .claude/skills/godxjp-ui-component + international-standardization audit",
|
|
@@ -7552,12 +7726,26 @@ with expectNoA11yViolations. Prefer Radix/cmdk/vaul for ARIA.`
|
|
|
7552
7726
|
"default"); positive booleans; tone for status; forward ref + ...props + className + id; export
|
|
7553
7727
|
XProp + XProp as XProps and register in props/registry. Then: add an MCP catalog entry + a
|
|
7554
7728
|
real-screen docs page; verify typecheck/lint/audit/check:*/preview:build/test all green.`
|
|
7729
|
+
},
|
|
7730
|
+
{
|
|
7731
|
+
id: "report-bug",
|
|
7732
|
+
title: "Found a library-level defect \u2192 file a gh issue (never paper over it)",
|
|
7733
|
+
tagline: "A missing token / wrong vocab / broken a11y in the system is a bug to report, not to work around.",
|
|
7734
|
+
body: `If satisfying this contract is blocked by @godxjp/ui itself \u2014 a token tier that
|
|
7735
|
+
doesn't exist, a primitive missing the controlled-vocabulary prop, a Radix wiring with a
|
|
7736
|
+
real a11y bug, a catalog example that's wrong \u2014 the contract says STOP and fix the SYSTEM,
|
|
7737
|
+
not the call site. Don't bake a one-off around it. If you can fix the library in this repo,
|
|
7738
|
+
do. If you can't (or you're a consumer agent without write access), open a detailed GitHub
|
|
7739
|
+
issue: use the draft_bug_report MCP tool to produce the issue body + a 'gh issue create
|
|
7740
|
+
--repo godx-jp/godxjp-ui \u2026' command, linking the component (get_component) and the cardinal
|
|
7741
|
+
rule (get_rule) involved, with a minimal repro, expected vs actual, version, and env.`
|
|
7555
7742
|
}
|
|
7556
7743
|
]
|
|
7557
7744
|
},
|
|
7558
7745
|
// ── design-to-page (consumer: handoff → real page) ─────────────
|
|
7559
7746
|
{
|
|
7560
7747
|
id: "design-to-page",
|
|
7748
|
+
audience: "consumer",
|
|
7561
7749
|
name: "Design handoff \u2192 real page (consumer build guide)",
|
|
7562
7750
|
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.",
|
|
7563
7751
|
source: "@godxjp/ui .design/research (chats-intent, tables, atomic-components) + dxs-kintai SKILL/colors_and_type.css",
|
|
@@ -7686,6 +7874,114 @@ format numbers/dates via Intl. Then run the build: pnpm typecheck + pnpm lint +
|
|
|
7686
7874
|
pnpm audit must be green, console clean, and eyeball the page at 390 / 768 / 1280
|
|
7687
7875
|
(atoms never wrap, containers wrap with row-gap, tabs horizontal-scroll, grids
|
|
7688
7876
|
minmax(0,1fr), heights never break).`
|
|
7877
|
+
},
|
|
7878
|
+
{
|
|
7879
|
+
id: "report-bug",
|
|
7880
|
+
title: "godx-ui bug / can't-follow-a-rule \u2192 file a gh issue (never fake it)",
|
|
7881
|
+
tagline: "If the LIBRARY is wrong, report it \u2014 don't hand-roll a workaround that hides the bug.",
|
|
7882
|
+
body: `When you CANNOT satisfy a rule because @godxjp/ui itself is at fault \u2014 a
|
|
7883
|
+
primitive doesn't expose the controlled-vocabulary prop you need, a token is
|
|
7884
|
+
missing, a component has a real a11y/behaviour bug, an example in the catalog is
|
|
7885
|
+
wrong \u2014 the rule is: DO NOT silently hand-roll/fake a replacement to dodge it (that
|
|
7886
|
+
just buries a library bug inside every app). Instead:
|
|
7887
|
+
\u2022 DON'T: copy a primitive's internals into your app, swap in a raw <input>/<div>, or
|
|
7888
|
+
redeclare a token to route around the defect.
|
|
7889
|
+
\u2022 DO: open a detailed GitHub issue against the library, then apply the SMALLEST
|
|
7890
|
+
possible local workaround marked // TODO(godxui#<n>: <summary>) so it's grep-able
|
|
7891
|
+
and removed once fixed.
|
|
7892
|
+
\u2022 Use the MCP tool draft_bug_report to generate the issue body + a copy-paste
|
|
7893
|
+
'gh issue create --repo godx-jp/godxjp-ui \u2026' command. Include: the component/rule
|
|
7894
|
+
(link via get_component/get_rule), a minimal repro, expected vs actual, the
|
|
7895
|
+
installed @godxjp/ui version, and your env. A vague "X is broken" issue is not
|
|
7896
|
+
enough \u2014 the report must let a maintainer reproduce in one paste.`
|
|
7897
|
+
}
|
|
7898
|
+
]
|
|
7899
|
+
},
|
|
7900
|
+
// ── compose-a-screen (consumer: primitives → a finished screen) ──
|
|
7901
|
+
{
|
|
7902
|
+
id: "compose-a-screen",
|
|
7903
|
+
audience: "consumer",
|
|
7904
|
+
name: "Compose a screen \u2014 primitives \u2192 a finished app view (consumer)",
|
|
7905
|
+
whenToUse: "You (a consumer agent) are building a NEW screen/page in an app that imports @godxjp/ui \u2014 from a written brief or product requirement, not a design handoff. Read this to assemble it from real primitives via this MCP: pick the right components, lay out one-intent-per-screen, wire every state + a11y + i18n, and verify. For a Claude Design handoff bundle/mock specifically, use design-to-page instead.",
|
|
7906
|
+
source: "@godxjp/ui MCP (consumer surface) \u2014 taste/one-intent + component-discipline + dxs-kintai DNA",
|
|
7907
|
+
sections: [
|
|
7908
|
+
{
|
|
7909
|
+
id: "pick-primitives",
|
|
7910
|
+
title: "Pick primitives via the MCP \u2014 never hand-roll, never guess a prop",
|
|
7911
|
+
tagline: "Decompose the screen into a shopping list; resolve each item with list_primitives \u2192 get_component.",
|
|
7912
|
+
body: `Start from the requirement, not the markup. Write a shopping list of every
|
|
7913
|
+
block the screen needs, then resolve each through THIS MCP before writing JSX:
|
|
7914
|
+
list_primitives (discover the group), get_component <Name> (confirm the exact
|
|
7915
|
+
prop/union/default \u2014 never guess), suggest_primitive / search_components when unsure
|
|
7916
|
+
which fits. Hard rules: compose ONLY real @godxjp/ui primitives \u2014 no styled <div>
|
|
7917
|
+
faking a Card, no raw <input>/<select>/<button>/<textarea>/<table>. No duplication:
|
|
7918
|
+
Select (showSearch/loadOptions) is the ONLY searchable/async select (there is no
|
|
7919
|
+
Combobox/Autocomplete/CountrySelect); the 4 i18n pickers are one AppSettingPicker
|
|
7920
|
+
kind=\u2026. A table = Card + CardContent-flush + DataTable. If a block has no clean
|
|
7921
|
+
primitive, see gaps handling in design-to-page/gaps-extend-or-ask + report-bug.`
|
|
7922
|
+
},
|
|
7923
|
+
{
|
|
7924
|
+
id: "assemble-screen",
|
|
7925
|
+
title: "Assemble it \u2014 one intent per screen, real chrome, fixed signaling",
|
|
7926
|
+
tagline: "One primary question per page; AppShell/PageContainer chrome; --primary once; semantic color is fixed.",
|
|
7927
|
+
body: `Distil the screen to ONE primary question it answers (one-intent-per-screen):
|
|
7928
|
+
1\u20132 hero facts + ONE primary list/form + contextual actions; push tertiary content to
|
|
7929
|
+
a Sheet/Dialog/next page. An 8-stat-card wall is a red flag. Use real page chrome
|
|
7930
|
+
(AppShell/Sidebar/Topbar/PageContainer) \u2014 content never touches the viewport edge,
|
|
7931
|
+
two bordered surfaces never touch (\u9593/breathing via Stack gap). Exactly ONE --primary
|
|
7932
|
+
action per view; status uses the FIXED semantic mapping (success/warning/info/
|
|
7933
|
+
attention/danger) \u2014 never recolor a wa-iro hue into a role, never use --primary for
|
|
7934
|
+
status. Pick density up front (compact 28 heavy-table / default 32 / comfortable 44
|
|
7935
|
+
login-mobile) and don't mix it mid-page. Hierarchy from type weight+size+color
|
|
7936
|
+
(20/18/14/13 \xD7 400/500/700), not colored background blocks. Mobile-first: default one
|
|
7937
|
+
column, add columns only at md:/lg: when each keeps \u226514px body at \u2265~280px width.`
|
|
7938
|
+
},
|
|
7939
|
+
{
|
|
7940
|
+
id: "state-and-a11y",
|
|
7941
|
+
title: "Wire every state + a11y + i18n (the part that gets skipped)",
|
|
7942
|
+
tagline: "default/hover/focus/active/disabled/loading/empty/error all handled; APG keyboard; t() everything.",
|
|
7943
|
+
body: `A screen isn't done at the happy path. Handle every state: Skeleton for INIT
|
|
7944
|
+
fetch (no data yet), Form loading / Spinner for active save (data present), EmptyState
|
|
7945
|
+
for no-data (one calm sentence, no illustration), inline error near the field via
|
|
7946
|
+
FormField (NOT a disappearing toast). Forms: explicit label + help + error always \u2014
|
|
7947
|
+
never placeholder-as-label. A11y (WAI-ARIA APG + WCAG 2.2 AA): correct roles/landmarks,
|
|
7948
|
+
keyboard (arrows/Home/End/Enter/Esc, visible focus, no positive tabindex, return focus
|
|
7949
|
+
on close), \u226524px targets, never colour-only state (add sr-only text), icon-only buttons
|
|
7950
|
+
need a name. i18n: zero hardcoded strings \u2014 every label + aria-label through t();
|
|
7951
|
+
numbers/currency/dates via Intl with the active locale (ISO 4217/8601, IANA tz),
|
|
7952
|
+
plurals via Intl.PluralRules. State-truthful affordances: a parent checkbox aggregates
|
|
7953
|
+
its children (checked/indeterminate/empty); a held value is visible when a control
|
|
7954
|
+
opens; controlled inputs mirror type\u2194click both ways (a controlled value with no
|
|
7955
|
+
synchronous onValueChange FREEZES the input).`
|
|
7956
|
+
},
|
|
7957
|
+
{
|
|
7958
|
+
id: "verify",
|
|
7959
|
+
title: "Verify \u2014 states shown, console clean, build green, 3 widths",
|
|
7960
|
+
tagline: "Drive every interactive control; 0 console errors/warnings; typecheck/lint green; eyeball 390/768/1280.",
|
|
7961
|
+
body: `Before calling the screen done: drive EVERY interactive control to its
|
|
7962
|
+
terminal state in a real browser (don't infer behaviour from source) and read the
|
|
7963
|
+
DevTools console \u2014 a <button>-in-<button>/hydration/act()/404 warning is a FINDING,
|
|
7964
|
+
not noise. Confirm: every prop \xD7 union \xD7 state is exercised; held values visible on
|
|
7965
|
+
open; multi-step selections (date range, capped multi-select) can be restarted from a
|
|
7966
|
+
complete state, not trapped; controlled mirrors update both directions. Run the app's
|
|
7967
|
+
build: typecheck + lint clean, console clean, and eyeball at 390 / 768 / 1280 (atoms
|
|
7968
|
+
never wrap, containers wrap with row-gap, natural-width components stay w-fit, no
|
|
7969
|
+
decorative edge fades, no dead grey panes). If a failure traces to @godxjp/ui itself,
|
|
7970
|
+
do not fake around it \u2014 see report-bug.`
|
|
7971
|
+
},
|
|
7972
|
+
{
|
|
7973
|
+
id: "report-bug",
|
|
7974
|
+
title: "godx-ui bug / can't-follow-a-rule \u2192 file a gh issue (never fake it)",
|
|
7975
|
+
tagline: "If the LIBRARY is wrong, report it \u2014 don't hand-roll a workaround that hides the bug.",
|
|
7976
|
+
body: `Same contract as design-to-page/report-bug: when a rule is impossible because
|
|
7977
|
+
@godxjp/ui is at fault (missing token, a primitive without the controlled-vocabulary
|
|
7978
|
+
prop, a real a11y/behaviour bug, a wrong catalog example) \u2014 DO NOT silently fake a
|
|
7979
|
+
replacement. DON'T copy primitive internals, drop to raw HTML, or redeclare a token to
|
|
7980
|
+
dodge it. DO open a detailed GitHub issue (use the draft_bug_report MCP tool to build
|
|
7981
|
+
the body + the 'gh issue create --repo godx-jp/godxjp-ui \u2026' command), then apply the
|
|
7982
|
+
smallest local workaround tagged // TODO(godxui#<n>: <summary>). The issue must carry a
|
|
7983
|
+
minimal repro, expected vs actual, the installed version, and env \u2014 enough to
|
|
7984
|
+
reproduce in one paste.`
|
|
7689
7985
|
}
|
|
7690
7986
|
]
|
|
7691
7987
|
}
|
|
@@ -7696,7 +7992,7 @@ function findSkill(id) {
|
|
|
7696
7992
|
function findSection(skillId, sectionId) {
|
|
7697
7993
|
return findSkill(skillId)?.sections.find((s) => s.id === sectionId);
|
|
7698
7994
|
}
|
|
7699
|
-
function routeTask(task) {
|
|
7995
|
+
function routeTask(task, opts) {
|
|
7700
7996
|
const q = task.toLowerCase();
|
|
7701
7997
|
const matches = [];
|
|
7702
7998
|
const route = (kw, skill, section, why, alsoSee) => {
|
|
@@ -7787,13 +8083,73 @@ function routeTask(task) {
|
|
|
7787
8083
|
"Generate design image first \u2192 analyze \u2192 implement."
|
|
7788
8084
|
);
|
|
7789
8085
|
route(
|
|
7790
|
-
[
|
|
8086
|
+
[
|
|
8087
|
+
"handoff",
|
|
8088
|
+
"design bundle",
|
|
8089
|
+
"claude design",
|
|
8090
|
+
"prototype",
|
|
8091
|
+
"build the page",
|
|
8092
|
+
"implement the design",
|
|
8093
|
+
"build this screen",
|
|
8094
|
+
"mockup"
|
|
8095
|
+
],
|
|
7791
8096
|
"design-to-page",
|
|
7792
8097
|
"map-to-primitives",
|
|
7793
8098
|
"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.",
|
|
7794
8099
|
["design-to-page/read-intent", "design-to-page/dna", "design-to-page/tables-central"]
|
|
7795
8100
|
);
|
|
7796
|
-
|
|
8101
|
+
route(
|
|
8102
|
+
[
|
|
8103
|
+
"compose a screen",
|
|
8104
|
+
"new screen",
|
|
8105
|
+
"new page",
|
|
8106
|
+
"create a page",
|
|
8107
|
+
"create a screen",
|
|
8108
|
+
"build a view",
|
|
8109
|
+
"build a screen",
|
|
8110
|
+
"from scratch",
|
|
8111
|
+
"screen from a brief"
|
|
8112
|
+
],
|
|
8113
|
+
"compose-a-screen",
|
|
8114
|
+
"pick-primitives",
|
|
8115
|
+
"Build a new app screen from real @godxjp/ui primitives (MCP-first): one-intent-per-screen, real chrome, every state + a11y + i18n, verify.",
|
|
8116
|
+
[
|
|
8117
|
+
"compose-a-screen/assemble-screen",
|
|
8118
|
+
"compose-a-screen/state-and-a11y",
|
|
8119
|
+
"taste/one-intent-per-screen"
|
|
8120
|
+
]
|
|
8121
|
+
);
|
|
8122
|
+
route(
|
|
8123
|
+
[
|
|
8124
|
+
"bug in godx",
|
|
8125
|
+
"godx-ui bug",
|
|
8126
|
+
"report a bug",
|
|
8127
|
+
"file an issue",
|
|
8128
|
+
"gh issue",
|
|
8129
|
+
"can't follow the rule",
|
|
8130
|
+
"library is broken",
|
|
8131
|
+
"primitive is broken"
|
|
8132
|
+
],
|
|
8133
|
+
"compose-a-screen",
|
|
8134
|
+
"report-bug",
|
|
8135
|
+
"If @godxjp/ui itself is at fault, don't fake a workaround \u2014 file a detailed gh issue (use draft_bug_report).",
|
|
8136
|
+
["design-to-page/report-bug"]
|
|
8137
|
+
);
|
|
8138
|
+
const filtered = opts?.consumerOnly ? matches.filter((m) => {
|
|
8139
|
+
const sk = findSkill(m.skill);
|
|
8140
|
+
return !sk || sk.audience !== "core";
|
|
8141
|
+
}) : matches;
|
|
8142
|
+
if (filtered.length === 0) {
|
|
8143
|
+
if (opts?.consumerOnly) {
|
|
8144
|
+
return [
|
|
8145
|
+
{
|
|
8146
|
+
skill: "compose-a-screen",
|
|
8147
|
+
section: "pick-primitives",
|
|
8148
|
+
why: `No keyword match for "${task}". Default consumer path: compose the screen from real primitives via the MCP.`,
|
|
8149
|
+
alsoSee: ["design-to-page/map-to-primitives", "taste/one-intent-per-screen"]
|
|
8150
|
+
}
|
|
8151
|
+
];
|
|
8152
|
+
}
|
|
7797
8153
|
return [
|
|
7798
8154
|
{
|
|
7799
8155
|
skill: "taste",
|
|
@@ -7802,7 +8158,7 @@ function routeTask(task) {
|
|
|
7802
8158
|
}
|
|
7803
8159
|
];
|
|
7804
8160
|
}
|
|
7805
|
-
return
|
|
8161
|
+
return filtered;
|
|
7806
8162
|
}
|
|
7807
8163
|
|
|
7808
8164
|
// src/data/anti-ai-tells.ts
|
|
@@ -8531,27 +8887,71 @@ var TOOL_DEFINITIONS = [
|
|
|
8531
8887
|
},
|
|
8532
8888
|
{
|
|
8533
8889
|
name: "get_tokens",
|
|
8534
|
-
description: "Read design tokens, optionally filtered by category.",
|
|
8890
|
+
description: "Read design tokens, optionally filtered by tier category (primitive / semantic / component).",
|
|
8535
8891
|
inputSchema: {
|
|
8536
8892
|
type: "object",
|
|
8537
8893
|
properties: {
|
|
8538
8894
|
category: {
|
|
8539
8895
|
type: "string",
|
|
8540
|
-
enum: [
|
|
8541
|
-
"color",
|
|
8542
|
-
"spacing",
|
|
8543
|
-
"typography",
|
|
8544
|
-
"radius",
|
|
8545
|
-
"shadow",
|
|
8546
|
-
"motion",
|
|
8547
|
-
"breakpoint",
|
|
8548
|
-
"density",
|
|
8549
|
-
"z-index"
|
|
8550
|
-
]
|
|
8896
|
+
enum: ["primitive", "semantic", "component"]
|
|
8551
8897
|
}
|
|
8552
8898
|
}
|
|
8553
8899
|
}
|
|
8554
8900
|
},
|
|
8901
|
+
// ── CONSUMER NAMESPACE (app-dev surface — core-only skills hidden) ─
|
|
8902
|
+
{
|
|
8903
|
+
name: "list_consumer_skills",
|
|
8904
|
+
description: "List the design skills relevant to an app-dev BUILDING WITH @godxjp/ui (audience consumer/both). Hides core library-maintenance skills. START HERE if you import @godxjp/ui and want guidance (design-to-page, compose-a-screen, taste, \u2026). Returns id + name + whenToUse + section ids.",
|
|
8905
|
+
inputSchema: { type: "object", properties: {} }
|
|
8906
|
+
},
|
|
8907
|
+
{
|
|
8908
|
+
name: "get_consumer_skill",
|
|
8909
|
+
description: "Fetch ONE section of ONE consumer-facing skill. Same as get_skill_section but refuses core-only skills (steers app-devs away from library-maintenance material). Use after list_consumer_skills / route_consumer_task.",
|
|
8910
|
+
inputSchema: {
|
|
8911
|
+
type: "object",
|
|
8912
|
+
properties: {
|
|
8913
|
+
skill: {
|
|
8914
|
+
type: "string",
|
|
8915
|
+
description: "Consumer skill id (e.g. 'design-to-page', 'compose-a-screen')."
|
|
8916
|
+
},
|
|
8917
|
+
section: { type: "string", description: "Section id within that skill." }
|
|
8918
|
+
},
|
|
8919
|
+
required: ["skill"]
|
|
8920
|
+
}
|
|
8921
|
+
},
|
|
8922
|
+
{
|
|
8923
|
+
name: "route_consumer_task",
|
|
8924
|
+
description: "Natural-language task \u2192 consumer skill+section pointer. Like route_task but only points to consumer-facing skills (never core library-maintenance). Use FIRST when you're building an app with @godxjp/ui.",
|
|
8925
|
+
inputSchema: {
|
|
8926
|
+
type: "object",
|
|
8927
|
+
properties: { task: { type: "string", description: "Describe what you want to build." } },
|
|
8928
|
+
required: ["task"]
|
|
8929
|
+
}
|
|
8930
|
+
},
|
|
8931
|
+
{
|
|
8932
|
+
name: "draft_bug_report",
|
|
8933
|
+
description: "When @godxjp/ui ITSELF is at fault (missing token, a primitive lacking the controlled-vocabulary prop, a real a11y/behaviour bug, a wrong catalog example) and you cannot follow a rule \u2014 DON'T fake a workaround. This drafts a detailed GitHub issue body + a copy-paste `gh issue create` command so you can report it. Prints the command only; never runs gh.",
|
|
8934
|
+
inputSchema: {
|
|
8935
|
+
type: "object",
|
|
8936
|
+
properties: {
|
|
8937
|
+
summary: { type: "string", description: "One-line title of the bug / blocked rule." },
|
|
8938
|
+
repro: { type: "string", description: "Minimal steps or code to reproduce." },
|
|
8939
|
+
expected: { type: "string", description: "What SHOULD happen (per the rule/spec)." },
|
|
8940
|
+
actual: { type: "string", description: "What actually happens." },
|
|
8941
|
+
component: {
|
|
8942
|
+
type: "string",
|
|
8943
|
+
description: "Affected component name, if any (links to get_component)."
|
|
8944
|
+
},
|
|
8945
|
+
rule: {
|
|
8946
|
+
type: "number",
|
|
8947
|
+
description: "Cardinal rule number that can't be followed, if any."
|
|
8948
|
+
},
|
|
8949
|
+
version: { type: "string", description: "Installed @godxjp/ui version (e.g. '12.1.0')." },
|
|
8950
|
+
env: { type: "string", description: "Environment (browser/OS/framework), if relevant." }
|
|
8951
|
+
},
|
|
8952
|
+
required: ["summary"]
|
|
8953
|
+
}
|
|
8954
|
+
},
|
|
8555
8955
|
// ── TASK ROUTING (smallest response — pointer) ─────────────────
|
|
8556
8956
|
{
|
|
8557
8957
|
name: "route_task",
|
|
@@ -8618,9 +9018,18 @@ async function dispatchTool(name, args) {
|
|
|
8618
9018
|
case "get_rule":
|
|
8619
9019
|
return getRule(typeof args.number === "number" ? args.number : void 0);
|
|
8620
9020
|
case "get_vocab":
|
|
8621
|
-
return getVocab(args.name);
|
|
9021
|
+
return getVocab(args.name == null ? void 0 : String(args.name));
|
|
8622
9022
|
case "get_tokens":
|
|
8623
9023
|
return getTokens(args.category);
|
|
9024
|
+
// Consumer namespace
|
|
9025
|
+
case "list_consumer_skills":
|
|
9026
|
+
return listConsumerSkills();
|
|
9027
|
+
case "get_consumer_skill":
|
|
9028
|
+
return getConsumerSkill(String(args.skill ?? ""), String(args.section ?? ""));
|
|
9029
|
+
case "route_consumer_task":
|
|
9030
|
+
return routeTaskTool(String(args.task ?? ""), { consumerOnly: true });
|
|
9031
|
+
case "draft_bug_report":
|
|
9032
|
+
return draftBugReport(args);
|
|
8624
9033
|
// Task routing
|
|
8625
9034
|
case "route_task":
|
|
8626
9035
|
return routeTaskTool(String(args.task ?? ""));
|
|
@@ -8638,12 +9047,15 @@ async function dispatchTool(name, args) {
|
|
|
8638
9047
|
function listSkills() {
|
|
8639
9048
|
let out = `# Available skills (${SKILLS.length})
|
|
8640
9049
|
|
|
9050
|
+
`;
|
|
9051
|
+
out += `Each is tagged \`[audience]\` \u2014 \`core\` = building @godxjp/ui itself, \`consumer\` = building an app with it, \`both\`. App-devs: use \`list_consumer_skills\` to hide core material.
|
|
9052
|
+
|
|
8641
9053
|
`;
|
|
8642
9054
|
out += `Use \`get_skill_section skill="..." section="..."\` to drill in.
|
|
8643
9055
|
|
|
8644
9056
|
`;
|
|
8645
9057
|
for (const s of SKILLS) {
|
|
8646
|
-
out += `## ${s.id} \u2014 ${s.name}
|
|
9058
|
+
out += `## ${s.id} \u2014 ${s.name} \`[${s.audience}]\`
|
|
8647
9059
|
`;
|
|
8648
9060
|
out += `**When to use:** ${s.whenToUse}
|
|
8649
9061
|
|
|
@@ -8656,6 +9068,124 @@ function listSkills() {
|
|
|
8656
9068
|
_Source: ${SKILLS.map((s) => s.source).filter((v, i, a) => a.indexOf(v) === i).slice(0, 3).join("; ")}, \u2026_`;
|
|
8657
9069
|
return out;
|
|
8658
9070
|
}
|
|
9071
|
+
function listConsumerSkills() {
|
|
9072
|
+
const list = SKILLS.filter(isConsumerSkill);
|
|
9073
|
+
let out = `# Consumer skills (${list.length}) \u2014 building an app WITH @godxjp/ui
|
|
9074
|
+
|
|
9075
|
+
`;
|
|
9076
|
+
out += `Core library-maintenance skills are hidden. Drill in with \`get_consumer_skill skill="..." section="..."\`, or route a task with \`route_consumer_task\`.
|
|
9077
|
+
|
|
9078
|
+
`;
|
|
9079
|
+
for (const s of list) {
|
|
9080
|
+
out += `## ${s.id} \u2014 ${s.name} \`[${s.audience}]\`
|
|
9081
|
+
`;
|
|
9082
|
+
out += `**When to use:** ${s.whenToUse}
|
|
9083
|
+
|
|
9084
|
+
`;
|
|
9085
|
+
out += `**Sections:** ${s.sections.map((sec) => `\`${sec.id}\``).join(", ")}
|
|
9086
|
+
|
|
9087
|
+
`;
|
|
9088
|
+
}
|
|
9089
|
+
return out;
|
|
9090
|
+
}
|
|
9091
|
+
function getConsumerSkill(skillId, sectionId) {
|
|
9092
|
+
const skill = findSkill(skillId);
|
|
9093
|
+
if (skill && !isConsumerSkill(skill)) {
|
|
9094
|
+
return `Skill "${skillId}" is CORE-only (building @godxjp/ui itself) and isn't served to app-devs. Use \`list_consumer_skills\` for consumer-facing guidance${skillId === "component-discipline" ? ` \u2014 the standards you need when composing/extending are folded into \`compose-a-screen/state-and-a11y\` and \`design-to-page/verify\`.` : `.`}`;
|
|
9095
|
+
}
|
|
9096
|
+
return getSkillSection(skillId, sectionId);
|
|
9097
|
+
}
|
|
9098
|
+
function draftBugReport(args) {
|
|
9099
|
+
const get = (k) => {
|
|
9100
|
+
const v = args[k];
|
|
9101
|
+
return typeof v === "string" ? v.trim() : "";
|
|
9102
|
+
};
|
|
9103
|
+
const summary = get("summary");
|
|
9104
|
+
if (!summary) {
|
|
9105
|
+
return "Pass at least `summary` (one-line title). For a useful report also pass `repro`, `expected`, `actual`, and ideally `component` / `rule` / `version` / `env`. A vague report a maintainer can't reproduce is not enough.";
|
|
9106
|
+
}
|
|
9107
|
+
const repro = get("repro");
|
|
9108
|
+
const expected = get("expected");
|
|
9109
|
+
const actual = get("actual");
|
|
9110
|
+
const component = get("component");
|
|
9111
|
+
const rule = typeof args.rule === "number" ? args.rule : void 0;
|
|
9112
|
+
const version = get("version");
|
|
9113
|
+
const env = get("env");
|
|
9114
|
+
const missing = [];
|
|
9115
|
+
if (!repro) missing.push("repro");
|
|
9116
|
+
if (!expected) missing.push("expected");
|
|
9117
|
+
if (!actual) missing.push("actual");
|
|
9118
|
+
const ph = (label, val) => val ? val : `_(TODO: ${label} \u2014 required for a reproducible report)_`;
|
|
9119
|
+
const title = `[bug] ${summary}`;
|
|
9120
|
+
let body = `## Summary
|
|
9121
|
+
|
|
9122
|
+
${summary}
|
|
9123
|
+
|
|
9124
|
+
`;
|
|
9125
|
+
body += `## Affected
|
|
9126
|
+
|
|
9127
|
+
`;
|
|
9128
|
+
body += component ? `- Component: \`${component}\` (see \`get_component name="${component}"\`)
|
|
9129
|
+
` : `- Component: _(n/a)_
|
|
9130
|
+
`;
|
|
9131
|
+
body += rule !== void 0 ? `- Cardinal rule: #${rule} (see \`get_rule number=${rule}\`)
|
|
9132
|
+
` : "";
|
|
9133
|
+
body += `
|
|
9134
|
+
## Reproduction (minimal)
|
|
9135
|
+
|
|
9136
|
+
${ph("repro", repro)}
|
|
9137
|
+
|
|
9138
|
+
`;
|
|
9139
|
+
body += `## Expected
|
|
9140
|
+
|
|
9141
|
+
${ph("expected", expected)}
|
|
9142
|
+
|
|
9143
|
+
`;
|
|
9144
|
+
body += `## Actual
|
|
9145
|
+
|
|
9146
|
+
${ph("actual", actual)}
|
|
9147
|
+
|
|
9148
|
+
`;
|
|
9149
|
+
body += `## Environment
|
|
9150
|
+
|
|
9151
|
+
`;
|
|
9152
|
+
body += `- @godxjp/ui version: ${version || "_(TODO: e.g. 12.1.0)_"}
|
|
9153
|
+
`;
|
|
9154
|
+
body += `- Env: ${env || "_(TODO: browser / OS / framework)_"}
|
|
9155
|
+
|
|
9156
|
+
`;
|
|
9157
|
+
body += `## Proposed fix
|
|
9158
|
+
|
|
9159
|
+
_(optional \u2014 what the library should do instead)_
|
|
9160
|
+
`;
|
|
9161
|
+
const q = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
9162
|
+
const cmd = `gh issue create --repo godx-jp/godxjp-ui --label bug --title ${q(title)} --body ${q(body)}`;
|
|
9163
|
+
let out = `# Draft bug report
|
|
9164
|
+
|
|
9165
|
+
`;
|
|
9166
|
+
if (missing.length) {
|
|
9167
|
+
out += `> \u26A0\uFE0F Incomplete \u2014 fill ${missing.map((m) => `\`${m}\``).join(", ")} before filing (a report a maintainer can't reproduce will bounce).
|
|
9168
|
+
|
|
9169
|
+
`;
|
|
9170
|
+
}
|
|
9171
|
+
out += `**Title:** ${title}
|
|
9172
|
+
|
|
9173
|
+
`;
|
|
9174
|
+
out += `## Issue body (Markdown)
|
|
9175
|
+
|
|
9176
|
+
${body}
|
|
9177
|
+
`;
|
|
9178
|
+
out += `## File it (copy-paste \u2014 this tool does NOT run gh)
|
|
9179
|
+
|
|
9180
|
+
\`\`\`sh
|
|
9181
|
+
${cmd}
|
|
9182
|
+
\`\`\`
|
|
9183
|
+
|
|
9184
|
+
`;
|
|
9185
|
+
out += `_Reminder: don't hand-roll a fake workaround to hide the bug \u2014 file this, then mark any minimal local workaround with \`// TODO(godxui#<n>)\`._
|
|
9186
|
+
`;
|
|
9187
|
+
return out;
|
|
9188
|
+
}
|
|
8659
9189
|
function listPrimitives(group) {
|
|
8660
9190
|
const list = group ? componentsByGroup(group) : COMPONENTS;
|
|
8661
9191
|
if (list.length === 0) return `No components${group ? ` in group "${group}"` : ""}.`;
|
|
@@ -8995,11 +9525,11 @@ function getTokens(cat) {
|
|
|
8995
9525
|
}
|
|
8996
9526
|
return out;
|
|
8997
9527
|
}
|
|
8998
|
-
function routeTaskTool(task) {
|
|
9528
|
+
function routeTaskTool(task, opts) {
|
|
8999
9529
|
if (!task.trim())
|
|
9000
9530
|
return "Describe the task (e.g. 'design a premium agency hero', 'audit existing settings page').";
|
|
9001
|
-
const results = routeTask(task);
|
|
9002
|
-
let out = `# Routing "${task}"
|
|
9531
|
+
const results = routeTask(task, opts);
|
|
9532
|
+
let out = `# Routing "${task}"${opts?.consumerOnly ? " (consumer)" : ""}
|
|
9003
9533
|
|
|
9004
9534
|
`;
|
|
9005
9535
|
for (const r of results) {
|
|
@@ -9098,10 +9628,19 @@ function lintJsx(jsx) {
|
|
|
9098
9628
|
check(/<input[\s>]/, "Use `<Input>` instead of raw `<input>` (rule 29).");
|
|
9099
9629
|
check(/<select[\s>]/, "Use `<Select>` instead of raw `<select>` (rule 29).");
|
|
9100
9630
|
check(/<textarea[\s>]/, "Use `<Textarea>` instead of raw `<textarea>` (rule 29).");
|
|
9631
|
+
check(/<(table|thead|tbody)[\s>]/, "Use `<DataTable>` instead of a hand-rolled `<table>` (rule 29).");
|
|
9101
9632
|
check(
|
|
9102
9633
|
/bg-(red|blue|green|yellow|gray|slate|zinc|neutral|stone|orange|amber|lime|emerald|teal|cyan|sky|indigo|violet|purple|fuchsia|pink|rose)-\d{2,3}\b/,
|
|
9103
9634
|
"Use semantic token utilities (`bg-primary`/`bg-destructive`) not raw color scales (rule 2)."
|
|
9104
9635
|
);
|
|
9636
|
+
check(
|
|
9637
|
+
/\b(?:ml|mr|pl|pr|left|right)-(?:\d|\[|auto|px|full|screen)|\b(?:rounded-[lr]|border-[lr]|text-(?:left|right))\b/,
|
|
9638
|
+
"Physical direction class \u2014 use logical CSS (`ms-/me-`, `ps-/pe-`, `start-/end-`, `rounded-s/e`, `text-start/end`) so the UI flips correctly under RTL (rule: logical CSS)."
|
|
9639
|
+
);
|
|
9640
|
+
check(
|
|
9641
|
+
/size=["']default["']/,
|
|
9642
|
+
'`size="default"` is not in the controlled vocabulary \u2014 use `size` \u2208 xs|sm|md|lg.'
|
|
9643
|
+
);
|
|
9105
9644
|
check(
|
|
9106
9645
|
/<Tag[\s\S]*?color=["']error["']/i,
|
|
9107
9646
|
'Tag `color="error"` \u2192 `"destructive"` (v5.0, PR #60).'
|
|
@@ -9170,6 +9709,7 @@ Note: heuristic only \u2014 not a substitute for the full CI gate.
|
|
|
9170
9709
|
}
|
|
9171
9710
|
|
|
9172
9711
|
// src/resources/registry.ts
|
|
9712
|
+
var RULE_COUNT = CARDINAL_RULES.length;
|
|
9173
9713
|
var RESOURCE_DEFINITIONS = [
|
|
9174
9714
|
{
|
|
9175
9715
|
uri: "godx-ui://components",
|
|
@@ -9191,8 +9731,8 @@ var RESOURCE_DEFINITIONS = [
|
|
|
9191
9731
|
},
|
|
9192
9732
|
{
|
|
9193
9733
|
uri: "godx-ui://rules",
|
|
9194
|
-
name:
|
|
9195
|
-
description:
|
|
9734
|
+
name: `Cardinal rules (${RULE_COUNT})`,
|
|
9735
|
+
description: `The ${RULE_COUNT} binding rules from CLAUDE.md as Markdown.`,
|
|
9196
9736
|
mimeType: "text/markdown"
|
|
9197
9737
|
},
|
|
9198
9738
|
{
|
|
@@ -9299,7 +9839,7 @@ ${c.example}
|
|
|
9299
9839
|
// package.json
|
|
9300
9840
|
var package_default = {
|
|
9301
9841
|
name: "@godxjp/ui-mcp",
|
|
9302
|
-
version: "0.
|
|
9842
|
+
version: "0.19.0",
|
|
9303
9843
|
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).",
|
|
9304
9844
|
type: "module",
|
|
9305
9845
|
main: "./dist/index.js",
|