@godxjp/ui-mcp 0.19.0 → 0.20.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 CHANGED
@@ -7,7 +7,7 @@ MCP-aware agent live access to:
7
7
  - 80+ component catalog (props, types, defaults, examples)
8
8
  - 14 shared prop-vocabulary types (`SizeProp`, `ColorProp`, `LoadingProp`, …)
9
9
  - 48 design tokens across the primitive / semantic / component tiers
10
- - 41 cardinal rules from `CLAUDE.md`
10
+ - 42 cardinal rules from `CLAUDE.md`
11
11
  - 9 canonical copy-paste-ready patterns (sign-up, settings, data-table, …)
12
12
  - 15 design skills, each tagged by **audience** — 12 taste-family (taste / soft / minimalist /
13
13
  brutalist / gpt-tasteskill / redesign / output / brandkit / stitch / imagegen-mobile /
@@ -270,7 +270,7 @@ consumer/core guides are framework-native.
270
270
  | `godx-ui://prop-vocabulary` | JSON | Shared vocab |
271
271
  | `godx-ui://tokens` | JSON | All tokens |
272
272
  | `godx-ui://tokens/{category}` | JSON | Tokens by category |
273
- | `godx-ui://rules` | Markdown | All 41 rules |
273
+ | `godx-ui://rules` | Markdown | All 42 rules |
274
274
  | `godx-ui://rules/{number}` | Markdown | One rule |
275
275
  | `godx-ui://patterns` | JSON | Pattern index |
276
276
  | `godx-ui://patterns/{name}` | Markdown | One pattern |
package/dist/index.js CHANGED
@@ -712,9 +712,9 @@ function MyShell({ children }: { content: React.ReactNode }) {
712
712
  props: [
713
713
  {
714
714
  name: "variant",
715
- type: '"default" | "destructive" | "outline" | "secondary" | "ghost" | "link"',
715
+ type: '"default" | "destructive" | "outline" | "dashed" | "secondary" | "ghost" | "link"',
716
716
  defaultValue: '"default"',
717
- description: "Visual style."
717
+ description: "Visual style. `dashed` = outline with a dashed border (Ant-style add-row / placeholder action)."
718
718
  },
719
719
  {
720
720
  name: "size",
@@ -722,6 +722,12 @@ function MyShell({ children }: { content: React.ReactNode }) {
722
722
  defaultValue: '"default"',
723
723
  description: "Size preset (height, padding, icon dims)."
724
724
  },
725
+ {
726
+ name: "shape",
727
+ type: '"default" | "pill" | "sharp"',
728
+ defaultValue: '"default"',
729
+ description: "Corner radius from the tokens \u2014 `default` (control radius), `pill` (fully rounded, --radius-pill), `sharp` (square, --radius-sharp). Use the prop instead of a `rounded-*` className."
730
+ },
725
731
  {
726
732
  name: "asChild",
727
733
  type: "boolean",
@@ -768,6 +774,98 @@ import { Trash2 } from "lucide-react";
768
774
  storyPath: "general/Button.stories.tsx",
769
775
  rules: [23]
770
776
  },
777
+ {
778
+ name: "Text",
779
+ group: "general",
780
+ tagline: 'Typographic primitive \u2014 use INSTEAD of a hand-rolled `<span className="text-[13px] font-medium text-muted-foreground">`. Size is a type-scale step (never px); tone/weight are tokens.',
781
+ props: [
782
+ {
783
+ name: "size",
784
+ type: '"2xs" | "xs" | "sm" | "md" | "lg" | "xl"',
785
+ defaultValue: '"sm"',
786
+ description: "Golden-ratio type-scale step. NEVER an arbitrary px (`text-[13px]` is banned) \u2014 pick the nearest step."
787
+ },
788
+ {
789
+ name: "tone",
790
+ type: '"default" | "muted" | "primary" | "success" | "warning" | "destructive" | "info"',
791
+ defaultValue: '"default"',
792
+ description: "Semantic foreground colour. Replaces `text-muted-foreground` etc. on a raw span."
793
+ },
794
+ {
795
+ name: "weight",
796
+ type: '"regular" | "medium" | "semibold"',
797
+ defaultValue: '"regular"',
798
+ description: "Font weight (system 2-weight 400/500; semibold resolves to the 500 token)."
799
+ },
800
+ { name: "align", type: '"start" | "center" | "end"', description: "Logical text alignment." },
801
+ { name: "truncate", type: "boolean", description: "Single-line ellipsis." },
802
+ { name: "tabular", type: "boolean", description: "Tabular figures for aligned numbers." },
803
+ { name: "mono", type: "boolean", description: "Monospace family for codes / ids." },
804
+ {
805
+ name: "as",
806
+ type: '"span" | "p" | "div" | "label" | "strong" | "em" | "small"',
807
+ defaultValue: '"span"',
808
+ description: "Rendered element."
809
+ }
810
+ ],
811
+ usage: [
812
+ "DO use `<Text>` for ALL body / inline / caption text instead of a styled `<span>`/`<p>`. Pick `size` from the scale; never write `text-[13px]`/`text-[11px]` or `font-semibold` by hand.",
813
+ 'DO use `tone` for colour (`muted`/`primary`/semantic), `tabular` for numbers, `mono` for codes \u2014 not `className="text-muted-foreground font-mono tabular-nums"`.',
814
+ "For a heading, use `<Heading level>` instead of a large-size `<Text>`."
815
+ ],
816
+ useCases: [
817
+ 'A muted caption under a value: `<Text size="xs" tone="muted">2026\u5E745\u6708\u5EA6</Text>`.',
818
+ 'A monospace id in a list row: `<Text size="xs" mono tone="muted">RC-204881</Text>`.',
819
+ 'An emphasized inline figure: `<Text weight="medium" tabular>\xA51,240,000</Text>`.'
820
+ ],
821
+ storyPath: "general/typography.tsx",
822
+ rules: [2, 23],
823
+ example: `import { Text } from "@godxjp/ui/general";
824
+
825
+ <Text size="xs" tone="muted">\u88DC\u52A9\u30C6\u30AD\u30B9\u30C8</Text>
826
+ <Text weight="medium" tabular>\xA51,240,000</Text>
827
+ <Text size="xs" mono tone="muted">RC-204881</Text>`
828
+ },
829
+ {
830
+ name: "Heading",
831
+ group: "general",
832
+ tagline: "Section heading sized from the --heading-h* tokens. `level` sets the size AND the semantic <h1..h4>.",
833
+ props: [
834
+ {
835
+ name: "level",
836
+ type: "1 | 2 | 3 | 4",
837
+ defaultValue: "2",
838
+ description: "Heading level \u2014 sizes from --heading-h{1..4} and renders the matching <h*>."
839
+ },
840
+ {
841
+ name: "as",
842
+ type: '"h1" | "h2" | "h3" | "h4" | "div"',
843
+ description: "Override the rendered element (e.g. a visual h2 that is a real <h1>)."
844
+ },
845
+ {
846
+ name: "tone",
847
+ type: '"default" | "muted" | "primary" | "success" | "warning" | "destructive" | "info"',
848
+ defaultValue: '"default"',
849
+ description: "Semantic foreground colour."
850
+ },
851
+ { name: "align", type: '"start" | "center" | "end"', description: "Logical text alignment." },
852
+ { name: "truncate", type: "boolean", description: "Single-line ellipsis." }
853
+ ],
854
+ usage: [
855
+ 'DO use `<Heading level>` for section titles instead of a raw `<h2 className="text-lg font-semibold">`. The level drives both the token size and the semantic element.',
856
+ "Inside a Card use `<CardTitle>`; use `<Heading>` for free-standing page/section headings not covered by a component slot."
857
+ ],
858
+ useCases: [
859
+ "A section heading on a dashboard: `<Heading level={3}>\u4ECA\u6708\u306EKPI</Heading>`.",
860
+ 'A visually-smaller heading that must stay an <h1> for a11y: `<Heading level={1} as="h1">\u2026</Heading>`.'
861
+ ],
862
+ storyPath: "general/typography.tsx",
863
+ rules: [6, 23],
864
+ example: `import { Heading } from "@godxjp/ui/general";
865
+
866
+ <Heading level={2}>\u8ACB\u6C42\u66F8\u4E00\u89A7</Heading>
867
+ <Heading level={3} tone="muted">\u88DC\u8DB3\u30BB\u30AF\u30B7\u30E7\u30F3</Heading>`
868
+ },
771
869
  // ─── data-display ───────────────────────────────────────────────────────
772
870
  {
773
871
  name: "DataTable",
@@ -1015,6 +1113,13 @@ export default function InvoiceList({
1015
1113
  "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
1114
  "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
1115
  ],
1116
+ useCases: [
1117
+ "Server-paginated \u4ED5\u8A33 (journal entry) or \u8ACB\u6C42 (invoice) admin list backed by an AJAX/useQuery endpoint: drive sorting + globalFilter + pagination from the query and pass rowCount \u2014 the grid never loads the whole table into the browser. (Prefer DataTable here if the screen must NOT pull @tanstack/react-table.)",
1118
+ "Member / employee directory with a user-toggled 'set view' column picker (DataGrid.ViewOptions) \u2014 let admins hide columns like \u5165\u793E\u65E5 or \u90E8\u7F72 they don't need, persisting the columnVisibility state per user.",
1119
+ "Bulk-operation worklist (e.g. approve/export selected \u7D4C\u8CBB\u7CBE\u7B97 rows): enableRowSelection + DataGrid.BulkActions to show a 'N\u4EF6\u9078\u629E\u4E2D' action bar with \u4E00\u62EC\u627F\u8A8D / CSV\u51FA\u529B buttons only when rows are checked.",
1120
+ "Dense reconciliation or ledger table where operators flip between compact and comfortable row height via DataGrid.DensityToggle to fit more rows on screen during data-entry-heavy sessions.",
1121
+ "Client-side grid for a fully-loaded small dataset (e.g. a fixed master list of \u52D8\u5B9A\u79D1\u76EE): set manualSorting/manualFiltering/manualPagination={false} so TanStack sorts, searches, and paginates in-browser without any server round-trip."
1122
+ ],
1018
1123
  related: ["DataTable", "Table", "DataState", "Select", "DropdownMenu"],
1019
1124
  example: `import { DataGrid, type ColumnDef } from "@godxjp/ui/data-grid";
1020
1125
  import { Flex } from "@godxjp/ui/layout";
@@ -1225,14 +1330,25 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
1225
1330
  props: [
1226
1331
  {
1227
1332
  name: "variant",
1228
- type: '"default" | "secondary" | "outline" | "success" | "warning" | "destructive" | "info" | "neutral"',
1333
+ type: '"default" | "secondary" | "outline" | "dashed"',
1334
+ defaultValue: '"default"',
1335
+ description: "STRUCTURAL emphasis only (fill/border style) \u2014 NOT colour. Use `tone` for semantic colour. `dashed` = dashed border."
1336
+ },
1337
+ {
1338
+ name: "tone",
1339
+ type: '"default" | "success" | "warning" | "destructive" | "info" | "muted" | "neutral"',
1340
+ description: "SEMANTIC colour intent (ToneProp). This is the colour knob \u2014 success/warning/destructive/info/etc. Keep variant for structure, tone for meaning."
1341
+ },
1342
+ {
1343
+ name: "shape",
1344
+ type: '"default" | "pill" | "sharp"',
1229
1345
  defaultValue: '"default"',
1230
- description: "Visual variant. Overrides the auto-mapped status tone when status is provided."
1346
+ description: "Corner radius from the tokens \u2014 `default` (badge radius), `pill` (fully rounded), `sharp` (square). Use the prop instead of a `rounded-*` className."
1231
1347
  },
1232
1348
  {
1233
1349
  name: "status",
1234
1350
  type: "string",
1235
- description: "Lifecycle key. Known keys auto-map to variant + icon + i18n label; unknown keys fall back to neutral."
1351
+ description: "Lifecycle key. Known keys auto-map to tone + icon + i18n label; unknown keys fall back to neutral."
1236
1352
  },
1237
1353
  {
1238
1354
  name: "icon",
@@ -1881,6 +1997,11 @@ import { ResponsiveGrid } from "@godxjp/ui/layout";
1881
1997
  defaultValue: '""',
1882
1998
  description: "Controlled selected value (data-driven API). Pass an empty string to represent no selection."
1883
1999
  },
2000
+ {
2001
+ name: "defaultValue",
2002
+ type: "string",
2003
+ description: "Uncontrolled initial value (data-driven API). The trigger shows the matching option's label at rest \u2014 including in searchable (showSearch) mode \u2014 so an edit form pre-filled from server data renders the label, not the placeholder. Selected option is marked by a background tint (no check icon)."
2004
+ },
1884
2005
  {
1885
2006
  name: "onChange",
1886
2007
  type: "(value: string, option?: SearchSelectOptionProp) => void",
@@ -3311,7 +3432,7 @@ export function InvoicePeriodFilter() {
3311
3432
  description: "Initial value for uncontrolled mode. Same shape as value."
3312
3433
  },
3313
3434
  {
3314
- name: "onChange",
3435
+ name: "onValueChange",
3315
3436
  type: "(value: string[] | string[][], selectedOptions?: TreeOptionProp[] | TreeOptionProp[][]) => void",
3316
3437
  description: "Fires when selection changes. First arg is the selected path(s); second is the matching node objects. On clear, called with []."
3317
3438
  },
@@ -3495,7 +3616,7 @@ function MultiRegionPicker() {
3495
3616
  description: "Initial value for uncontrolled usage. Ignored once `value` is provided."
3496
3617
  },
3497
3618
  {
3498
- name: "onChange",
3619
+ name: "onValueChange",
3499
3620
  type: "(value: string | string[] | undefined) => void",
3500
3621
  description: "Called on selection change. Returns `string` in single mode, `string[]` in multi/checkable mode, or `undefined` when cleared."
3501
3622
  },
@@ -6019,18 +6140,35 @@ export default function PasswordBlock() {
6019
6140
  group: "navigation",
6020
6141
  tagline: "Context menu primitives with keyboard support and compound parts for command-style action surfaces.",
6021
6142
  props: [
6022
- { name: "open", type: "boolean", description: "Controlled open state." },
6023
6143
  {
6024
6144
  name: "onOpenChange",
6025
6145
  type: "(open: boolean) => void",
6026
6146
  description: "Open-state callback."
6027
6147
  },
6028
- { name: "value", type: "string", description: "Selected value (for controlled patterns)." }
6148
+ {
6149
+ name: "modal",
6150
+ type: "boolean",
6151
+ defaultValue: "true",
6152
+ description: "Modal mode \u2014 locks scroll + outside interaction while open. Set false to keep the rest of the page interactive."
6153
+ },
6154
+ {
6155
+ name: "dir",
6156
+ type: '"ltr" | "rtl"',
6157
+ description: "Reading direction for arrow-key navigation (inherits from the document if omitted)."
6158
+ }
6159
+ ],
6160
+ usage: [
6161
+ "DO trigger this on `onContextMenu` (right-click / long-press), NOT on left-click \u2014 for a button that opens a list of actions on left-click use `DropdownMenu` instead. The two are not interchangeable.",
6162
+ "DO wrap exactly the right-clickable surface in `<ContextMenuTrigger>` (a table row, a card, a file tile) \u2014 the menu anchors to the pointer position, so the trigger should be the whole interactive region the menu acts on.",
6163
+ "DON'T put primary, always-visible actions only behind a context menu \u2014 right-click is a discoverability dead-end on touch and for new users. Mirror critical actions in a visible `Button`/`DropdownMenu` and use ContextMenu as an accelerator.",
6164
+ 'DO mark irreversible items with `variant="destructive"` (\u524A\u9664 / \u53D6\u308A\u6D88\u3057) and group them under a `<ContextMenuSeparator>`; use `<ContextMenuShortcut>` to show the keyboard accelerator, `<ContextMenuSub>`/`<ContextMenuSubTrigger>` for nested submenus, and `<ContextMenuCheckboxItem>`/`<ContextMenuRadioItem>` for stateful toggles.',
6165
+ "DON'T hand-roll a positioned `<div>` + `onContextMenu={e => e.preventDefault()}` \u2014 the primitive already gives you keyboard navigation, focus trapping, typeahead, and WAI-ARIA menu semantics for free."
6029
6166
  ],
6030
6167
  useCases: [
6031
- "Right-click action menu",
6032
- "Contextual menus for rows and cards",
6033
- "Nested action rows with shortcuts"
6168
+ "Right-click actions on a DataTable/DataGrid row (\u8A73\u7D30 / \u8907\u88FD / \u524A\u9664) as a power-user accelerator alongside the visible row action button.",
6169
+ "Contextual menu on a file or document tile in an upload/asset manager (\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 / \u540D\u524D\u5909\u66F4 / \u524A\u9664).",
6170
+ "Nested action menu with submenus and shortcuts (e.g. '\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8 \u25B8 CSV / PDF') on a report card.",
6171
+ "Stateful toggles on a board/kanban card via ContextMenuCheckboxItem (e.g. \u30D4\u30F3\u7559\u3081, \u5B8C\u4E86\u3068\u3057\u3066\u30DE\u30FC\u30AF)."
6034
6172
  ],
6035
6173
  storyPath: "navigation/ContextMenu.stories.tsx",
6036
6174
  rules: [3, 6],
@@ -6054,21 +6192,34 @@ export default function PasswordBlock() {
6054
6192
  group: "navigation",
6055
6193
  tagline: "Application menubar primitives (menus, sub-menus, and check/radio items).",
6056
6194
  props: [
6195
+ {
6196
+ name: "value",
6197
+ type: "string",
6198
+ description: "Controlled value of the currently-open menu (pair with onValueChange)."
6199
+ },
6057
6200
  {
6058
6201
  name: "defaultValue",
6059
6202
  type: "string",
6060
- description: "Uncontrolled initial selected value."
6203
+ description: "Uncontrolled initial open menu."
6061
6204
  },
6062
6205
  {
6063
6206
  name: "onValueChange",
6064
6207
  type: "(value: string) => void",
6065
- description: "Selection callback."
6208
+ description: "Fires with the id of the menu that opened (or '' when all close)."
6066
6209
  }
6067
6210
  ],
6211
+ usage: [
6212
+ "DO reserve Menubar for a persistent, desktop-app-style command bar (\u30D5\u30A1\u30A4\u30EB / \u7DE8\u96C6 / \u8868\u793A \u2026) where multiple top-level menus sit side by side \u2014 moving the pointer across triggers opens the adjacent menu without an extra click.",
6213
+ "DON'T use Menubar for primary site/page navigation (links between pages) \u2014 that is `NavigationMenu`. Menubar items run *commands*; NavigationMenu items *navigate*.",
6214
+ "DON'T use Menubar when there is only one menu button \u2014 a single trigger that drops a list of actions is a `DropdownMenu`. Menubar earns its weight only with several coordinated menus.",
6215
+ "DO compose the full structure: `<Menubar>` \u203A `<MenubarMenu>` \u203A `<MenubarTrigger>` + `<MenubarContent>` with `<MenubarItem>`; use `<MenubarSeparator>` to group, `<MenubarShortcut>` for accelerators, `<MenubarSub>` for nested menus, and `<MenubarCheckboxItem>`/`<MenubarRadioItem>` for view toggles.",
6216
+ 'DO mark destructive commands with `variant="destructive"` and give every item an `onSelect` handler \u2014 items are commands, so they should *do* something, not just close.'
6217
+ ],
6068
6218
  useCases: [
6069
- "Top-bar application command menus",
6070
- "Workspace menus with nested items",
6071
- "Desktop-like navigation shells"
6219
+ "Top-bar command menu for a back-office editor (\u30D5\u30A1\u30A4\u30EB / \u7DE8\u96C6 / \u8868\u793A / \u30D8\u30EB\u30D7) with shortcuts and submenus.",
6220
+ "Workspace tool menus in an admin console where each menu groups a category of actions (\u30C7\u30FC\u30BF / \u30EC\u30DD\u30FC\u30C8 / \u8A2D\u5B9A).",
6221
+ "Desktop-like application shell (e.g. an internal POS or accounting workstation) that mirrors native menubar conventions.",
6222
+ "View-state toggles via MenubarCheckboxItem/MenubarRadioItem (e.g. \u8868\u793A \u203A \u30B0\u30EA\u30C3\u30C9\u7DDA\u3092\u8868\u793A, \u901A\u8CA8\u8868\u793A \u25B8 \xA5 / $)."
6072
6223
  ],
6073
6224
  storyPath: "navigation/Menubar.stories.tsx",
6074
6225
  rules: [3, 6],
@@ -6094,18 +6245,41 @@ export default function PasswordBlock() {
6094
6245
  defaultValue: '"horizontal"',
6095
6246
  description: "Main-axis arrangement for the nav menu."
6096
6247
  },
6248
+ {
6249
+ name: "value",
6250
+ type: "string",
6251
+ description: "Controlled value of the currently-open item (pair with onValueChange)."
6252
+ },
6097
6253
  {
6098
6254
  name: "defaultValue",
6099
6255
  type: "string",
6100
- description: "Uncontrolled initial selected value."
6256
+ description: "Uncontrolled initial open item."
6101
6257
  },
6102
6258
  {
6103
6259
  name: "onValueChange",
6104
6260
  type: "(value: string) => void",
6105
- description: "Selection callback."
6261
+ description: "Fires with the id of the item whose dropdown opened (or '' when all close)."
6262
+ },
6263
+ {
6264
+ name: "delayDuration",
6265
+ type: "number",
6266
+ defaultValue: "200",
6267
+ description: "Hover delay (ms) before a trigger's content opens."
6106
6268
  }
6107
6269
  ],
6108
- useCases: ["Primary app navigation", "Sectioned marketing navigation", "Nested link groups"],
6270
+ usage: [
6271
+ "DO use NavigationMenu for primary *navigation* between pages/sections \u2014 items wrap `<NavigationMenuLink>` (an `<a>`), not command buttons. For command bars (\u30D5\u30A1\u30A4\u30EB/\u7DE8\u96C6 \u2026) use `Menubar`; for a single action drop-down use `DropdownMenu`.",
6272
+ "DO render real links inside `<NavigationMenuLink asChild>` so SPA routers work: `<NavigationMenuLink asChild><Link href={route('reports.index')}>\u30EC\u30DD\u30FC\u30C8</Link></NavigationMenuLink>` \u2014 never nest a raw `<a>` directly with its own onClick navigation.",
6273
+ "DO use `<NavigationMenuTrigger>` + `<NavigationMenuContent>` only when an item needs a rich dropdown panel (link groups, featured cards). Top-level items that go straight to a page should be a bare `<NavigationMenuLink>` with NO trigger.",
6274
+ "DON'T use it as the app's left sidebar \u2014 for a persistent vertical app sidebar use `Sidebar`/`AppShell`. Set `orientation=\"vertical\"` only for an in-content vertical link menu, not the global shell.",
6275
+ "DON'T hand-roll the hover/focus dropdown timing \u2014 the primitive manages open-on-hover with `delayDuration`, keyboard navigation, and the animated viewport for you."
6276
+ ],
6277
+ useCases: [
6278
+ "Primary top navigation for an admin/portal app with dropdown panels grouping related pages (e.g. \u30EC\u30DD\u30FC\u30C8 \u25BE \u2192 \u58F2\u4E0A / \u7D4C\u8CBB / \u5165\u91D1).",
6279
+ "Sectioned marketing or docs navigation with featured link cards inside NavigationMenuContent.",
6280
+ "Nested link groups where one trigger reveals a multi-column panel of related destinations.",
6281
+ "Vertical in-content navigation (orientation='vertical') for a settings or documentation area \u2014 distinct from the global Sidebar shell."
6282
+ ],
6109
6283
  storyPath: "navigation/NavigationMenu.stories.tsx",
6110
6284
  rules: [3, 6],
6111
6285
  example: `import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger } from "@godxjp/ui/navigation";
@@ -6123,12 +6297,53 @@ export default function PasswordBlock() {
6123
6297
  group: "layout",
6124
6298
  tagline: "Resizable panel group/child/handle primitives from react-resizable-panels.",
6125
6299
  props: [
6126
- { name: "id", type: "string", description: "Panel identifier for persistence." },
6127
- { name: "defaultSize", type: "number", description: "Initial panel size (percent/units)." },
6128
- { name: "minSize", type: "number", description: "Minimum size constraint." },
6129
- { name: "maxSize", type: "number", description: "Maximum size constraint." }
6300
+ {
6301
+ name: "orientation",
6302
+ type: '"horizontal" | "vertical"',
6303
+ defaultValue: '"horizontal"',
6304
+ description: "ResizablePanelGroup prop \u2014 axis the panels are laid out / resized along (horizontal = side-by-side)."
6305
+ },
6306
+ {
6307
+ name: "id",
6308
+ type: "string",
6309
+ description: "ResizablePanel identifier \u2014 required for collapse/expand control and for layout persistence."
6310
+ },
6311
+ {
6312
+ name: "defaultSize",
6313
+ type: "number",
6314
+ description: "ResizablePanel initial size as a percentage (0\u2013100) of the group."
6315
+ },
6316
+ {
6317
+ name: "minSize",
6318
+ type: "number",
6319
+ description: "ResizablePanel minimum size (%) \u2014 drag can't shrink below this."
6320
+ },
6321
+ { name: "maxSize", type: "number", description: "ResizablePanel maximum size (%)." },
6322
+ {
6323
+ name: "collapsible",
6324
+ type: "boolean",
6325
+ defaultValue: "false",
6326
+ description: "ResizablePanel \u2014 allow the panel to collapse to collapsedSize when dragged below minSize. Pair with onResize to react to collapse."
6327
+ },
6328
+ {
6329
+ name: "onResize",
6330
+ type: "(size: PanelSize, id, prevSize) => void",
6331
+ description: "ResizablePanel \u2014 fires while/after the panel is resized (e.g. to persist layout)."
6332
+ }
6333
+ ],
6334
+ usage: [
6335
+ 'DO put the layout on `<ResizablePanelGroup orientation="horizontal|vertical">`, the resizable regions in `<ResizablePanel>`, and a `<ResizableHandle>` BETWEEN every adjacent pair \u2014 a group of N panels needs N-1 handles or there is nothing to drag.',
6336
+ "DO size panels with `defaultSize`/`minSize`/`maxSize` as PERCENTAGES (the group totals 100), not pixels \u2014 don't fight this with a fixed `w-[280px]` className on the panel.",
6337
+ "DON'T reach for ResizablePanel when the split is fixed and never user-adjustable \u2014 use a plain `Flex`/`ResponsiveGrid`, or `SplitPane` for a simple two-pane layout. Resizable is for *user-draggable* boundaries only.",
6338
+ "DO give each panel a stable `id` and use `collapsible` + `collapsedSize` for a side panel the user can fully tuck away (e.g. a filters rail), reacting via `onResize`.",
6339
+ "DON'T hand-roll a draggable divider with mouse-move listeners \u2014 the primitive handles pointer + keyboard resizing, ARIA separator semantics, and min/max clamping. Always render `<ResizableHandle>`, never a bare styled `<div>`."
6340
+ ],
6341
+ useCases: [
6342
+ "Master\u2013detail admin layout: a draggable list pane on the left and a detail/preview pane on the right (e.g. \u4ED5\u8A33\u4E00\u89A7 | \u4ED5\u8A33\u8A73\u7D30).",
6343
+ "Collapsible filters or navigation rail beside a data table that operators can widen for long labels or tuck away to maximize the table.",
6344
+ "Stacked vertical split (orientation='vertical') such as a results table over a live JSON/log preview in a data-import tool.",
6345
+ "Three-pane workbench (nav | content | inspector) where each boundary is independently draggable and layout is persisted via id + onResize."
6130
6346
  ],
6131
- useCases: ["Split-pane layouts", "Resizable sidebars", "Code editors with adjustable zones"],
6132
6347
  storyPath: "layout/ResizablePanel.stories.tsx",
6133
6348
  rules: [3, 6],
6134
6349
  example: `import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@godxjp/ui/layout";
@@ -6157,10 +6372,23 @@ export default function PasswordBlock() {
6157
6372
  {
6158
6373
  name: "setApi",
6159
6374
  type: "(api: CarouselApi) => void",
6160
- description: "Receive carousel API for custom logic."
6375
+ description: "Receive the Embla api for custom logic (autoplay, external prev/next). NOT needed for dots \u2014 CarouselDots reads the api from context itself."
6161
6376
  }
6162
6377
  ],
6163
- useCases: ["Feature cards", "Image galleries", "Horizontal stepping lists"],
6378
+ usage: [
6379
+ "DO compose the full set: `<Carousel>` \u203A `<CarouselContent>` \u203A many `<CarouselItem>`, with `<CarouselPrevious>`/`<CarouselNext>` for arrows and `<CarouselDots>` for the indicator row. Don't render items outside `<CarouselContent>` \u2014 the track is the scroll container.",
6380
+ "DO use `<CarouselDots>` for the active-slide indicator instead of wiring `setApi` by hand \u2014 it reads `selectedIndex`/`scrollSnaps` from the Carousel context, renders one `aria-current` dot per snap, and auto-hides when there is \u22641 slide.",
6381
+ "DON'T use a Carousel where ALL items must be seen/compared at once or be keyboard-reachable in reading order (e.g. a list of selectable options, a data table, primary navigation) \u2014 hiding content behind a swipe is an anti-pattern there; use a Grid/`ResponsiveGrid`, `ScrollArea`, or `Tabs`.",
6382
+ "DON'T autoplay without a pause-on-hover/focus control and reduced-motion respect \u2014 pass the Embla autoplay plugin via `plugins` only for non-essential decorative content, never for content the user must read.",
6383
+ "DO set `opts={{ loop: true }}` for galleries that wrap, and rely on the built-in disabling: `CarouselPrevious`/`CarouselNext` auto-disable at the ends (via `canScrollPrev`/`canScrollNext`) \u2014 don't hide them, let them grey out.",
6384
+ "DO give each `<CarouselItem>` real, meaningful content; the component already injects an 'N of M' slide label for screen readers, so don't add a redundant one (a consumer `aria-label` on the item overrides the default)."
6385
+ ],
6386
+ useCases: [
6387
+ "Feature / onboarding highlight cards on a dashboard or landing surface, with CarouselDots showing position.",
6388
+ "Image or document thumbnail gallery (e.g. uploaded receipts / \u7269\u4EF6\u5199\u771F) with looping and prev/next arrows.",
6389
+ "Horizontal stepping list of compact KPI or announcement cards that overflow the viewport width.",
6390
+ "Product/plan comparison cards on a marketing page where swiping between a few options is acceptable (not the primary action)."
6391
+ ],
6164
6392
  storyPath: "data-display/Carousel.stories.tsx",
6165
6393
  rules: [3, 6],
6166
6394
  example: `import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, CarouselDots } from "@godxjp/ui/data-display";
@@ -6192,10 +6420,28 @@ export default function PasswordBlock() {
6192
6420
  type: "(value: string) => void",
6193
6421
  description: "Validated value callback."
6194
6422
  },
6195
- { name: "step", type: "number", defaultValue: "1", description: "Minute step." },
6423
+ {
6424
+ name: "step",
6425
+ type: "number",
6426
+ defaultValue: "1",
6427
+ description: "Minute step (clamped 1\u201359). Snaps the committed minute to the nearest lower multiple and sets the ArrowUp/ArrowDown increment."
6428
+ },
6196
6429
  { name: "name", type: "string", description: "Form field name." }
6197
6430
  ],
6198
- useCases: ["Time filters", "Schedule pickers (calendar-free)", "HH:mm-only forms"],
6431
+ usage: [
6432
+ "DO treat the value as a plain `HH:mm` string (24-hour, zero-padded) \u2014 TimeInput is calendar-free. For a date, or a date+time, use `DatePicker`/`Calendar`; for a richer dropdown time selector use `TimePicker`.",
6433
+ "DO drive it controlled with `value` + `onValueChange` (it follows the vocabulary \u2014 NOT `onChange`/`defaultValue` pairing for control). `onValueChange` fires only with a VALID, step-snapped `HH:mm`, so your state never holds a half-typed value.",
6434
+ "DON'T pass `value` without `onValueChange` \u2014 like every controlled @godxjp/ui input that freezes the field. Omit both for uncontrolled (use `defaultValue`).",
6435
+ "DO set `step` to your scheduling granularity (e.g. `15` or `30`) \u2014 the user can still type freely, but blur/Enter snaps the minute down to the nearest multiple, and ArrowUp/ArrowDown step by that amount (wrapping across midnight).",
6436
+ "DO let the built-in masking + validation work: digits auto-format to `HH:mm`, invalid input sets `aria-invalid` and is reverted on blur. Don't add your own regex/onChange masking on top.",
6437
+ "DON'T use it for a duration/elapsed time that can exceed 23:59 \u2014 it's a clock time-of-day input (00:00\u201323:59). Use a numeric Input for durations."
6438
+ ],
6439
+ useCases: [
6440
+ "\u52E4\u6020 (attendance) start/end time fields \u2014 \u51FA\u52E4 / \u9000\u52E4 HH:mm entry with step={1} or a rounding step for shift schedules.",
6441
+ "Business-hours / reservation slot editor where times snap to a 15- or 30-minute grid (step={15}).",
6442
+ "A from\u2013to time range filter on a report or log screen (two TimeInputs) with no date component.",
6443
+ "Any calendar-free HH:mm-only form field (e.g. a recurring daily batch time, a \u7DE0\u3081\u6642\u523B)."
6444
+ ],
6199
6445
  storyPath: "data-entry/TimeInput.stories.tsx",
6200
6446
  rules: [3, 6],
6201
6447
  example: `import { TimeInput } from "@godxjp/ui/data-entry";
@@ -6666,6 +6912,11 @@ var CARDINAL_RULES = [
6666
6912
  number: 41,
6667
6913
  title: "Drawer & dialog footer layout",
6668
6914
  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.'
6915
+ },
6916
+ {
6917
+ number: 42,
6918
+ title: "Props & Tokens Before Customization",
6919
+ body: "Before reaching for a Tailwind class, inline `style`, or extra CSS, you MUST first check whether the component already supports the need via a PROP, a design TOKEN, or a layout/typography PRIMITIVE. godx-ui is meant to be enough on its own (Ant-Design-style): `className` is for genuine one-offs only \u2014 never to redo what an API already does. Specifically: (1) NEVER hand-roll typography \u2014 no `text-[13px]`/`text-[11px]` arbitrary px (bypasses the golden type scale), no `font-medium`/`font-semibold`/`text-muted-foreground` on a raw `<span>`; use `<Text size tone weight tabular mono>` / `<Heading level>`. (2) NEVER hand-roll a trivial flex/grid wrapper; use `<Flex>` / `<ResponsiveGrid>` / `<PageContainer>`. (3) NEVER set a control's radius/height/colour with a utility when a `shape`/`size`/`tone`/token exists. If a real need has NO prop/token/primitive, that is a library GAP \u2014 file it (draft_bug_report), don't paper over it with ad-hoc Tailwind."
6669
6920
  }
6670
6921
  ];
6671
6922
  function findRule(num) {
@@ -9628,7 +9879,10 @@ function lintJsx(jsx) {
9628
9879
  check(/<input[\s>]/, "Use `<Input>` instead of raw `<input>` (rule 29).");
9629
9880
  check(/<select[\s>]/, "Use `<Select>` instead of raw `<select>` (rule 29).");
9630
9881
  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).");
9882
+ check(
9883
+ /<(table|thead|tbody)[\s>]/,
9884
+ "Use `<DataTable>` instead of a hand-rolled `<table>` (rule 29)."
9885
+ );
9632
9886
  check(
9633
9887
  /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/,
9634
9888
  "Use semantic token utilities (`bg-primary`/`bg-destructive`) not raw color scales (rule 2)."
@@ -9641,6 +9895,10 @@ function lintJsx(jsx) {
9641
9895
  /size=["']default["']/,
9642
9896
  '`size="default"` is not in the controlled vocabulary \u2014 use `size` \u2208 xs|sm|md|lg.'
9643
9897
  );
9898
+ check(
9899
+ /\btext-\[[0-9.]+px\]/,
9900
+ "Arbitrary text size `text-[Npx]` bypasses the golden type scale \u2014 use `<Text size>` / `<Heading level>` (rule 42)."
9901
+ );
9644
9902
  check(
9645
9903
  /<Tag[\s\S]*?color=["']error["']/i,
9646
9904
  'Tag `color="error"` \u2192 `"destructive"` (v5.0, PR #60).'
@@ -9839,7 +10097,7 @@ ${c.example}
9839
10097
  // package.json
9840
10098
  var package_default = {
9841
10099
  name: "@godxjp/ui-mcp",
9842
- version: "0.19.0",
10100
+ version: "0.20.0",
9843
10101
  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).",
9844
10102
  type: "module",
9845
10103
  main: "./dist/index.js",