@nysds/mcp-server 1.21.0 → 1.21.1

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.
@@ -1939,6 +1939,11 @@
1939
1939
  "privacy": "private",
1940
1940
  "description": "Functions\n--------------------------------------------------------------------------"
1941
1941
  },
1942
+ {
1943
+ "kind": "field",
1944
+ "name": "_boundDisabledClickGuard",
1945
+ "privacy": "private"
1946
+ },
1942
1947
  {
1943
1948
  "kind": "method",
1944
1949
  "name": "_getSlottedOl",
@@ -1957,7 +1962,15 @@
1957
1962
  "type": {
1958
1963
  "text": "HTMLLIElement[]"
1959
1964
  }
1960
- }
1965
+ },
1966
+ "parameters": [
1967
+ {
1968
+ "name": "ol",
1969
+ "type": {
1970
+ "text": "HTMLOListElement"
1971
+ }
1972
+ }
1973
+ ]
1961
1974
  },
1962
1975
  {
1963
1976
  "kind": "method",
@@ -1997,7 +2010,57 @@
1997
2010
  },
1998
2011
  {
1999
2012
  "kind": "method",
2000
- "name": "_createBackToParentElement",
2013
+ "name": "_createIcon",
2014
+ "privacy": "private",
2015
+ "return": {
2016
+ "type": {
2017
+ "text": "HTMLElement"
2018
+ }
2019
+ },
2020
+ "parameters": [
2021
+ {
2022
+ "name": "name",
2023
+ "type": {
2024
+ "text": "string"
2025
+ }
2026
+ },
2027
+ {
2028
+ "name": "size",
2029
+ "type": {
2030
+ "text": "string"
2031
+ }
2032
+ }
2033
+ ]
2034
+ },
2035
+ {
2036
+ "kind": "method",
2037
+ "name": "_resetItem",
2038
+ "privacy": "private",
2039
+ "parameters": [
2040
+ {
2041
+ "name": "li",
2042
+ "type": {
2043
+ "text": "HTMLLIElement"
2044
+ }
2045
+ }
2046
+ ]
2047
+ },
2048
+ {
2049
+ "kind": "method",
2050
+ "name": "_applyDisabledState",
2051
+ "privacy": "private",
2052
+ "parameters": [
2053
+ {
2054
+ "name": "a",
2055
+ "type": {
2056
+ "text": "HTMLAnchorElement"
2057
+ }
2058
+ }
2059
+ ]
2060
+ },
2061
+ {
2062
+ "kind": "method",
2063
+ "name": "_applyBackToParentStyle",
2001
2064
  "privacy": "private",
2002
2065
  "parameters": [
2003
2066
  {
@@ -2010,7 +2073,7 @@
2010
2073
  },
2011
2074
  {
2012
2075
  "kind": "method",
2013
- "name": "_createCrumbElement",
2076
+ "name": "_applyCrumbStyle",
2014
2077
  "privacy": "private",
2015
2078
  "parameters": [
2016
2079
  {
@@ -2027,6 +2090,19 @@
2027
2090
  }
2028
2091
  ]
2029
2092
  },
2093
+ {
2094
+ "kind": "method",
2095
+ "name": "_insertEllipsis",
2096
+ "privacy": "private",
2097
+ "parameters": [
2098
+ {
2099
+ "name": "referenceLi",
2100
+ "type": {
2101
+ "text": "HTMLLIElement"
2102
+ }
2103
+ }
2104
+ ]
2105
+ },
2030
2106
  {
2031
2107
  "kind": "method",
2032
2108
  "name": "_handleSlotChange",
@@ -3047,6 +3123,38 @@
3047
3123
  "description": "Height of the card. Set to `100%` to stretch the card to its container's height, so a row of cards renders at an equal height. The extra height is absorbed by the main content area, keeping the `footer` slot pinned to the bottom of the card. Requires the container to give the card a height to fill (e.g. a grid column with `nys-display-flex`).",
3048
3124
  "name": "--nys-card-height",
3049
3125
  "default": "fit-content"
3126
+ },
3127
+ {
3128
+ "description": "Font size of the preheading text.",
3129
+ "name": "--nys-card-font-size--preheading"
3130
+ },
3131
+ {
3132
+ "description": "Font size of the heading text.",
3133
+ "name": "--nys-card-font-size--heading"
3134
+ },
3135
+ {
3136
+ "description": "Font size of the subheading text.",
3137
+ "name": "--nys-card-font-size--subheading"
3138
+ },
3139
+ {
3140
+ "description": "Font size of the description text.",
3141
+ "name": "--nys-card-font-size--description"
3142
+ },
3143
+ {
3144
+ "description": "Line height of the preheading text.",
3145
+ "name": "--nys-card-line-height--preheading"
3146
+ },
3147
+ {
3148
+ "description": "Line height of the heading text.",
3149
+ "name": "--nys-card-line-height--heading"
3150
+ },
3151
+ {
3152
+ "description": "Line height of the subheading text.",
3153
+ "name": "--nys-card-line-height--subheading"
3154
+ },
3155
+ {
3156
+ "description": "Line height of the description text.",
3157
+ "name": "--nys-card-line-height--description"
3050
3158
  }
3051
3159
  ],
3052
3160
  "slots": [
@@ -3083,6 +3191,17 @@
3083
3191
  "attribute": "id",
3084
3192
  "reflects": true
3085
3193
  },
3194
+ {
3195
+ "kind": "field",
3196
+ "name": "size",
3197
+ "type": {
3198
+ "text": "\"sm\" | \"md\" | \"lg\""
3199
+ },
3200
+ "default": "\"md\"",
3201
+ "description": "The size of the text content within a card (preheading, heading, subheading, and description).",
3202
+ "attribute": "size",
3203
+ "reflects": true
3204
+ },
3086
3205
  {
3087
3206
  "kind": "field",
3088
3207
  "name": "preheading",
@@ -3357,6 +3476,16 @@
3357
3476
  "fieldName": "id",
3358
3477
  "propName": "id"
3359
3478
  },
3479
+ {
3480
+ "name": "size",
3481
+ "type": {
3482
+ "text": "\"sm\" | \"md\" | \"lg\""
3483
+ },
3484
+ "default": "\"md\"",
3485
+ "description": "The size of the text content within a card (preheading, heading, subheading, and description).",
3486
+ "fieldName": "size",
3487
+ "propName": "size"
3488
+ },
3360
3489
  {
3361
3490
  "name": "preheading",
3362
3491
  "type": {
@@ -3476,6 +3605,21 @@
3476
3605
  "code": "<div class=\"nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-3\">\n<nys-card\nheading=\"Heading\"\nsubheading=\"Subheading\"\ndescription=\"A short description of the card's subject.\"\n></nys-card>\n</div>",
3477
3606
  "lang": "html"
3478
3607
  },
3608
+ {
3609
+ "title": "Size SM",
3610
+ "code": "<div class=\"nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-3\">\n<nys-card\nsize=\"sm\"\npreheading=\"Preheading\"\nheading=\"Heading\"\nsubheading=\"Subheading\"\ndescription=\"A short description of the card's subject.\"\n></nys-card>\n</div>",
3611
+ "lang": "html"
3612
+ },
3613
+ {
3614
+ "title": "Size MD (default)",
3615
+ "code": "<div class=\"nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-3\">\n<nys-card\nsize=\"md\"\npreheading=\"Preheading\"\nheading=\"Heading\"\nsubheading=\"Subheading\"\ndescription=\"A short description of the card's subject.\"\n></nys-card>\n</div>",
3616
+ "lang": "html"
3617
+ },
3618
+ {
3619
+ "title": "Size LG",
3620
+ "code": "<div class=\"nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-3\">\n<nys-card\nsize=\"lg\"\npreheading=\"Preheading\"\nheading=\"Heading\"\nsubheading=\"Subheading\"\ndescription=\"A short description of the card's subject.\"\n></nys-card>\n</div>",
3621
+ "lang": "html"
3622
+ },
3479
3623
  {
3480
3624
  "title": "Media",
3481
3625
  "code": "<div class=\"nys-tablet:nys-grid-col-6 nys-desktop:nys-grid-col-3\">\n<nys-card\nheading=\"Heading\"\ndescription=\"A card with a media image.\"\n>\n<img slot=\"media\"\nsrc=\"https://images.unsplash.com/photo-1513360371669-4adf3dd7dff8?q=80&w=2070&auto=format&fit=crop\"\nrole=\"presentation\"\n/>\n</nys-card>\n</div>",
@@ -8584,7 +8728,7 @@
8584
8728
  "declarations": [
8585
8729
  {
8586
8730
  "kind": "class",
8587
- "description": "Agency-branded header with app/agency name, navigation, and responsive mobile menu.\n\nPlace below `nys-unavheader`. Slot navigation links as `<ul><li><a>` elements; active links\nare auto-highlighted based on current URL, unless you set `aria-current` on a link\nyourself — then the header leaves the current-page state entirely to you, which is\nwhat apps that don't route on the pathname (hash-routed SPAs, for example) need.\nMobile menu toggles automatically on narrow screens.",
8731
+ "description": "Agency-branded header with app/agency name, navigation, and responsive mobile menu.\n\nPlace below `nys-unavheader`. Slot navigation links as `<ul><li><a>` elements; active links\nare auto-highlighted based on current URL. Mobile menu toggles automatically on narrow screens.",
8588
8732
  "name": "NysGlobalHeader",
8589
8733
  "slots": [
8590
8734
  {
@@ -8597,17 +8741,6 @@
8597
8741
  }
8598
8742
  ],
8599
8743
  "members": [
8600
- {
8601
- "kind": "field",
8602
- "name": "id",
8603
- "type": {
8604
- "text": "string"
8605
- },
8606
- "default": "\"\"",
8607
- "description": "Unique identifier. Auto-generated if not provided.",
8608
- "attribute": "id",
8609
- "reflects": true
8610
- },
8611
8744
  {
8612
8745
  "kind": "field",
8613
8746
  "name": "appName",
@@ -8694,19 +8827,30 @@
8694
8827
  "privacy": "private",
8695
8828
  "description": "Watches for the viewport growing past the mobile breakpoint. The menu and its\ntoggle are `display: none` there, so an open menu that survived a resize would\nleave the focus trap guarding elements nobody can reach."
8696
8829
  },
8830
+ {
8831
+ "kind": "field",
8832
+ "name": "_navSlot",
8833
+ "type": {
8834
+ "text": "HTMLSlotElement | null"
8835
+ },
8836
+ "privacy": "private",
8837
+ "description": "Functions\n--------------------------------------------------------------------------",
8838
+ "readonly": true
8839
+ },
8697
8840
  {
8698
8841
  "kind": "method",
8699
- "name": "_highlightActiveLink",
8842
+ "name": "_getAssignedLinks",
8700
8843
  "privacy": "private",
8701
- "parameters": [
8702
- {
8703
- "name": "container",
8704
- "type": {
8705
- "text": "HTMLElement"
8706
- }
8844
+ "return": {
8845
+ "type": {
8846
+ "text": "HTMLAnchorElement[]"
8707
8847
  }
8708
- ],
8709
- "description": "Functions\n--------------------------------------------------------------------------"
8848
+ }
8849
+ },
8850
+ {
8851
+ "kind": "method",
8852
+ "name": "_highlightActiveLink",
8853
+ "privacy": "private"
8710
8854
  },
8711
8855
  {
8712
8856
  "kind": "method",
@@ -8731,6 +8875,23 @@
8731
8875
  }
8732
8876
  ]
8733
8877
  },
8878
+ {
8879
+ "kind": "method",
8880
+ "name": "_setMobileMenuOpen",
8881
+ "privacy": "private",
8882
+ "parameters": [
8883
+ {
8884
+ "name": "open",
8885
+ "type": {
8886
+ "text": "boolean"
8887
+ }
8888
+ },
8889
+ {
8890
+ "name": "restoreFocus",
8891
+ "default": "false"
8892
+ }
8893
+ ]
8894
+ },
8734
8895
  {
8735
8896
  "kind": "method",
8736
8897
  "name": "_toggleMobileMenu",
@@ -8743,30 +8904,8 @@
8743
8904
  "text": "HTMLElement | null"
8744
8905
  },
8745
8906
  "privacy": "private",
8746
- "description": "The toggle, which is both the trap's first stop and where focus returns.",
8747
8907
  "readonly": true
8748
8908
  },
8749
- {
8750
- "kind": "field",
8751
- "name": "_mobileNav",
8752
- "type": {
8753
- "text": "HTMLElement | null"
8754
- },
8755
- "privacy": "private",
8756
- "readonly": true
8757
- },
8758
- {
8759
- "kind": "method",
8760
- "name": "_closeMobileMenu",
8761
- "privacy": "private",
8762
- "parameters": [
8763
- {
8764
- "name": "restoreFocus",
8765
- "default": "false"
8766
- }
8767
- ],
8768
- "description": "Closes the mobile menu.\n\n`restoreFocus` moves focus back to the toggle, which is required whenever the\nmenu is dismissed by keyboard: the closed menu is `display: none`, so focus\nsitting on one of its links would otherwise be dropped to the top of the\ndocument (WCAG 2.4.3 Focus Order). A click outside is a pointer gesture that\nlands somewhere the user chose, so that path leaves focus alone."
8769
- },
8770
8909
  {
8771
8910
  "kind": "method",
8772
8911
  "name": "_focusableMenuElements",
@@ -8795,7 +8934,7 @@
8795
8934
  }
8796
8935
  }
8797
8936
  ],
8798
- "description": "The focused element, but only when it is one of the menu's own stops.\n\n`document.activeElement` reports the host for anything focused inside this\nshadow root, so the shadow root's own `activeElement` is what identifies the\nreal stop."
8937
+ "description": "The focused element, but only when it is one of the menu's own stops.\n\n`document.activeElement` reports the host for anything focused inside this\nshadow root (the toggle button) or the links in the lightDOM."
8799
8938
  },
8800
8939
  {
8801
8940
  "kind": "method",
@@ -8813,7 +8952,33 @@
8813
8952
  },
8814
8953
  {
8815
8954
  "kind": "method",
8816
- "name": "_listenLinkClicks",
8955
+ "name": "_renderBrandMark",
8956
+ "privacy": "private"
8957
+ },
8958
+ {
8959
+ "kind": "method",
8960
+ "name": "_getNysLogo",
8961
+ "privacy": "private"
8962
+ },
8963
+ {
8964
+ "kind": "field",
8965
+ "name": "_boundClickOutside",
8966
+ "privacy": "private"
8967
+ },
8968
+ {
8969
+ "kind": "field",
8970
+ "name": "_boundLinkClick",
8971
+ "privacy": "private"
8972
+ },
8973
+ {
8974
+ "kind": "field",
8975
+ "name": "_boundBreakpointChange",
8976
+ "privacy": "private",
8977
+ "description": "Growing past the mobile breakpoint takes the menu off the page, so drop the\nopen state with it. No focus restore: the toggle is gone too, and the resize\nwas not a dismissal the user aimed at anything."
8978
+ },
8979
+ {
8980
+ "kind": "field",
8981
+ "name": "_boundKeyDown",
8817
8982
  "privacy": "private"
8818
8983
  },
8819
8984
  {
@@ -8845,51 +9010,9 @@
8845
9010
  "privacy": "private",
8846
9011
  "description": "Literal name for the banner: the author's override, or the \"Site\" default when\nthere is no visible title to reference. Undefined whenever `_bannerLabelledBy`\nhas something to point at, so the landmark never carries both.",
8847
9012
  "readonly": true
8848
- },
8849
- {
8850
- "kind": "method",
8851
- "name": "_renderNameContainer",
8852
- "privacy": "private",
8853
- "description": "App/agency title block. Rendered on its own so the linked and unlinked\nvariants cannot drift apart — the ids here are what names the banner."
8854
- },
8855
- {
8856
- "kind": "method",
8857
- "name": "_renderBrandMark",
8858
- "privacy": "private"
8859
- },
8860
- {
8861
- "kind": "method",
8862
- "name": "_getNysLogo",
8863
- "privacy": "private"
8864
- },
8865
- {
8866
- "kind": "field",
8867
- "name": "_boundClickOutside",
8868
- "privacy": "private"
8869
- },
8870
- {
8871
- "kind": "field",
8872
- "name": "_boundBreakpointChange",
8873
- "privacy": "private",
8874
- "description": "Growing past the mobile breakpoint takes the menu off the page, so drop the\nopen state with it. No focus restore: the toggle is gone too, and the resize\nwas not a dismissal the user aimed at anything."
8875
- },
8876
- {
8877
- "kind": "field",
8878
- "name": "_boundKeyDown",
8879
- "privacy": "private"
8880
9013
  }
8881
9014
  ],
8882
9015
  "attributes": [
8883
- {
8884
- "name": "id",
8885
- "type": {
8886
- "text": "string"
8887
- },
8888
- "default": "\"\"",
8889
- "description": "Unique identifier. Auto-generated if not provided.",
8890
- "fieldName": "id",
8891
- "propName": "id"
8892
- },
8893
9016
  {
8894
9017
  "name": "appName",
8895
9018
  "type": {
@@ -8974,14 +9097,9 @@
8974
9097
  "code": "<nys-globalheader agencyName=\"Office of Information Technology Services\">\n<ul>\n<li><a href=\"https://its.ny.gov/services\">Services</a></li>\n<li><a href=\"https://its.ny.gov/get-help\">Help Center</a></li>\n<li><a href=\"https://its.ny.gov/cybersecurity\">Cybersecurity</a></li>\n<li><a href=\"https://its.ny.gov/policies\">Policies and Laws</a></li>\n<li><a href=\"https://its.ny.gov/procurement\">Procurement</a></li>\n<li><a href=\"https://its.ny.gov/about-us\">About Us</a></li>\n</ul>\n</nys-globalheader>",
8975
9098
  "lang": "html"
8976
9099
  },
8977
- {
8978
- "title": "Author-controlled active link",
8979
- "code": "<!-- Set aria-current yourself and the header stops guessing from the URL. -->\n<nys-globalheader agencyName=\"Office of Information Technology Services\">\n<ul>\n<li><a href=\"#/services\">Services</a></li>\n<li><a href=\"#/help\" aria-current=\"page\">Help Center</a></li>\n</ul>\n</nys-globalheader>",
8980
- "lang": "html"
8981
- },
8982
9100
  {
8983
9101
  "title": "User Actions",
8984
- "code": "<nys-globalheader agencyName=\"Office of Information Technology Services\">\n<nys-button slot=\"user-actions\" label=\"Log out\">\n<nys-avatar\nslot=\"prefix-icon\"\nariaLabel=\"User avatar\"\ninitials=\"NY\"\n></nys-avatar>\n</nys-button>\n</nys-globalheader>\n<nys-dropdownmenu id=\"dropdownmenu\" for=\"my-action-slot\">\n<nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\" disabled></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n</nys-dropdownmenu>",
9102
+ "code": "<nys-globalheader agencyName=\"Office of Information Technology Services\">\n<nys-button id=\"my-action-slot\" slot=\"user-actions\" label=\"Log out\">\n<nys-avatar\nslot=\"prefix-icon\"\nariaLabel=\"User avatar\"\ninitials=\"NY\"\n></nys-avatar>\n</nys-button>\n</nys-globalheader>\n<nys-dropdownmenu id=\"dropdownmenu\" for=\"my-action-slot\">\n<nys-dropdownmenuitem label=\"Profile\" href=\"/profile\"></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Repositories & Github Pages\" href=\"/repos\"></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Organizations\" href=\"/organizations\" disabled></nys-dropdownmenuitem>\n<nys-dropdownmenuitem label=\"Sign out\" href=\"/logout\"></nys-dropdownmenuitem>\n</nys-dropdownmenu>",
8985
9103
  "lang": "html"
8986
9104
  },
8987
9105
  {
@@ -9688,11 +9806,22 @@
9688
9806
  "attribute": "divider",
9689
9807
  "reflects": true
9690
9808
  },
9809
+ {
9810
+ "kind": "field",
9811
+ "name": "inverted",
9812
+ "type": {
9813
+ "text": "boolean"
9814
+ },
9815
+ "default": "false",
9816
+ "description": "Adjusts colors for dark backgrounds.",
9817
+ "attribute": "inverted",
9818
+ "reflects": true
9819
+ },
9691
9820
  {
9692
9821
  "kind": "field",
9693
9822
  "name": "_childObserver",
9694
9823
  "privacy": "private",
9695
- "default": "new MutationObserver(() => this._syncDividers())"
9824
+ "default": "new MutationObserver(() => { this._syncDividers(); this._syncInverted(); })"
9696
9825
  },
9697
9826
  {
9698
9827
  "kind": "field",
@@ -9700,6 +9829,11 @@
9700
9829
  "privacy": "private",
9701
9830
  "default": "new WeakSet<Element>()"
9702
9831
  },
9832
+ {
9833
+ "kind": "method",
9834
+ "name": "_syncInverted",
9835
+ "privacy": "private"
9836
+ },
9703
9837
  {
9704
9838
  "kind": "method",
9705
9839
  "name": "_syncDividers",
@@ -9726,6 +9860,16 @@
9726
9860
  "description": "Draws a divider between items. No divider is drawn after the last item.",
9727
9861
  "fieldName": "divider",
9728
9862
  "propName": "divider"
9863
+ },
9864
+ {
9865
+ "name": "inverted",
9866
+ "type": {
9867
+ "text": "boolean"
9868
+ },
9869
+ "default": "false",
9870
+ "description": "Adjusts colors for dark backgrounds.",
9871
+ "fieldName": "inverted",
9872
+ "propName": "inverted"
9729
9873
  }
9730
9874
  ],
9731
9875
  "superclass": {
@@ -9734,7 +9878,7 @@
9734
9878
  },
9735
9879
  "tagName": "nys-iconlist",
9736
9880
  "customElement": true,
9737
- "summary": "A scannable list of icon + text items, with an optional divider between rows.",
9881
+ "summary": "A scannable list of icon + text items.",
9738
9882
  "examples": [
9739
9883
  {
9740
9884
  "title": "Basic",
@@ -9756,6 +9900,11 @@
9756
9900
  "code": "<nys-iconlist id=\"event-details3\">\n<nys-iconlistitem icon=\"calendar_month\">July 4, 2026</nys-iconlistitem>\n<nys-iconlistitem icon=\"schedule\">\n5:00 PM\n<span slot=\"secondary\">Eastern Standard Time</span>\n</nys-iconlistitem>\n<nys-iconlistitem icon=\"location_on\">\nCentral Park West\n<span slot=\"secondary\">New York, NY</span>\n</nys-iconlistitem>\n</nys-iconlist>",
9757
9901
  "lang": "html"
9758
9902
  },
9903
+ {
9904
+ "title": "Inverted",
9905
+ "code": "<nys-iconlist id=\"demo-inverted\" divider inverted>\n<nys-iconlistitem icon=\"calendar_month\">July 4, 2026</nys-iconlistitem>\n<nys-iconlistitem icon=\"schedule\">\n5:00 PM\n<span slot=\"secondary\">Eastern Standard Time</span>\n</nys-iconlistitem>\n<nys-iconlistitem icon=\"location_on\">\nCentral Park West\n<span slot=\"secondary\">New York, NY</span>\n</nys-iconlistitem>\n</nys-iconlist>",
9906
+ "lang": "html"
9907
+ },
9759
9908
  {
9760
9909
  "title": "Checklist",
9761
9910
  "code": "<nys-iconlist id=\"requirements\">\n<nys-iconlistitem icon=\"check_circle\">Recent pay stubs</nys-iconlistitem>\n<nys-iconlistitem icon=\"check_circle\">Current rent/mortgage statement</nys-iconlistitem>\n<nys-iconlistitem icon=\"check_circle\">Current property tax bill</nys-iconlistitem>\n<nys-iconlistitem icon=\"check_circle\">Current homeowner's insurance bill</nys-iconlistitem>\n<nys-iconlistitem icon=\"check_circle\">Social Security card</nys-iconlistitem>\n</nys-iconlist>",
@@ -9823,6 +9972,17 @@
9823
9972
  "attribute": "divider",
9824
9973
  "reflects": true
9825
9974
  },
9975
+ {
9976
+ "kind": "field",
9977
+ "name": "inverted",
9978
+ "type": {
9979
+ "text": "boolean"
9980
+ },
9981
+ "default": "false",
9982
+ "description": "Adjusts colors for dark backgrounds. Set by the parent `<nys-iconlist inverted>`; not intended to be\nset directly.",
9983
+ "attribute": "inverted",
9984
+ "reflects": true
9985
+ },
9826
9986
  {
9827
9987
  "kind": "method",
9828
9988
  "name": "_handleSecondarySlotChange",
@@ -9857,6 +10017,16 @@
9857
10017
  "description": "Draws a rule below the item. Set by the parent `<nys-iconlist divider>`; not intended to be\nset directly.",
9858
10018
  "fieldName": "divider",
9859
10019
  "propName": "divider"
10020
+ },
10021
+ {
10022
+ "name": "inverted",
10023
+ "type": {
10024
+ "text": "boolean"
10025
+ },
10026
+ "default": "false",
10027
+ "description": "Adjusts colors for dark backgrounds. Set by the parent `<nys-iconlist inverted>`; not intended to be\nset directly.",
10028
+ "fieldName": "inverted",
10029
+ "propName": "inverted"
9860
10030
  }
9861
10031
  ],
9862
10032
  "superclass": {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * New York State Design System v1.21.0
2
+ * New York State Design System v1.21.1
3
3
  * Description: A design system for New York State's digital products.
4
4
  * Repository: https://github.com/its-hcd/nysds
5
5
  * License: MIT
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Framework snippet generation
3
+ *
4
+ * Turns a component's canonical HTML examples into React and Angular
5
+ * snippets using `@nysds/codegen`'s `transformExample` — the same
6
+ * transformer the docs site and Storybook autodocs use, so an AI assistant
7
+ * asking the MCP server sees exactly the same code a developer sees on
8
+ * designsystem.ny.gov.
9
+ */
10
+ import { type CEMExample, type CEMFormControl } from "./cem-parser.js";
11
+ export type FrameworkFilter = "html" | "react" | "angular";
12
+ export interface FrameworkSnippet {
13
+ code: string;
14
+ imports: string[];
15
+ warnings: string[];
16
+ unsupported: boolean;
17
+ }
18
+ export interface ExampleWithSnippets {
19
+ title: string;
20
+ html: string;
21
+ react: FrameworkSnippet;
22
+ angular: FrameworkSnippet;
23
+ }
24
+ /**
25
+ * Builds React and Angular snippets for every HTML example on a component.
26
+ *
27
+ * When `framework` names one target explicitly, that framework's snippet
28
+ * uses its most idiomatic forms binding for a form-control component —
29
+ * React's controlled pattern (`value` + `onNys*`), Angular's
30
+ * `formControlName` (Reactive Forms). The unrequested framework, and every
31
+ * snippet when `framework` is `"html"` (the default), stays a plain
32
+ * attribute-for-attribute conversion so the default response isn't
33
+ * surprising.
34
+ */
35
+ export declare function buildExampleSnippets(examples: CEMExample[] | undefined, framework: FrameworkFilter, formControl: CEMFormControl | undefined): ExampleWithSnippets[];
36
+ //# sourceMappingURL=framework-snippets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-snippets.d.ts","sourceRoot":"","sources":["../../src/lib/framework-snippets.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,EAAU,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE/E,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,gBAAgB,CAAC;IACxB,OAAO,EAAE,gBAAgB,CAAC;CAC3B;AAgBD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EAAE,GAAG,SAAS,EAClC,SAAS,EAAE,eAAe,EAC1B,WAAW,EAAE,cAAc,GAAG,SAAS,GACtC,mBAAmB,EAAE,CA+BvB"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Framework snippet generation
3
+ *
4
+ * Turns a component's canonical HTML examples into React and Angular
5
+ * snippets using `@nysds/codegen`'s `transformExample` — the same
6
+ * transformer the docs site and Storybook autodocs use, so an AI assistant
7
+ * asking the MCP server sees exactly the same code a developer sees on
8
+ * designsystem.ny.gov.
9
+ */
10
+ import { transformExample, } from "@nysds/codegen";
11
+ import { getCEM } from "./cem-parser.js";
12
+ function toSnippet(result) {
13
+ return {
14
+ code: result.code,
15
+ imports: result.imports,
16
+ warnings: result.warnings,
17
+ unsupported: result.unsupported,
18
+ };
19
+ }
20
+ /**
21
+ * Builds React and Angular snippets for every HTML example on a component.
22
+ *
23
+ * When `framework` names one target explicitly, that framework's snippet
24
+ * uses its most idiomatic forms binding for a form-control component —
25
+ * React's controlled pattern (`value` + `onNys*`), Angular's
26
+ * `formControlName` (Reactive Forms). The unrequested framework, and every
27
+ * snippet when `framework` is `"html"` (the default), stays a plain
28
+ * attribute-for-attribute conversion so the default response isn't
29
+ * surprising.
30
+ */
31
+ export function buildExampleSnippets(examples, framework, formControl) {
32
+ if (!examples || examples.length === 0)
33
+ return [];
34
+ const manifest = getCEM();
35
+ const reactFormsMode = framework === "react" && formControl ? "template" : "none";
36
+ const angularFormsMode = framework === "angular" && formControl ? "reactive" : "none";
37
+ return examples
38
+ .filter((example) => !example.lang || example.lang === "html")
39
+ .map((example) => ({
40
+ title: example.title,
41
+ html: example.code,
42
+ react: toSnippet(transformExample({
43
+ html: example.code,
44
+ framework: "react",
45
+ manifest,
46
+ formsMode: reactFormsMode,
47
+ })),
48
+ angular: toSnippet(transformExample({
49
+ html: example.code,
50
+ framework: "angular",
51
+ manifest,
52
+ formsMode: angularFormsMode,
53
+ })),
54
+ }));
55
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Framework usage notes
3
+ *
4
+ * Short, framework-specific guidance attached to `get_component` responses
5
+ * when the caller asks for `framework: "react"` or `"angular"` — the import
6
+ * line, the event-prop naming rule, and (when the component is a form
7
+ * control) how it binds into that framework's forms. Naming follows the
8
+ * rules in `.claude/plans/framework-support/README.md` section 4.1, reused
9
+ * here via `@nysds/codegen` rather than re-derived.
10
+ */
11
+ import type { CEMFormControl } from "./cem-parser.js";
12
+ export interface FrameworkUsageNotes {
13
+ package: string;
14
+ import: string;
15
+ events: string;
16
+ forms?: string;
17
+ }
18
+ export declare function buildReactUsageNotes(tagName: string, className: string, formControl: CEMFormControl | undefined): FrameworkUsageNotes;
19
+ export declare function buildAngularUsageNotes(tagName: string, className: string, formControl: CEMFormControl | undefined): FrameworkUsageNotes;
20
+ //# sourceMappingURL=framework-usage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-usage.d.ts","sourceRoot":"","sources":["../../src/lib/framework-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAQD,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,cAAc,GAAG,SAAS,GACtC,mBAAmB,CAqBrB;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,cAAc,GAAG,SAAS,GACtC,mBAAmB,CAmBrB"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Framework usage notes
3
+ *
4
+ * Short, framework-specific guidance attached to `get_component` responses
5
+ * when the caller asks for `framework: "react"` or `"angular"` — the import
6
+ * line, the event-prop naming rule, and (when the component is a form
7
+ * control) how it binds into that framework's forms. Naming follows the
8
+ * rules in `.claude/plans/framework-support/README.md` section 4.1, reused
9
+ * here via `@nysds/codegen` rather than re-derived.
10
+ */
11
+ import { eventToAngularOutput, eventToReactProp, tagToSubpath, } from "@nysds/codegen";
12
+ const FORM_CONTROL_LABEL = {
13
+ value: "value",
14
+ checked: "checked state",
15
+ files: "selected files",
16
+ };
17
+ export function buildReactUsageNotes(tagName, className, formControl) {
18
+ const subpath = tagToSubpath(tagName);
19
+ const changeProp = formControl
20
+ ? eventToReactProp(formControl.changeEvent)
21
+ : undefined;
22
+ const inputProp = formControl?.inputEvent !== undefined
23
+ ? eventToReactProp(formControl.inputEvent)
24
+ : undefined;
25
+ return {
26
+ package: "@nysds/react",
27
+ import: `import { ${className} } from "@nysds/react/${subpath}";`,
28
+ events: "Events map to onNys* props (nys-change -> onNysChange). The handler receives the typed CustomEvent, so e.detail autocompletes.",
29
+ forms: formControl
30
+ ? `Form control (${formControl.kind}). For a controlled component, bind ${formControl.kind} and update state from ${changeProp}${inputProp ? ` (or ${inputProp} for every keystroke)` : ""}; re-rendering with the same ${FORM_CONTROL_LABEL[formControl.kind]} snaps the element back to your state. See get_guide({ topic: "installation", framework: "react" }) for React Hook Form and uncontrolled-form patterns.`
31
+ : undefined,
32
+ };
33
+ }
34
+ export function buildAngularUsageNotes(tagName, className, formControl) {
35
+ const subpath = tagToSubpath(tagName);
36
+ const angularClass = `${className}Component`;
37
+ const changeOutput = formControl
38
+ ? eventToAngularOutput(formControl.changeEvent)
39
+ : undefined;
40
+ return {
41
+ package: "@nysds/angular",
42
+ import: `import { ${angularClass} } from "@nysds/angular/${subpath}";`,
43
+ events: `Events map to camelCase outputs (nys-change -> (nysChange)); event.detail is typed.${changeOutput
44
+ ? ` This component's change output is (${changeOutput}).`
45
+ : ""}`,
46
+ forms: formControl
47
+ ? 'Implements ControlValueAccessor: works with [(ngModel)], formControlName (Reactive Forms), and Signal Forms [formField] with no CUSTOM_ELEMENTS_SCHEMA. Add the nysControlErrors directive to let Angular own validation display instead of the component\'s own errorMessage/showError. See get_guide({ topic: "installation", framework: "angular" }).'
48
+ : undefined,
49
+ };
50
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Framework package index
3
+ *
4
+ * Reads `data/frameworks.json`, written by `scripts/sync-guides.mjs` from
5
+ * `packages/react/package.json` and `packages/angular/package.json`. Gives
6
+ * tools and resources the published package name and version without
7
+ * hand-maintaining either.
8
+ */
9
+ export interface FrameworkPackageInfo {
10
+ packageName: string;
11
+ version: string;
12
+ }
13
+ export interface FrameworksIndex {
14
+ react: FrameworkPackageInfo;
15
+ angular: FrameworkPackageInfo;
16
+ }
17
+ export declare function getFrameworksIndex(): FrameworksIndex;
18
+ //# sourceMappingURL=frameworks-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks-data.d.ts","sourceRoot":"","sources":["../../src/lib/frameworks-data.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,oBAAoB,CAAC;IAC5B,OAAO,EAAE,oBAAoB,CAAC;CAC/B;AAiBD,wBAAgB,kBAAkB,IAAI,eAAe,CAcpD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Framework package index
3
+ *
4
+ * Reads `data/frameworks.json`, written by `scripts/sync-guides.mjs` from
5
+ * `packages/react/package.json` and `packages/angular/package.json`. Gives
6
+ * tools and resources the published package name and version without
7
+ * hand-maintaining either.
8
+ */
9
+ import { readFileSync, existsSync } from "node:fs";
10
+ import { resolve, dirname } from "node:path";
11
+ import { fileURLToPath } from "node:url";
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ let cached = null;
14
+ function getFrameworksDataPath() {
15
+ const candidates = [
16
+ resolve(__dirname, "../../data/frameworks.json"),
17
+ resolve(process.cwd(), "data/frameworks.json"),
18
+ ];
19
+ for (const path of candidates) {
20
+ if (existsSync(path))
21
+ return path;
22
+ }
23
+ throw new Error(`data/frameworks.json not found. Searched paths:\n${candidates.join("\n")}`);
24
+ }
25
+ export function getFrameworksIndex() {
26
+ if (cached)
27
+ return cached;
28
+ try {
29
+ cached = JSON.parse(readFileSync(getFrameworksDataPath(), "utf-8"));
30
+ }
31
+ catch (error) {
32
+ console.error("Warning: Could not load data/frameworks.json:", error);
33
+ cached = {
34
+ react: { packageName: "@nysds/react", version: "unknown" },
35
+ angular: { packageName: "@nysds/angular", version: "unknown" },
36
+ };
37
+ }
38
+ return cached;
39
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Framework Resources
3
+ *
4
+ * MCP resources for NYSDS framework packages (@nysds/react, @nysds/angular).
5
+ *
6
+ * Resources:
7
+ * - nysds://frameworks - Index of framework packages with version and guide URI
8
+ * - nysds://frameworks/react - @nysds/react guide (synced from its README)
9
+ * - nysds://frameworks/angular - @nysds/angular guide (synced from its README)
10
+ */
11
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
12
+ export declare function registerFrameworkResources(server: McpServer): void;
13
+ //# sourceMappingURL=frameworks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.d.ts","sourceRoot":"","sources":["../../src/resources/frameworks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAezE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8ElE"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Framework Resources
3
+ *
4
+ * MCP resources for NYSDS framework packages (@nysds/react, @nysds/angular).
5
+ *
6
+ * Resources:
7
+ * - nysds://frameworks - Index of framework packages with version and guide URI
8
+ * - nysds://frameworks/react - @nysds/react guide (synced from its README)
9
+ * - nysds://frameworks/angular - @nysds/angular guide (synced from its README)
10
+ */
11
+ import { readFileSync } from "node:fs";
12
+ import { join, dirname } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import { getFrameworksIndex } from "../lib/frameworks-data.js";
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+ const GUIDES_DIR = join(__dirname, "../../data/guides/frameworks");
18
+ function loadFrameworkGuide(framework) {
19
+ try {
20
+ return readFileSync(join(GUIDES_DIR, `${framework}.md`), "utf-8");
21
+ }
22
+ catch {
23
+ return `Framework guide not found: ${framework}. Run "npm run sync:guides -w @nysds/mcp-server".`;
24
+ }
25
+ }
26
+ export function registerFrameworkResources(server) {
27
+ // nysds://frameworks - Index of framework packages
28
+ server.resource("frameworks", "nysds://frameworks", {
29
+ description: "Index of NYSDS framework packages (@nysds/react, @nysds/angular) with their published version and guide resource URI",
30
+ mimeType: "application/json",
31
+ }, async () => {
32
+ const index = getFrameworksIndex();
33
+ const list = [
34
+ {
35
+ id: "react",
36
+ packageName: index.react.packageName,
37
+ version: index.react.version,
38
+ guideUri: "nysds://frameworks/react",
39
+ },
40
+ {
41
+ id: "angular",
42
+ packageName: index.angular.packageName,
43
+ version: index.angular.version,
44
+ guideUri: "nysds://frameworks/angular",
45
+ },
46
+ ];
47
+ return {
48
+ contents: [
49
+ {
50
+ uri: "nysds://frameworks",
51
+ mimeType: "application/json",
52
+ text: JSON.stringify(list, null, 2),
53
+ },
54
+ ],
55
+ };
56
+ });
57
+ // nysds://frameworks/react - @nysds/react guide
58
+ server.resource("frameworks-react", "nysds://frameworks/react", {
59
+ description: "@nysds/react install, usage, forms, SSR, and troubleshooting guide",
60
+ mimeType: "text/markdown",
61
+ }, async () => ({
62
+ contents: [
63
+ {
64
+ uri: "nysds://frameworks/react",
65
+ mimeType: "text/markdown",
66
+ text: loadFrameworkGuide("react"),
67
+ },
68
+ ],
69
+ }));
70
+ // nysds://frameworks/angular - @nysds/angular guide
71
+ server.resource("frameworks-angular", "nysds://frameworks/angular", {
72
+ description: "@nysds/angular install, usage, forms, SSR, and troubleshooting guide",
73
+ mimeType: "text/markdown",
74
+ }, async () => ({
75
+ contents: [
76
+ {
77
+ uri: "nysds://frameworks/angular",
78
+ mimeType: "text/markdown",
79
+ text: loadFrameworkGuide("angular"),
80
+ },
81
+ ],
82
+ }));
83
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/mcp-server",
3
- "version": "1.21.0",
3
+ "version": "1.21.1",
4
4
  "description": "MCP server for the New York State Design System. Exposes components, tokens, and documentation to AI assistants.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,8 +30,8 @@
30
30
  "zod": "^3.25"
31
31
  },
32
32
  "devDependencies": {
33
- "@nysds/styles": "^1.21.0",
34
- "@nysds/tokens": "^1.21.0",
33
+ "@nysds/styles": "^1.21.1",
34
+ "@nysds/tokens": "^1.21.1",
35
35
  "@types/node": "^22.0.0",
36
36
  "typescript": "^5.9.3"
37
37
  },