@handamade/psi-mcp 0.9.1 → 0.10.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 +1 -1
- package/dist/psi-index.json +342 -18
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @handamade/psi-mcp
|
|
2
2
|
|
|
3
|
-
MCP server and agent-context generator for the Psi (Ψ) design system. Documents the system — the
|
|
3
|
+
MCP server and agent-context generator for the Psi (Ψ) design system. Documents the system — the 25 React 19 components, 13 composition patterns (D47) that recipe them together with gap-annotated compose trees, every semantic token with its OKLCH derivation formula resolved across all four themes, and the usage guidance — through two read-only tools. It does not write code.
|
|
4
4
|
|
|
5
5
|
## Connect
|
|
6
6
|
|
package/dist/psi-index.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.10.0",
|
|
3
3
|
"themes": [
|
|
4
4
|
"light",
|
|
5
5
|
"dark",
|
|
@@ -481,6 +481,13 @@
|
|
|
481
481
|
"default": null,
|
|
482
482
|
"description": "Label text."
|
|
483
483
|
},
|
|
484
|
+
{
|
|
485
|
+
"name": "aria-label",
|
|
486
|
+
"type": "string",
|
|
487
|
+
"required": false,
|
|
488
|
+
"default": null,
|
|
489
|
+
"description": "Accessible name when there is no visible label — a table's row-selection\ncheckbox, say. Optional, unlike IconButton's required form (D60): a\nlabelled checkbox is still the common case."
|
|
490
|
+
},
|
|
484
491
|
{
|
|
485
492
|
"name": "ref",
|
|
486
493
|
"type": "Ref<HTMLInputElement>",
|
|
@@ -497,7 +504,7 @@
|
|
|
497
504
|
}
|
|
498
505
|
],
|
|
499
506
|
"slots": [],
|
|
500
|
-
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# Checkbox\n\nNative checkbox with a built-in label; for independent binary choices.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `children` | `ReactNode` | — | no | Label text. |\n| `ref` | `Ref<HTMLInputElement>` | — | no | Forwarded ref to the underlying `<input type=\"checkbox\">` element. |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Keyboard & assistive tech\n\n| Keys | Behavior |\n|---|---|\n| Space | Toggles. Native <input type=checkbox> underneath (visually hidden). |\n\n\n## Theming\n\nOverride `--psi-checkbox-*` custom properties at any scope.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
507
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# Checkbox\n\nNative checkbox with a built-in label; for independent binary choices.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `children` | `ReactNode` | — | no | Label text. |\n| `aria-label` | `string` | — | no | Accessible name when there is no visible label — a table's row-selection checkbox, say. Optional, unlike IconButton's required form (D60): a labelled checkbox is still the common case. |\n| `ref` | `Ref<HTMLInputElement>` | — | no | Forwarded ref to the underlying `<input type=\"checkbox\">` element. |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Keyboard & assistive tech\n\n| Keys | Behavior |\n|---|---|\n| Space | Toggles. Native <input type=checkbox> underneath (visually hidden). |\n\n\n## Theming\n\nOverride `--psi-checkbox-*` custom properties at any scope.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
501
508
|
},
|
|
502
509
|
{
|
|
503
510
|
"name": "Switch",
|
|
@@ -829,6 +836,256 @@
|
|
|
829
836
|
"props": [],
|
|
830
837
|
"slots": [],
|
|
831
838
|
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# MenuSeparator\n\nHairline rule between Menu item groups. No props by design (D53).\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n\n\n## Keyboard & assistive tech\n\n| Keys | Behavior |\n|---|---|\n\n\nNon-interactive rule with role=\"separator\" — exposed to assistive tech as a separator, never focusable, and skipped by roving navigation.\n\n## Theming\n\nThis component has no `--psi-menu-separator-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
839
|
+
},
|
|
840
|
+
{
|
|
841
|
+
"name": "Table",
|
|
842
|
+
"description": "Data table on native table semantics. Holds no state: sorting, selection and pagination are the consumer's (D62, extending D50/D53).",
|
|
843
|
+
"props": [
|
|
844
|
+
{
|
|
845
|
+
"name": "size",
|
|
846
|
+
"type": "32 | 40 | 48",
|
|
847
|
+
"required": false,
|
|
848
|
+
"default": 40,
|
|
849
|
+
"description": "Row height in px."
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
"name": "stickyHeader",
|
|
853
|
+
"type": "boolean",
|
|
854
|
+
"required": false,
|
|
855
|
+
"default": null,
|
|
856
|
+
"description": "Pins the header while the body scrolls."
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
"name": "sortable",
|
|
860
|
+
"type": "boolean",
|
|
861
|
+
"required": false,
|
|
862
|
+
"default": false,
|
|
863
|
+
"description": "Enables the sort affordance on header cells that declare a `sortKey`."
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
"name": "sort",
|
|
867
|
+
"type": "TableSortState | null",
|
|
868
|
+
"required": false,
|
|
869
|
+
"default": null,
|
|
870
|
+
"description": "Controlled sort state; `null` when nothing is sorted."
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
"name": "onSortChange",
|
|
874
|
+
"type": "((sort: TableSortState) => void)",
|
|
875
|
+
"required": false,
|
|
876
|
+
"default": null,
|
|
877
|
+
"description": "Called when a header's sort control is activated. Optional in the type\nbecause `sortable` may be false; a discriminated union expressing the real\ncontract does not survive docgen's flat prop extraction, which would strip\nthese props from the manifest entirely (D62)."
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
"name": "selectable",
|
|
881
|
+
"type": "boolean",
|
|
882
|
+
"required": false,
|
|
883
|
+
"default": false,
|
|
884
|
+
"description": "Renders the row-selection checkbox column."
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
"name": "selected",
|
|
888
|
+
"type": "ReadonlySet<string>",
|
|
889
|
+
"required": false,
|
|
890
|
+
"default": "new Set<string>()",
|
|
891
|
+
"description": "Controlled selection, keyed by each `TableRow`'s `rowId`."
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
"name": "onSelectionChange",
|
|
895
|
+
"type": "((selected: ReadonlySet<string>) => void)",
|
|
896
|
+
"required": false,
|
|
897
|
+
"default": null,
|
|
898
|
+
"description": "Called with the next selection. See `onSortChange` on why it is optional."
|
|
899
|
+
},
|
|
900
|
+
{
|
|
901
|
+
"name": "className",
|
|
902
|
+
"type": "string",
|
|
903
|
+
"required": false,
|
|
904
|
+
"default": null,
|
|
905
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
906
|
+
},
|
|
907
|
+
{
|
|
908
|
+
"name": "ref",
|
|
909
|
+
"type": "Ref<HTMLTableElement>",
|
|
910
|
+
"required": false,
|
|
911
|
+
"default": null,
|
|
912
|
+
"description": "Forwarded ref to the underlying `<table>` element."
|
|
913
|
+
}
|
|
914
|
+
],
|
|
915
|
+
"slots": [
|
|
916
|
+
{
|
|
917
|
+
"name": "body",
|
|
918
|
+
"accepts": {
|
|
919
|
+
"components": [
|
|
920
|
+
"TableHead",
|
|
921
|
+
"TableBody"
|
|
922
|
+
]
|
|
923
|
+
},
|
|
924
|
+
"cardinality": "1..*",
|
|
925
|
+
"order": 1
|
|
926
|
+
}
|
|
927
|
+
],
|
|
928
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# Table\n\nData table on native table semantics. Holds no state: sorting, selection and pagination are the consumer's (D62, extending D50/D53).\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `size` | `32 \\| 40 \\| 48` | 40 | no | Row height in px. |\n| `stickyHeader` | `boolean` | — | no | Pins the header while the body scrolls. |\n| `sortable` | `boolean` | false | no | Enables the sort affordance on header cells that declare a `sortKey`. |\n| `sort` | `TableSortState \\| null` | — | no | Controlled sort state; `null` when nothing is sorted. |\n| `onSortChange` | `((sort: TableSortState) => void)` | — | no | Called when a header's sort control is activated. Optional in the type because `sortable` may be false; a discriminated union expressing the real contract does not survive docgen's flat prop extraction, which would strip these props from the manifest entirely (D62). |\n| `selectable` | `boolean` | false | no | Renders the row-selection checkbox column. |\n| `selected` | `ReadonlySet<string>` | new Set<string>() | no | Controlled selection, keyed by each `TableRow`'s `rowId`. |\n| `onSelectionChange` | `((selected: ReadonlySet<string>) => void)` | — | no | Called with the next selection. See `onSortChange` on why it is optional. |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n| `ref` | `Ref<HTMLTableElement>` | — | no | Forwarded ref to the underlying `<table>` element. |\n\n## Theming\n\nOverride `--psi-table-*` custom properties at any scope; interactive states derive automatically (L - 0.04 hover, L - 0.08 active).\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "TableHead",
|
|
932
|
+
"description": "`<thead>`. When the table is selectable, prepends the select-all cell to the FIRST header row so the header's column count matches the body's — the checkbox column is Table's, not the consumer's schema. Clones the row rather than rebuilding it, so the consumer's own props on that `TableRow` survive.",
|
|
933
|
+
"props": [
|
|
934
|
+
{
|
|
935
|
+
"name": "className",
|
|
936
|
+
"type": "string",
|
|
937
|
+
"required": false,
|
|
938
|
+
"default": null,
|
|
939
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
940
|
+
}
|
|
941
|
+
],
|
|
942
|
+
"slots": [],
|
|
943
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# TableHead\n\n`<thead>`. When the table is selectable, prepends the select-all cell to the FIRST header row so the header's column count matches the body's — the checkbox column is Table's, not the consumer's schema. Clones the row rather than rebuilding it, so the consumer's own props on that `TableRow` survive.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-table-head-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
944
|
+
},
|
|
945
|
+
{
|
|
946
|
+
"name": "TableBody",
|
|
947
|
+
"description": "`<tbody>` wrapper.",
|
|
948
|
+
"props": [
|
|
949
|
+
{
|
|
950
|
+
"name": "className",
|
|
951
|
+
"type": "string",
|
|
952
|
+
"required": false,
|
|
953
|
+
"default": null,
|
|
954
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
955
|
+
}
|
|
956
|
+
],
|
|
957
|
+
"slots": [],
|
|
958
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# TableBody\n\n`<tbody>` wrapper.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-table-body-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
"name": "TableRow",
|
|
962
|
+
"description": "`<tr>`. `rowId` is the key the `selected` set holds.",
|
|
963
|
+
"props": [
|
|
964
|
+
{
|
|
965
|
+
"name": "rowId",
|
|
966
|
+
"type": "string",
|
|
967
|
+
"required": false,
|
|
968
|
+
"default": null,
|
|
969
|
+
"description": "Stable identity for selection. Required for selectable tables (D62)."
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
"name": "selectLabel",
|
|
973
|
+
"type": "string",
|
|
974
|
+
"required": false,
|
|
975
|
+
"default": null,
|
|
976
|
+
"description": "Accessible name for this row's selection checkbox."
|
|
977
|
+
},
|
|
978
|
+
{
|
|
979
|
+
"name": "className",
|
|
980
|
+
"type": "string",
|
|
981
|
+
"required": false,
|
|
982
|
+
"default": null,
|
|
983
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
984
|
+
}
|
|
985
|
+
],
|
|
986
|
+
"slots": [],
|
|
987
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# TableRow\n\n`<tr>`. `rowId` is the key the `selected` set holds.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `rowId` | `string` | — | no | Stable identity for selection. Required for selectable tables (D62). |\n| `selectLabel` | `string` | — | no | Accessible name for this row's selection checkbox. |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-table-row-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
988
|
+
},
|
|
989
|
+
{
|
|
990
|
+
"name": "TableHeaderCell",
|
|
991
|
+
"description": "`<th scope=\"col\">`. `aria-sort` belongs on the th, never on the inner button — assistive tech reads the sort state from the column header.",
|
|
992
|
+
"props": [
|
|
993
|
+
{
|
|
994
|
+
"name": "sortKey",
|
|
995
|
+
"type": "string",
|
|
996
|
+
"required": false,
|
|
997
|
+
"default": null,
|
|
998
|
+
"description": "Sort key this column emits. Enables the sort control when the table is `sortable`."
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
"name": "numeric",
|
|
1002
|
+
"type": "boolean",
|
|
1003
|
+
"required": false,
|
|
1004
|
+
"default": null,
|
|
1005
|
+
"description": "Right-aligns and renders tabular figures (D62)."
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
"name": "className",
|
|
1009
|
+
"type": "string",
|
|
1010
|
+
"required": false,
|
|
1011
|
+
"default": null,
|
|
1012
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
1013
|
+
}
|
|
1014
|
+
],
|
|
1015
|
+
"slots": [],
|
|
1016
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# TableHeaderCell\n\n`<th scope=\"col\">`. `aria-sort` belongs on the th, never on the inner button — assistive tech reads the sort state from the column header.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `sortKey` | `string` | — | no | Sort key this column emits. Enables the sort control when the table is `sortable`. |\n| `numeric` | `boolean` | — | no | Right-aligns and renders tabular figures (D62). |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-table-header-cell-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
1017
|
+
},
|
|
1018
|
+
{
|
|
1019
|
+
"name": "TableCell",
|
|
1020
|
+
"description": "`<td>`. `numeric` means right-aligned *and* tabular — a column that aligns but whose digits jitter between rows defeats the purpose.",
|
|
1021
|
+
"props": [
|
|
1022
|
+
{
|
|
1023
|
+
"name": "numeric",
|
|
1024
|
+
"type": "boolean",
|
|
1025
|
+
"required": false,
|
|
1026
|
+
"default": null,
|
|
1027
|
+
"description": "Right-aligns and renders tabular figures (D62)."
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
"name": "className",
|
|
1031
|
+
"type": "string",
|
|
1032
|
+
"required": false,
|
|
1033
|
+
"default": null,
|
|
1034
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
1035
|
+
}
|
|
1036
|
+
],
|
|
1037
|
+
"slots": [],
|
|
1038
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# TableCell\n\n`<td>`. `numeric` means right-aligned *and* tabular — a column that aligns but whose digits jitter between rows defeats the purpose.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `numeric` | `boolean` | — | no | Right-aligns and renders tabular figures (D62). |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-table-cell-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
1039
|
+
},
|
|
1040
|
+
{
|
|
1041
|
+
"name": "Pagination",
|
|
1042
|
+
"description": "Numbered pager with ellipsis truncation (D63). Standalone rather than a Table family member: `table-pagination` composes it as a Toolbar sibling of the page-size Select.",
|
|
1043
|
+
"props": [
|
|
1044
|
+
{
|
|
1045
|
+
"name": "page",
|
|
1046
|
+
"type": "number",
|
|
1047
|
+
"required": true,
|
|
1048
|
+
"default": null,
|
|
1049
|
+
"description": "Current page, 1-based."
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
"name": "pageCount",
|
|
1053
|
+
"type": "number",
|
|
1054
|
+
"required": true,
|
|
1055
|
+
"default": null,
|
|
1056
|
+
"description": "Total number of pages."
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
"name": "onPageChange",
|
|
1060
|
+
"type": "(page: number) => void",
|
|
1061
|
+
"required": true,
|
|
1062
|
+
"default": null,
|
|
1063
|
+
"description": "Called with the requested page. Required — unlike Table's `onSortChange`/\n`onSelectionChange`, which are optional because `sortable`/`selectable`\ngate whether they're meaningful, `Pagination` has no such gating boolean:\nthe prop is unconditionally meaningful, so a `Pagination` without it is a\ndead control (final review finding, D62)."
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"name": "siblingCount",
|
|
1067
|
+
"type": "number",
|
|
1068
|
+
"required": false,
|
|
1069
|
+
"default": 1,
|
|
1070
|
+
"description": "Pages shown either side of the current one before truncating."
|
|
1071
|
+
},
|
|
1072
|
+
{
|
|
1073
|
+
"name": "aria-label",
|
|
1074
|
+
"type": "string",
|
|
1075
|
+
"required": false,
|
|
1076
|
+
"default": "Pagination",
|
|
1077
|
+
"description": "Accessible name for the nav landmark."
|
|
1078
|
+
},
|
|
1079
|
+
{
|
|
1080
|
+
"name": "className",
|
|
1081
|
+
"type": "string",
|
|
1082
|
+
"required": false,
|
|
1083
|
+
"default": null,
|
|
1084
|
+
"description": "Additional CSS class name(s) merged onto the component's root element."
|
|
1085
|
+
}
|
|
1086
|
+
],
|
|
1087
|
+
"slots": [],
|
|
1088
|
+
"doc": "<!-- Generated by emit-docs.ts — do not edit. -->\n# Pagination\n\nNumbered pager with ellipsis truncation (D63). Standalone rather than a Table family member: `table-pagination` composes it as a Toolbar sibling of the page-size Select.\n\n## Props\n\n| Prop | Type | Default | Required | Description |\n|---|---|---|---|---|\n| `page` | `number` | — | yes | Current page, 1-based. |\n| `pageCount` | `number` | — | yes | Total number of pages. |\n| `onPageChange` | `(page: number) => void` | — | yes | Called with the requested page. Required — unlike Table's `onSortChange`/ `onSelectionChange`, which are optional because `sortable`/`selectable` gate whether they're meaningful, `Pagination` has no such gating boolean: the prop is unconditionally meaningful, so a `Pagination` without it is a dead control (final review finding, D62). |\n| `siblingCount` | `number` | 1 | no | Pages shown either side of the current one before truncating. |\n| `aria-label` | `string` | Pagination | no | Accessible name for the nav landmark. |\n| `className` | `string` | — | no | Additional CSS class name(s) merged onto the component's root element. |\n\n## Theming\n\nThis component has no `--psi-pagination-*` tokens — its styling binds scale tokens only, so there is nothing component-scoped to override. Theme changes reach it through the semantic tokens of its children and surroundings.\n\n\n\n## Rules\n\n- One accent per visual group; everything else neutral or ghost.\n- danger only for actions with real consequences.\n- Sizes are px numbers (24|32|40|48), never S/M/L.\n- Typography tokens are --psi-text-{size}-{lineHeight}-{weight}.\n- Override component tokens (--psi-{component}-*), not semantic tokens, for one-off theming.\n- --psi-button-font overrides button typography across all sizes (documented D34 override; ember → mono).\n- Wrap labeled form controls in Field — label association, description/error line, aria-describedby and aria-invalid come wired; don't hand-roll label+message rows.\n- Use Dialog for blocking modal flows — title/footer slots, dismissible gate; danger stays on the footer Buttons, one accent per group.\n"
|
|
832
1089
|
}
|
|
833
1090
|
],
|
|
834
1091
|
"tokens": [
|
|
@@ -2458,24 +2715,90 @@
|
|
|
2458
2715
|
"sortable": true
|
|
2459
2716
|
},
|
|
2460
2717
|
"slots": {
|
|
2461
|
-
"head": [
|
|
2462
|
-
"{content:columns-note}"
|
|
2463
|
-
],
|
|
2464
2718
|
"body": [
|
|
2465
|
-
|
|
2719
|
+
{
|
|
2720
|
+
"component": "TableHead",
|
|
2721
|
+
"slots": {
|
|
2722
|
+
"body": [
|
|
2723
|
+
{
|
|
2724
|
+
"component": "TableRow",
|
|
2725
|
+
"slots": {
|
|
2726
|
+
"body": [
|
|
2727
|
+
{
|
|
2728
|
+
"component": "TableHeaderCell",
|
|
2729
|
+
"props": {
|
|
2730
|
+
"sortKey": "date"
|
|
2731
|
+
},
|
|
2732
|
+
"content": "date-label"
|
|
2733
|
+
},
|
|
2734
|
+
{
|
|
2735
|
+
"component": "TableHeaderCell",
|
|
2736
|
+
"props": {
|
|
2737
|
+
"sortKey": "payee"
|
|
2738
|
+
},
|
|
2739
|
+
"content": "payee-label"
|
|
2740
|
+
},
|
|
2741
|
+
{
|
|
2742
|
+
"component": "TableHeaderCell",
|
|
2743
|
+
"props": {
|
|
2744
|
+
"sortKey": "amount",
|
|
2745
|
+
"numeric": true
|
|
2746
|
+
},
|
|
2747
|
+
"content": "amount-label"
|
|
2748
|
+
}
|
|
2749
|
+
]
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
]
|
|
2753
|
+
}
|
|
2754
|
+
},
|
|
2755
|
+
{
|
|
2756
|
+
"component": "TableBody",
|
|
2757
|
+
"slots": {
|
|
2758
|
+
"body": [
|
|
2759
|
+
{
|
|
2760
|
+
"component": "TableRow",
|
|
2761
|
+
"props": {
|
|
2762
|
+
"rowId": "row-id"
|
|
2763
|
+
},
|
|
2764
|
+
"slots": {
|
|
2765
|
+
"body": [
|
|
2766
|
+
{
|
|
2767
|
+
"component": "TableCell",
|
|
2768
|
+
"content": "date-cell"
|
|
2769
|
+
},
|
|
2770
|
+
{
|
|
2771
|
+
"component": "TableCell",
|
|
2772
|
+
"content": "payee-cell"
|
|
2773
|
+
},
|
|
2774
|
+
{
|
|
2775
|
+
"component": "TableCell",
|
|
2776
|
+
"props": {
|
|
2777
|
+
"numeric": true
|
|
2778
|
+
},
|
|
2779
|
+
"content": "amount-cell"
|
|
2780
|
+
}
|
|
2781
|
+
]
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
]
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2466
2787
|
]
|
|
2467
2788
|
}
|
|
2468
2789
|
},
|
|
2469
2790
|
"parameters": [],
|
|
2470
2791
|
"content": {
|
|
2471
|
-
"
|
|
2472
|
-
"
|
|
2792
|
+
"date-label": "Date",
|
|
2793
|
+
"payee-label": "Payee",
|
|
2794
|
+
"amount-label": "Amount",
|
|
2795
|
+
"date-cell": "[one row per record]",
|
|
2796
|
+
"payee-cell": "[put the row-actions menu in the last cell]",
|
|
2797
|
+
"amount-cell": "[numeric columns align right and use tabular figures]"
|
|
2473
2798
|
},
|
|
2474
|
-
"gaps": [
|
|
2475
|
-
|
|
2476
|
-
]
|
|
2477
|
-
"blocked": true,
|
|
2478
|
-
"preset": null
|
|
2799
|
+
"gaps": [],
|
|
2800
|
+
"blocked": false,
|
|
2801
|
+
"preset": "<Table\n selectable={true}\n sortable={true}\n>\n <TableHead>\n <TableRow>\n <TableHeaderCell sortKey=\"date\">Date</TableHeaderCell>\n <TableHeaderCell sortKey=\"payee\">Payee</TableHeaderCell>\n <TableHeaderCell numeric={true} sortKey=\"amount\">Amount</TableHeaderCell>\n </TableRow>\n </TableHead>\n <TableBody>\n <TableRow\n rowId=\"row-id\"\n >\n <TableCell>[one row per record]</TableCell>\n <TableCell>[put the row-actions menu in the last cell]</TableCell>\n <TableCell numeric={true}>[numeric columns align right and use tabular figures]</TableCell>\n </TableRow>\n </TableBody>\n</Table>\n"
|
|
2479
2802
|
},
|
|
2480
2803
|
{
|
|
2481
2804
|
"id": "date-range-filter",
|
|
@@ -2976,11 +3299,9 @@
|
|
|
2976
3299
|
"content": {
|
|
2977
3300
|
"page-size-label": "Rows per page"
|
|
2978
3301
|
},
|
|
2979
|
-
"gaps": [
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
"blocked": true,
|
|
2983
|
-
"preset": null
|
|
3302
|
+
"gaps": [],
|
|
3303
|
+
"blocked": false,
|
|
3304
|
+
"preset": "<Toolbar\n gap={12}\n>\n <Field\n label=\"Rows per page\"\n >\n <Select size={32} />\n </Field>\n <Pagination />\n</Toolbar>\n"
|
|
2984
3305
|
}
|
|
2985
3306
|
],
|
|
2986
3307
|
"scales": {
|
|
@@ -3040,6 +3361,7 @@
|
|
|
3040
3361
|
"gutterNarrow": 24
|
|
3041
3362
|
},
|
|
3042
3363
|
"zIndex": {
|
|
3364
|
+
"sticky": 1,
|
|
3043
3365
|
"nav": 100,
|
|
3044
3366
|
"overlay": 1000,
|
|
3045
3367
|
"tooltip": 1100
|
|
@@ -3171,6 +3493,7 @@
|
|
|
3171
3493
|
},
|
|
3172
3494
|
"recipes": {
|
|
3173
3495
|
"mediaTint": "Apply .psi-media-tint to media elements; the brand defines --psi-media-tint (D35). Hover/focus reveals true color over --psi-duration-450 --psi-ease-soft.",
|
|
3496
|
+
"tabularNumerals": "Apply .psi-tabular to numeric content for fixed-width digits; --psi-font-variant-numeric is tabular-nums (D62). Table's numeric columns bind the token directly rather than via the utility class.",
|
|
3174
3497
|
"sectionHeader": "SectionHeader ships as a recipe, not a component (v1.2 non-goal): baseline-aligned flex row — mono annotation (--psi-text-mono-14-20-regular, --psi-fg-accent) + h2 (.psi-display-32-32-extrabold) + optional trailing meta, border-bottom 1px var(--psi-border-faint), padding-bottom var(--psi-space-20)."
|
|
3175
3498
|
},
|
|
3176
3499
|
"tags": {
|
|
@@ -3320,6 +3643,7 @@
|
|
|
3320
3643
|
"gutterNarrow": 24
|
|
3321
3644
|
},
|
|
3322
3645
|
"zIndex": {
|
|
3646
|
+
"sticky": 1,
|
|
3323
3647
|
"nav": 100,
|
|
3324
3648
|
"overlay": 1000,
|
|
3325
3649
|
"tooltip": 1100
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@handamade/psi-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "MCP server and agent-context generator for the Psi (Ψ) design system",
|
|
6
6
|
"type": "module",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"tsx": "^4.22.4",
|
|
34
34
|
"typescript": "^5.7.0",
|
|
35
35
|
"vitest": "^3.2.6",
|
|
36
|
-
"@handamade/psi-tokens": "0.
|
|
37
|
-
"@handamade/psi-react": "0.
|
|
36
|
+
"@handamade/psi-tokens": "0.10.0",
|
|
37
|
+
"@handamade/psi-react": "0.10.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "tsx scripts/build-index.ts && tsc -p tsconfig.build.json"
|