@commercetools/nimbus-mcp 0.1.0 → 2.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.
Files changed (450) hide show
  1. package/README.md +63 -14
  2. package/data/docs/route-manifest.json +10913 -0
  3. package/data/docs/routes/components-accessibility-visually-hidden.json +388 -0
  4. package/data/docs/routes/components-accessibility.json +34 -0
  5. package/data/docs/routes/components-buttons-button.json +715 -0
  6. package/data/docs/routes/components-buttons-icon-button.json +852 -0
  7. package/data/docs/routes/components-buttons-icon-toggle-button.json +594 -0
  8. package/data/docs/routes/components-buttons-split-button.json +670 -0
  9. package/data/docs/routes/components-buttons-toggle-button-group.json +722 -0
  10. package/data/docs/routes/components-buttons-toggle-button.json +689 -0
  11. package/data/docs/routes/components-buttons.json +36 -0
  12. package/data/docs/routes/components-data-display-badge.json +555 -0
  13. package/data/docs/routes/components-data-display-card.json +338 -0
  14. package/data/docs/routes/components-data-display-data-table.json +855 -0
  15. package/data/docs/routes/components-data-display-draggable-list.json +596 -0
  16. package/data/docs/routes/components-data-display-table.json +472 -0
  17. package/data/docs/routes/components-data-display-tag-group.json +535 -0
  18. package/data/docs/routes/components-data-display.json +34 -0
  19. package/data/docs/routes/components-feedback-alert.json +696 -0
  20. package/data/docs/routes/components-feedback-dialog.json +682 -0
  21. package/data/docs/routes/components-feedback-drawer.json +600 -0
  22. package/data/docs/routes/components-feedback-loading-spinner.json +415 -0
  23. package/data/docs/routes/components-feedback-progress-bar.json +661 -0
  24. package/data/docs/routes/components-feedback-toast.json +1040 -0
  25. package/data/docs/routes/components-feedback-tooltip.json +510 -0
  26. package/data/docs/routes/components-feedback.json +34 -0
  27. package/data/docs/routes/components-forms-field-errors.json +557 -0
  28. package/data/docs/routes/components-forms-form-field.json +848 -0
  29. package/data/docs/routes/components-forms-group.json +427 -0
  30. package/data/docs/routes/components-forms-localized-field.json +770 -0
  31. package/data/docs/routes/components-forms.json +37 -0
  32. package/data/docs/routes/components-inputs-calendar.json +611 -0
  33. package/data/docs/routes/components-inputs-checkbox.json +774 -0
  34. package/data/docs/routes/components-inputs-combo-box.json +761 -0
  35. package/data/docs/routes/components-inputs-date-input.json +628 -0
  36. package/data/docs/routes/components-inputs-date-picker.json +709 -0
  37. package/data/docs/routes/components-inputs-date-range-picker.json +599 -0
  38. package/data/docs/routes/components-inputs-money-input.json +721 -0
  39. package/data/docs/routes/components-inputs-multiline-text-input.json +611 -0
  40. package/data/docs/routes/components-inputs-number-input.json +647 -0
  41. package/data/docs/routes/components-inputs-password-input.json +576 -0
  42. package/data/docs/routes/components-inputs-radio-input.json +583 -0
  43. package/data/docs/routes/components-inputs-range-calendar.json +607 -0
  44. package/data/docs/routes/components-inputs-rich-text-input.json +599 -0
  45. package/data/docs/routes/components-inputs-scoped-search-input.json +570 -0
  46. package/data/docs/routes/components-inputs-search-input.json +588 -0
  47. package/data/docs/routes/components-inputs-select-input.json +960 -0
  48. package/data/docs/routes/components-inputs-switch.json +720 -0
  49. package/data/docs/routes/components-inputs-text-input.json +566 -0
  50. package/data/docs/routes/components-inputs-time-input.json +775 -0
  51. package/data/docs/routes/components-inputs.json +34 -0
  52. package/data/docs/routes/components-layout-box.json +501 -0
  53. package/data/docs/routes/components-layout-defaultpage.json +748 -0
  54. package/data/docs/routes/components-layout-flex.json +587 -0
  55. package/data/docs/routes/components-layout-grid.json +393 -0
  56. package/data/docs/routes/components-layout-modalpage.json +716 -0
  57. package/data/docs/routes/components-layout-pagecontent.json +673 -0
  58. package/data/docs/routes/components-layout-separator.json +461 -0
  59. package/data/docs/routes/components-layout-simple-grid.json +519 -0
  60. package/data/docs/routes/components-layout-spacer.json +573 -0
  61. package/data/docs/routes/components-layout-stack.json +481 -0
  62. package/data/docs/routes/components-layout.json +34 -0
  63. package/data/docs/routes/components-media-avatar.json +427 -0
  64. package/data/docs/routes/components-media-icon.json +663 -0
  65. package/data/docs/routes/components-media-image.json +511 -0
  66. package/data/docs/routes/components-media-inline-svg.json +586 -0
  67. package/data/docs/routes/components-media.json +34 -0
  68. package/data/docs/routes/components-navigation-accordion.json +643 -0
  69. package/data/docs/routes/components-navigation-collapsible-motion.json +628 -0
  70. package/data/docs/routes/components-navigation-link.json +554 -0
  71. package/data/docs/routes/components-navigation-menu.json +546 -0
  72. package/data/docs/routes/components-navigation-pagination.json +502 -0
  73. package/data/docs/routes/components-navigation-steps.json +629 -0
  74. package/data/docs/routes/components-navigation-tabnav.json +546 -0
  75. package/data/docs/routes/components-navigation-tabs.json +635 -0
  76. package/data/docs/routes/components-navigation-toolbar.json +549 -0
  77. package/data/docs/routes/components-navigation.json +34 -0
  78. package/data/docs/routes/components-typography-code.json +39 -0
  79. package/data/docs/routes/components-typography-heading.json +402 -0
  80. package/data/docs/routes/components-typography-kbd.json +399 -0
  81. package/data/docs/routes/components-typography-list.json +593 -0
  82. package/data/docs/routes/components-typography-text.json +444 -0
  83. package/data/docs/routes/components-typography.json +34 -0
  84. package/data/docs/routes/components-utilities-nimbus-i18n-provider.json +295 -0
  85. package/data/docs/routes/components-utilities-nimbus-provider.json +663 -0
  86. package/data/docs/routes/components-utilities.json +34 -0
  87. package/data/docs/routes/components.json +33 -0
  88. package/data/docs/routes/home-contribute-adrs-adr0001-consumer-component-apis.json +314 -0
  89. package/data/docs/routes/home-contribute-adrs-adr0002-compound-component-extraction.json +160 -0
  90. package/data/docs/routes/home-contribute-adrs-adr0003-component-lifecycle-states.json +460 -0
  91. package/data/docs/routes/home-contribute-adrs.json +205 -0
  92. package/data/docs/routes/home-contribute-development-setup.json +213 -0
  93. package/data/docs/routes/home-contribute-stats.json +36 -0
  94. package/data/docs/routes/home-contribute.json +36 -0
  95. package/data/docs/routes/home-design-tokens-aspect-ratios.json +36 -0
  96. package/data/docs/routes/home-design-tokens-borders.json +35 -0
  97. package/data/docs/routes/home-design-tokens-colors.json +157 -0
  98. package/data/docs/routes/home-design-tokens-other-animations.json +119 -0
  99. package/data/docs/routes/home-design-tokens-other-blurs.json +36 -0
  100. package/data/docs/routes/home-design-tokens-other-breakpoints.json +61 -0
  101. package/data/docs/routes/home-design-tokens-other-cursors.json +36 -0
  102. package/data/docs/routes/home-design-tokens-other-z-indices.json +39 -0
  103. package/data/docs/routes/home-design-tokens-other.json +35 -0
  104. package/data/docs/routes/home-design-tokens-radii.json +59 -0
  105. package/data/docs/routes/home-design-tokens-shadows.json +57 -0
  106. package/data/docs/routes/home-design-tokens-sizes.json +137 -0
  107. package/data/docs/routes/home-design-tokens-spacing.json +36 -0
  108. package/data/docs/routes/home-design-tokens-typography.json +184 -0
  109. package/data/docs/routes/home-design-tokens.json +34 -0
  110. package/data/docs/routes/home-getting-started-core-concepts.json +301 -0
  111. package/data/docs/routes/home-getting-started-installation.json +621 -0
  112. package/data/docs/routes/home-getting-started-mcp-server-overview.json +139 -0
  113. package/data/docs/routes/home-getting-started-mcp-server-setup.json +316 -0
  114. package/data/docs/routes/home-getting-started-release-process.json +294 -0
  115. package/data/docs/routes/home-getting-started-testing-setup.json +296 -0
  116. package/data/docs/routes/home-playground-markdown.json +638 -0
  117. package/data/docs/routes/home-playground-toc.json +169 -0
  118. package/data/docs/routes/home-playground.json +34 -0
  119. package/data/docs/routes/home-style-props-background.json +236 -0
  120. package/data/docs/routes/home-style-props-border.json +310 -0
  121. package/data/docs/routes/home-style-props-display.json +120 -0
  122. package/data/docs/routes/home-style-props-effects.json +116 -0
  123. package/data/docs/routes/home-style-props-filters.json +396 -0
  124. package/data/docs/routes/home-style-props-flex-and-grid.json +496 -0
  125. package/data/docs/routes/home-style-props-interactivity.json +356 -0
  126. package/data/docs/routes/home-style-props-layout.json +422 -0
  127. package/data/docs/routes/home-style-props-list.json +116 -0
  128. package/data/docs/routes/home-style-props-sizing.json +244 -0
  129. package/data/docs/routes/home-style-props-spacing.json +228 -0
  130. package/data/docs/routes/home-style-props-svg.json +96 -0
  131. package/data/docs/routes/home-style-props-tables.json +116 -0
  132. package/data/docs/routes/home-style-props-transforms.json +216 -0
  133. package/data/docs/routes/home-style-props-transitions.json +216 -0
  134. package/data/docs/routes/home-style-props-typography.json +536 -0
  135. package/data/docs/routes/home-style-props.json +33 -0
  136. package/data/docs/routes/home.json +32 -0
  137. package/data/docs/routes/hooks-usecopytoclipboard.json +76 -0
  138. package/data/docs/routes/hooks-usehotkeys.json +117 -0
  139. package/data/docs/routes/hooks.json +33 -0
  140. package/data/docs/routes/icons.json +32 -0
  141. package/data/docs/routes/patterns-fields-date-range-picker-field.json +393 -0
  142. package/data/docs/routes/patterns-fields-money-input-field.json +415 -0
  143. package/data/docs/routes/patterns-fields-multiline-text-input-field.json +404 -0
  144. package/data/docs/routes/patterns-fields-number-input-field.json +470 -0
  145. package/data/docs/routes/patterns-fields-password-input-field.json +319 -0
  146. package/data/docs/routes/patterns-fields-search-input-field.json +382 -0
  147. package/data/docs/routes/patterns-fields-text-input-field.json +404 -0
  148. package/data/docs/routes/patterns-fields.json +78 -0
  149. package/data/docs/routes/patterns.json +34 -0
  150. package/data/docs/search-index.json +1 -0
  151. package/data/docs/types/Accordion.json +12 -0
  152. package/data/docs/types/AccordionContent.json +286 -0
  153. package/data/docs/types/AccordionHeader.json +891 -0
  154. package/data/docs/types/AccordionHeaderRightContent.json +27 -0
  155. package/data/docs/types/AccordionItem.json +242 -0
  156. package/data/docs/types/AccordionRoot.json +162 -0
  157. package/data/docs/types/Alert.json +12 -0
  158. package/data/docs/types/AlertActions.json +11 -0
  159. package/data/docs/types/AlertDescription.json +118 -0
  160. package/data/docs/types/AlertDismissButton.json +937 -0
  161. package/data/docs/types/AlertRoot.json +42 -0
  162. package/data/docs/types/AlertTitle.json +118 -0
  163. package/data/docs/types/Avatar.json +125 -0
  164. package/data/docs/types/Badge.json +64 -0
  165. package/data/docs/types/Body.json +67 -0
  166. package/data/docs/types/Box.json +85 -0
  167. package/data/docs/types/Button.json +1015 -0
  168. package/data/docs/types/Calendar.json +565 -0
  169. package/data/docs/types/Caption.json +67 -0
  170. package/data/docs/types/Card.json +12 -0
  171. package/data/docs/types/CardContent.json +27 -0
  172. package/data/docs/types/CardHeader.json +27 -0
  173. package/data/docs/types/CardRoot.json +106 -0
  174. package/data/docs/types/Cell.json +227 -0
  175. package/data/docs/types/Checkbox.json +897 -0
  176. package/data/docs/types/Code.json +112 -0
  177. package/data/docs/types/CollapsibleMotionContent.json +35 -0
  178. package/data/docs/types/CollapsibleMotionRoot.json +99 -0
  179. package/data/docs/types/CollapsibleMotionTrigger.json +71 -0
  180. package/data/docs/types/Column.json +101 -0
  181. package/data/docs/types/ColumnGroup.json +101 -0
  182. package/data/docs/types/ColumnHeader.json +193 -0
  183. package/data/docs/types/ComboBoxListBox.json +751 -0
  184. package/data/docs/types/ComboBoxOption.json +672 -0
  185. package/data/docs/types/ComboBoxPopover.json +786 -0
  186. package/data/docs/types/ComboBoxRoot.json +747 -0
  187. package/data/docs/types/ComboBoxSection.json +277 -0
  188. package/data/docs/types/ComboBoxTrigger.json +70 -0
  189. package/data/docs/types/Content.json +33 -0
  190. package/data/docs/types/DataTable.json +596 -0
  191. package/data/docs/types/DataTableBody.json +223 -0
  192. package/data/docs/types/DataTableFooter.json +27 -0
  193. package/data/docs/types/DataTableHeader.json +269 -0
  194. package/data/docs/types/DataTableManager.json +11 -0
  195. package/data/docs/types/DataTableRoot.json +590 -0
  196. package/data/docs/types/DataTableTable.json +271 -0
  197. package/data/docs/types/DateInput.json +792 -0
  198. package/data/docs/types/DatePicker.json +700 -0
  199. package/data/docs/types/DateRangePicker.json +936 -0
  200. package/data/docs/types/DateRangePickerField.json +1047 -0
  201. package/data/docs/types/DefaultPage.json +12 -0
  202. package/data/docs/types/DefaultPageActions.json +27 -0
  203. package/data/docs/types/DefaultPageBackLink.json +213 -0
  204. package/data/docs/types/DefaultPageContent.json +27 -0
  205. package/data/docs/types/DefaultPageFooter.json +27 -0
  206. package/data/docs/types/DefaultPageHeader.json +27 -0
  207. package/data/docs/types/DefaultPageRoot.json +106 -0
  208. package/data/docs/types/DefaultPageSubtitle.json +27 -0
  209. package/data/docs/types/DefaultPageTabNav.json +28 -0
  210. package/data/docs/types/DefaultPageTitle.json +27 -0
  211. package/data/docs/types/DialogBody.json +27 -0
  212. package/data/docs/types/DialogCloseTrigger.json +939 -0
  213. package/data/docs/types/DialogContent.json +27 -0
  214. package/data/docs/types/DialogFooter.json +27 -0
  215. package/data/docs/types/DialogHeader.json +27 -0
  216. package/data/docs/types/DialogRoot.json +138 -0
  217. package/data/docs/types/DialogTitle.json +27 -0
  218. package/data/docs/types/DialogTrigger.json +80 -0
  219. package/data/docs/types/DraggableList.json +12 -0
  220. package/data/docs/types/DraggableListField.json +894 -0
  221. package/data/docs/types/DraggableListItem.json +574 -0
  222. package/data/docs/types/DraggableListRoot.json +745 -0
  223. package/data/docs/types/Drawer.json +12 -0
  224. package/data/docs/types/DrawerBody.json +27 -0
  225. package/data/docs/types/DrawerCloseTrigger.json +939 -0
  226. package/data/docs/types/DrawerContent.json +27 -0
  227. package/data/docs/types/DrawerFooter.json +27 -0
  228. package/data/docs/types/DrawerHeader.json +27 -0
  229. package/data/docs/types/DrawerRoot.json +142 -0
  230. package/data/docs/types/DrawerTitle.json +27 -0
  231. package/data/docs/types/DrawerTrigger.json +80 -0
  232. package/data/docs/types/FieldErrors.getBuiltInMessage.json +11 -0
  233. package/data/docs/types/FieldErrors.getCustomMessage.json +9 -0
  234. package/data/docs/types/FieldErrors.json +109 -0
  235. package/data/docs/types/Flex.json +238 -0
  236. package/data/docs/types/Footer.json +67 -0
  237. package/data/docs/types/FormFieldDescription.json +11 -0
  238. package/data/docs/types/FormFieldError.json +11 -0
  239. package/data/docs/types/FormFieldInfoBox.json +27 -0
  240. package/data/docs/types/FormFieldInput.json +11 -0
  241. package/data/docs/types/FormFieldLabel.json +11 -0
  242. package/data/docs/types/FormFieldRoot.json +148 -0
  243. package/data/docs/types/Grid.json +253 -0
  244. package/data/docs/types/GridProps.json +11 -0
  245. package/data/docs/types/Group.json +143 -0
  246. package/data/docs/types/Header.json +67 -0
  247. package/data/docs/types/Heading.json +109 -0
  248. package/data/docs/types/Icon.json +112 -0
  249. package/data/docs/types/IconButton.json +1019 -0
  250. package/data/docs/types/IconToggleButton.json +787 -0
  251. package/data/docs/types/Image.json +373 -0
  252. package/data/docs/types/Indicator.json +67 -0
  253. package/data/docs/types/InlineSvg.json +98 -0
  254. package/data/docs/types/Item.json +67 -0
  255. package/data/docs/types/Kbd.json +118 -0
  256. package/data/docs/types/Link.json +380 -0
  257. package/data/docs/types/List.json +12 -0
  258. package/data/docs/types/ListIndicator.json +70 -0
  259. package/data/docs/types/ListItem.json +70 -0
  260. package/data/docs/types/ListRoot.json +124 -0
  261. package/data/docs/types/LoadingSpinner.json +87 -0
  262. package/data/docs/types/LocalizedField.json +460 -0
  263. package/data/docs/types/LocalizedStringFormatter.json +9 -0
  264. package/data/docs/types/MakeElementFocusable.json +196 -0
  265. package/data/docs/types/MenuContent.json +111 -0
  266. package/data/docs/types/MenuItem.json +671 -0
  267. package/data/docs/types/MenuRoot.json +670 -0
  268. package/data/docs/types/MenuSection.json +364 -0
  269. package/data/docs/types/MenuSubmenu.json +111 -0
  270. package/data/docs/types/MenuSubmenuTrigger.json +67 -0
  271. package/data/docs/types/MenuTrigger.json +906 -0
  272. package/data/docs/types/ModalPage.json +12 -0
  273. package/data/docs/types/ModalPageActions.json +27 -0
  274. package/data/docs/types/ModalPageContent.json +27 -0
  275. package/data/docs/types/ModalPageFooter.json +27 -0
  276. package/data/docs/types/ModalPageHeader.json +27 -0
  277. package/data/docs/types/ModalPageRoot.json +87 -0
  278. package/data/docs/types/ModalPageSubtitle.json +27 -0
  279. package/data/docs/types/ModalPageTabNav.json +28 -0
  280. package/data/docs/types/ModalPageTitle.json +27 -0
  281. package/data/docs/types/ModalPageTopBar.json +57 -0
  282. package/data/docs/types/MoneyInput.isEmpty.json +40 -0
  283. package/data/docs/types/MoneyInput.json +282 -0
  284. package/data/docs/types/MoneyInputField.json +379 -0
  285. package/data/docs/types/MoneyInputFieldProps.json +9 -0
  286. package/data/docs/types/MultilineTextInput.json +1194 -0
  287. package/data/docs/types/MultilineTextInputField.json +1269 -0
  288. package/data/docs/types/MultilineTextInputFieldProps.json +9 -0
  289. package/data/docs/types/NimbusI18nProvider.json +42 -0
  290. package/data/docs/types/NimbusI18nProviderProps.json +9 -0
  291. package/data/docs/types/NimbusProvider.json +270 -0
  292. package/data/docs/types/NumberInput.json +952 -0
  293. package/data/docs/types/NumberInputField.json +1004 -0
  294. package/data/docs/types/NumberInputFieldProps.json +9 -0
  295. package/data/docs/types/PageContent.json +11 -0
  296. package/data/docs/types/PageContentColumn.json +99 -0
  297. package/data/docs/types/PageContentRoot.json +114 -0
  298. package/data/docs/types/Pagination.json +159 -0
  299. package/data/docs/types/PasswordInput.json +1120 -0
  300. package/data/docs/types/PasswordInputField.json +1216 -0
  301. package/data/docs/types/PasswordInputFieldProps.json +9 -0
  302. package/data/docs/types/ProgressBar.json +280 -0
  303. package/data/docs/types/RadioInputOption.json +550 -0
  304. package/data/docs/types/RadioInputRoot.json +514 -0
  305. package/data/docs/types/RangeCalendar.json +618 -0
  306. package/data/docs/types/RichTextInput.json +134 -0
  307. package/data/docs/types/Root.json +122 -0
  308. package/data/docs/types/Row.json +67 -0
  309. package/data/docs/types/ScopedSearchInput.isEmpty.json +40 -0
  310. package/data/docs/types/ScopedSearchInput.json +253 -0
  311. package/data/docs/types/ScrollArea.json +82 -0
  312. package/data/docs/types/SearchInput.json +1165 -0
  313. package/data/docs/types/SearchInputField.json +1240 -0
  314. package/data/docs/types/Select.json +12 -0
  315. package/data/docs/types/SelectOption.json +572 -0
  316. package/data/docs/types/SelectOptionGroup.json +215 -0
  317. package/data/docs/types/SelectOptions.json +693 -0
  318. package/data/docs/types/SelectRoot.json +926 -0
  319. package/data/docs/types/Separator.json +65 -0
  320. package/data/docs/types/SimpleGrid.json +291 -0
  321. package/data/docs/types/Spacer.json +27 -0
  322. package/data/docs/types/SpacerProps.json +9 -0
  323. package/data/docs/types/SplitButton.json +203 -0
  324. package/data/docs/types/Stack.json +144 -0
  325. package/data/docs/types/Steps.json +12 -0
  326. package/data/docs/types/StepsChangeDetails.json +9 -0
  327. package/data/docs/types/StepsCompletedContent.json +28 -0
  328. package/data/docs/types/StepsCompletedContentProps.json +9 -0
  329. package/data/docs/types/StepsContent.json +43 -0
  330. package/data/docs/types/StepsContentProps.json +9 -0
  331. package/data/docs/types/StepsDescription.json +28 -0
  332. package/data/docs/types/StepsDescriptionProps.json +9 -0
  333. package/data/docs/types/StepsIndicator.json +28 -0
  334. package/data/docs/types/StepsIndicatorProps.json +9 -0
  335. package/data/docs/types/StepsItem.json +43 -0
  336. package/data/docs/types/StepsItemProps.json +9 -0
  337. package/data/docs/types/StepsList.json +28 -0
  338. package/data/docs/types/StepsListProps.json +9 -0
  339. package/data/docs/types/StepsNextTrigger.json +62 -0
  340. package/data/docs/types/StepsNextTriggerProps.json +9 -0
  341. package/data/docs/types/StepsNumber.json +28 -0
  342. package/data/docs/types/StepsNumberProps.json +9 -0
  343. package/data/docs/types/StepsPrevTrigger.json +62 -0
  344. package/data/docs/types/StepsPrevTriggerProps.json +9 -0
  345. package/data/docs/types/StepsRoot.json +183 -0
  346. package/data/docs/types/StepsRootProps.json +11 -0
  347. package/data/docs/types/StepsSeparator.json +28 -0
  348. package/data/docs/types/StepsSeparatorProps.json +9 -0
  349. package/data/docs/types/StepsStatus.json +57 -0
  350. package/data/docs/types/StepsStatusProps.json +9 -0
  351. package/data/docs/types/StepsTitle.json +28 -0
  352. package/data/docs/types/StepsTitleProps.json +9 -0
  353. package/data/docs/types/StepsTrigger.json +47 -0
  354. package/data/docs/types/StepsTriggerProps.json +9 -0
  355. package/data/docs/types/Switch.json +371 -0
  356. package/data/docs/types/TabListProps.json +9 -0
  357. package/data/docs/types/TabNav.json +12 -0
  358. package/data/docs/types/TabNavItem.json +300 -0
  359. package/data/docs/types/TabNavItemProps.json +9 -0
  360. package/data/docs/types/TabNavProps.json +9 -0
  361. package/data/docs/types/TabNavRoot.json +80 -0
  362. package/data/docs/types/TabPanelProps.json +9 -0
  363. package/data/docs/types/TabPanelsProps.json +9 -0
  364. package/data/docs/types/TabProps.json +9 -0
  365. package/data/docs/types/Table.json +9 -0
  366. package/data/docs/types/TableBody.json +67 -0
  367. package/data/docs/types/TableBodyProps.json +9 -0
  368. package/data/docs/types/TableCaption.json +67 -0
  369. package/data/docs/types/TableCaptionProps.json +9 -0
  370. package/data/docs/types/TableCell.json +227 -0
  371. package/data/docs/types/TableCellProps.json +9 -0
  372. package/data/docs/types/TableColumn.json +101 -0
  373. package/data/docs/types/TableColumnGroup.json +101 -0
  374. package/data/docs/types/TableColumnGroupProps.json +9 -0
  375. package/data/docs/types/TableColumnHeader.json +193 -0
  376. package/data/docs/types/TableColumnHeaderProps.json +9 -0
  377. package/data/docs/types/TableColumnProps.json +9 -0
  378. package/data/docs/types/TableFooter.json +67 -0
  379. package/data/docs/types/TableFooterProps.json +9 -0
  380. package/data/docs/types/TableHeader.json +67 -0
  381. package/data/docs/types/TableHeaderProps.json +9 -0
  382. package/data/docs/types/TableRoot.json +365 -0
  383. package/data/docs/types/TableRootProps.json +12 -0
  384. package/data/docs/types/TableRow.json +67 -0
  385. package/data/docs/types/TableRowProps.json +9 -0
  386. package/data/docs/types/TableScrollArea.json +82 -0
  387. package/data/docs/types/TableScrollAreaProps.json +9 -0
  388. package/data/docs/types/Tabs.json +12 -0
  389. package/data/docs/types/TabsList.json +110 -0
  390. package/data/docs/types/TabsPanel.json +112 -0
  391. package/data/docs/types/TabsPanels.json +108 -0
  392. package/data/docs/types/TabsRoot.json +211 -0
  393. package/data/docs/types/TabsTab.json +174 -0
  394. package/data/docs/types/TagGroup.json +12 -0
  395. package/data/docs/types/TagGroupRoot.json +306 -0
  396. package/data/docs/types/TagGroupTag.json +595 -0
  397. package/data/docs/types/TagGroupTagList.json +166 -0
  398. package/data/docs/types/Text.json +119 -0
  399. package/data/docs/types/TextInput.json +1156 -0
  400. package/data/docs/types/TextInputField.json +1263 -0
  401. package/data/docs/types/TimeInput.json +752 -0
  402. package/data/docs/types/ToastAction.json +9 -0
  403. package/data/docs/types/ToastManagerApi.json +9 -0
  404. package/data/docs/types/ToastOptions.json +9 -0
  405. package/data/docs/types/ToastOutlet.json +12 -0
  406. package/data/docs/types/ToastPlacement.json +9 -0
  407. package/data/docs/types/ToastPromiseOptions.json +9 -0
  408. package/data/docs/types/ToastType.json +9 -0
  409. package/data/docs/types/ToastVariant.json +9 -0
  410. package/data/docs/types/ToggleButton.json +789 -0
  411. package/data/docs/types/ToggleButtonGroup.json +9 -0
  412. package/data/docs/types/ToggleButtonGroupButton.json +331 -0
  413. package/data/docs/types/ToggleButtonGroupRoot.json +269 -0
  414. package/data/docs/types/Toolbar.json +176 -0
  415. package/data/docs/types/Tooltip.json +12 -0
  416. package/data/docs/types/TooltipContent.json +372 -0
  417. package/data/docs/types/TooltipRoot.json +179 -0
  418. package/data/docs/types/Trigger.json +69 -0
  419. package/data/docs/types/VisuallyHidden.json +93 -0
  420. package/data/docs/types/__object.json +12 -0
  421. package/data/docs/types/filters.json +11 -0
  422. package/data/docs/types/manifest.json +278 -0
  423. package/data/docs/types/toast.json +234 -0
  424. package/data/docs/types/useColorMode.json +13 -0
  425. package/data/docs/types/useColorModeValue.json +13 -0
  426. package/data/docs/types/useColorScheme.json +12 -0
  427. package/data/docs/types/useLocalizedStringFormatter.json +14 -0
  428. package/data/icons.json +21940 -0
  429. package/data/tokens.json +40061 -0
  430. package/dist/index.js +2516 -17
  431. package/package.json +25 -6
  432. package/dist/data-loader.d.ts +0 -102
  433. package/dist/data-loader.js +0 -104
  434. package/dist/index.d.ts +0 -13
  435. package/dist/server.d.ts +0 -9
  436. package/dist/server.js +0 -22
  437. package/dist/server.spec.d.ts +0 -1
  438. package/dist/server.spec.js +0 -69
  439. package/dist/tools/list-components.d.ts +0 -9
  440. package/dist/tools/list-components.js +0 -42
  441. package/dist/types.d.ts +0 -28
  442. package/dist/types.js +0 -4
  443. package/src/data-loader.ts +0 -226
  444. package/src/index.ts +0 -29
  445. package/src/server.spec.ts +0 -86
  446. package/src/server.ts +0 -28
  447. package/src/tools/list-components.ts +0 -49
  448. package/src/types.ts +0 -31
  449. package/tsconfig.json +0 -14
  450. package/vitest.config.ts +0 -9
package/dist/index.js CHANGED
@@ -1,23 +1,2522 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Nimbus MCP Server — stdio entry point.
4
- *
5
- * Connects the MCP server to stdin/stdout so it can be used with any MCP
6
- * client (e.g. Claude Desktop, Claude Code) via the stdio transport.
7
- *
8
- * Usage:
9
- * node dist/index.js
10
- * # or via package bin:
11
- * nimbus-mcp
12
- */
2
+
3
+ // src/index.ts
13
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
14
- import { createServer } from "./server.js";
5
+
6
+ // src/server.ts
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+
9
+ // src/tools/get-component.ts
10
+ import { readdir } from "fs/promises";
11
+ import { resolve as resolve3 } from "path";
12
+ import { z } from "zod";
13
+
14
+ // src/data-loader.ts
15
+ import { readFile as readFile2 } from "fs/promises";
16
+ import { existsSync } from "fs";
17
+ import { resolve as resolve2, dirname as dirname2 } from "path";
18
+ import { fileURLToPath as fileURLToPath2 } from "url";
19
+
20
+ // src/processors/flatten-tokens.ts
21
+ import { readFile } from "fs/promises";
22
+ import { resolve, dirname } from "path";
23
+ import { fileURLToPath } from "url";
24
+ var __dirname = dirname(fileURLToPath(import.meta.url));
25
+ function normaliseValue(value) {
26
+ return value.trim().toLowerCase();
27
+ }
28
+ function reverseLookup(data, value) {
29
+ return data.reverseLookup[normaliseValue(value)] ?? [];
30
+ }
31
+
32
+ // src/data-loader.ts
33
+ var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
34
+ function findPackageRoot() {
35
+ let dir = __dirname2;
36
+ while (dir !== dirname2(dir)) {
37
+ if (existsSync(resolve2(dir, "package.json"))) {
38
+ return dir;
39
+ }
40
+ dir = dirname2(dir);
41
+ }
42
+ return __dirname2;
43
+ }
44
+ var PACKAGE_ROOT = findPackageRoot();
45
+ var DATA_DIR = resolve2(PACKAGE_ROOT, "data");
46
+ function getDataDir() {
47
+ return DATA_DIR;
48
+ }
49
+ async function readJson(filePath) {
50
+ const raw = await readFile2(filePath, "utf-8");
51
+ return JSON.parse(raw);
52
+ }
53
+ function lazyJson(relativePath) {
54
+ let cached;
55
+ return async () => {
56
+ if (cached === void 0) {
57
+ const fullPath = resolve2(getDataDir(), relativePath);
58
+ cached = await readJson(fullPath);
59
+ }
60
+ return cached;
61
+ };
62
+ }
63
+ var getRouteManifest = lazyJson(
64
+ "docs/route-manifest.json"
65
+ );
66
+ var routeDataCache = /* @__PURE__ */ new Map();
67
+ async function getRouteData(slug) {
68
+ const cached = routeDataCache.get(slug);
69
+ if (cached) return cached;
70
+ const fullPath = resolve2(getDataDir(), "docs/routes", `${slug}.json`);
71
+ const data = await readJson(fullPath);
72
+ routeDataCache.set(slug, data);
73
+ return data;
74
+ }
75
+ async function getTypeData(componentName) {
76
+ const fullPath = resolve2(getDataDir(), "docs/types", `${componentName}.json`);
77
+ return readJson(fullPath);
78
+ }
79
+ var getTypesIndex = lazyJson("docs/types.json");
80
+ var getSearchIndex = lazyJson(
81
+ "docs/search-index.json"
82
+ );
83
+ var getDocsManifest = lazyJson("docs/docs.json");
84
+ var getIconCatalog = lazyJson("icons.json");
85
+ var getFlatTokenData = lazyJson("tokens.json");
86
+
87
+ // src/utils/markdown.ts
88
+ function stripMarkdown(text) {
89
+ const codeBlocks = [];
90
+ const withPlaceholders = text.replace(
91
+ /^```[^\n]*\n([\s\S]*?)^```[ \t]*$/gm,
92
+ (_, content) => {
93
+ codeBlocks.push(content.trimEnd());
94
+ return `\uE000CODE${codeBlocks.length - 1}\uE000`;
95
+ }
96
+ );
97
+ const stripped = withPlaceholders.replace(/^---[\s\S]*?---\n?/, "").replace(/<[A-Z][^>]*\/>/g, "").replace(/<[A-Z][^>]*>[\s\S]*?<\/[A-Z][^>]*>/g, "").replace(/<[a-z][^>]*\/>/g, "").replace(/<\/?[a-z][^>]*>/g, "").replace(/#{1,6}\s/g, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/\*([^*]+)\*/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\n{3,}/g, "\n\n").trim();
98
+ return stripped.replace(
99
+ /\uE000CODE(\d+)\uE000/g,
100
+ (_, i) => codeBlocks[Number(i)]
101
+ );
102
+ }
103
+
104
+ // src/utils/relevance.ts
105
+ var WEIGHTS = { title: 8, description: 4, tags: 4, content: 1 };
106
+ function filterAndRankPreLowered(items, tokens, getLowered) {
107
+ if (items.length === 0 || tokens.length === 0) return items;
108
+ const scored = [];
109
+ const tokenCount = tokens.length;
110
+ if (tokenCount === 1) {
111
+ const t = tokens[0];
112
+ for (const item of items) {
113
+ const { title, description, tags, content } = getLowered(item);
114
+ let score = 0;
115
+ if (title.includes(t)) score += WEIGHTS.title;
116
+ if (description.includes(t)) score += WEIGHTS.description;
117
+ if (tags.includes(t)) score += WEIGHTS.tags;
118
+ if (content.includes(t)) score += WEIGHTS.content;
119
+ if (score > 0) scored.push({ item, score });
120
+ }
121
+ } else {
122
+ for (const item of items) {
123
+ const fields = getLowered(item);
124
+ const { title, description, tags, content, combined } = fields;
125
+ let allPresent = true;
126
+ for (let i = 0; i < tokenCount; i++) {
127
+ if (!combined.includes(tokens[i])) {
128
+ allPresent = false;
129
+ break;
130
+ }
131
+ }
132
+ if (!allPresent) continue;
133
+ let score = 0;
134
+ for (let i = 0; i < tokenCount; i++) {
135
+ const t = tokens[i];
136
+ if (title.includes(t)) score += WEIGHTS.title;
137
+ if (description.includes(t)) score += WEIGHTS.description;
138
+ if (tags.includes(t)) score += WEIGHTS.tags;
139
+ if (content.includes(t)) score += WEIGHTS.content;
140
+ }
141
+ scored.push({ item, score });
142
+ }
143
+ }
144
+ return scored.sort((a, b) => b.score - a.score).map(({ item }) => item);
145
+ }
146
+ function scorePreLowered(fields, tokens) {
147
+ let score = 0;
148
+ for (const t of tokens) {
149
+ if (fields.title.includes(t)) score += WEIGHTS.title;
150
+ if (fields.description.includes(t)) score += WEIGHTS.description;
151
+ if (fields.tags.includes(t)) score += WEIGHTS.tags;
152
+ if (fields.content.includes(t)) score += WEIGHTS.content;
153
+ }
154
+ return score;
155
+ }
156
+ function boundedLevenshtein(a, b, maxDist) {
157
+ if (Math.abs(a.length - b.length) > maxDist) return -1;
158
+ if (a === b) return 0;
159
+ if (a.length > b.length) [a, b] = [b, a];
160
+ const m = a.length;
161
+ const n = b.length;
162
+ let prev = new Array(m + 1);
163
+ let curr = new Array(m + 1);
164
+ for (let i = 0; i <= m; i++) prev[i] = i;
165
+ for (let j = 1; j <= n; j++) {
166
+ curr[0] = j;
167
+ let rowMin = j;
168
+ for (let i = 1; i <= m; i++) {
169
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
170
+ curr[i] = Math.min(prev[i] + 1, curr[i - 1] + 1, prev[i - 1] + cost);
171
+ if (curr[i] < rowMin) rowMin = curr[i];
172
+ }
173
+ if (rowMin > maxDist) return -1;
174
+ [prev, curr] = [curr, prev];
175
+ }
176
+ return prev[m] <= maxDist ? prev[m] : -1;
177
+ }
178
+ function fuzzyScorePreLowered(fields, tokens) {
179
+ let score = 0;
180
+ const FUZZY_WEIGHTS = {
181
+ title: WEIGHTS.title / 2,
182
+ description: WEIGHTS.description / 2,
183
+ tags: WEIGHTS.tags / 2,
184
+ content: WEIGHTS.content / 2
185
+ };
186
+ const fieldData = [
187
+ {
188
+ text: fields.title,
189
+ noSpaces: fields.titleNoSpaces ?? fields.title.replace(/\s+/g, ""),
190
+ words: fields.titleWords ?? fields.title.split(/\s+/).filter(Boolean),
191
+ weight: FUZZY_WEIGHTS.title
192
+ },
193
+ {
194
+ text: fields.description,
195
+ noSpaces: fields.descriptionNoSpaces ?? fields.description.replace(/\s+/g, ""),
196
+ words: fields.descriptionWords ?? fields.description.split(/\s+/).filter(Boolean),
197
+ weight: FUZZY_WEIGHTS.description
198
+ },
199
+ {
200
+ text: fields.tags,
201
+ noSpaces: fields.tagsNoSpaces ?? fields.tags.replace(/\s+/g, ""),
202
+ words: fields.tagsWords ?? fields.tags.split(/\s+/).filter(Boolean),
203
+ weight: FUZZY_WEIGHTS.tags
204
+ }
205
+ ];
206
+ for (const token of tokens) {
207
+ if (token.length < 3) continue;
208
+ const maxDist = token.length <= 4 ? 1 : token.length <= 7 ? 2 : 3;
209
+ for (const { text, noSpaces, words, weight } of fieldData) {
210
+ if (text.includes(token)) {
211
+ score += weight;
212
+ continue;
213
+ }
214
+ if (noSpaces.includes(token)) {
215
+ score += weight;
216
+ continue;
217
+ }
218
+ let matched = false;
219
+ for (const word of words) {
220
+ if (boundedLevenshtein(token, word, maxDist) >= 0) {
221
+ matched = true;
222
+ break;
223
+ }
224
+ if (token.startsWith(word) || word.startsWith(token)) {
225
+ matched = true;
226
+ break;
227
+ }
228
+ }
229
+ if (matched) score += weight;
230
+ }
231
+ }
232
+ return score;
233
+ }
234
+ function fuzzyResolveName(needle, candidates, getNames) {
235
+ if (needle.length < 2) return void 0;
236
+ const lower = needle.toLowerCase();
237
+ const maxDist = lower.length <= 4 ? 1 : lower.length <= 7 ? 2 : 3;
238
+ let bestItem;
239
+ let bestDist = maxDist + 1;
240
+ let bestLen = Infinity;
241
+ for (const item of candidates) {
242
+ for (const name of getNames(item)) {
243
+ const nameLower = name.toLowerCase();
244
+ const dist = boundedLevenshtein(lower, nameLower, maxDist);
245
+ if (dist >= 0 && (dist < bestDist || dist === bestDist && nameLower.length < bestLen)) {
246
+ bestDist = dist;
247
+ bestLen = nameLower.length;
248
+ bestItem = item;
249
+ }
250
+ }
251
+ }
252
+ return bestItem;
253
+ }
254
+
255
+ // src/tools/get-component.ts
256
+ var SECTION_KEYS = [
257
+ "overview",
258
+ "guidelines",
259
+ "implementation",
260
+ "accessibility",
261
+ "props"
262
+ ];
263
+ var VIEW_KEY_MAP = {
264
+ overview: "overview",
265
+ guidelines: "guidelines",
266
+ implementation: "dev",
267
+ accessibility: "a11y"
268
+ };
269
+ var INHERITED_PARENT_NAMES = /* @__PURE__ */ new Set([
270
+ // Low-level HTML / DOM
271
+ "HTMLAttributes",
272
+ "DOMAttributes",
273
+ "ButtonHTMLAttributes",
274
+ "GlobalDOMEvents",
275
+ "GlobalDOMAttributes",
276
+ "AriaAttributes",
277
+ "HtmlProps",
278
+ // Chakra system internals
279
+ "SystemProperties",
280
+ "Conditions"
281
+ ]);
282
+ var EXCLUDED_PROP_NAMES = /* @__PURE__ */ new Set(["key"]);
283
+ function filterProps(typeData) {
284
+ return Object.values(typeData.props).filter(
285
+ (p) => !EXCLUDED_PROP_NAMES.has(p.name) && (!p.parent || !INHERITED_PARENT_NAMES.has(p.parent.name))
286
+ ).map((p) => {
287
+ const prop = {
288
+ name: p.name,
289
+ type: p.type.name,
290
+ required: p.required,
291
+ description: p.description
292
+ };
293
+ if (p.defaultValue) prop.defaultValue = p.defaultValue.value;
294
+ return prop;
295
+ });
296
+ }
297
+ var resolveCatalogCache;
298
+ var resolveCatalogRoutesRef;
299
+ var topLevelNamesCache;
300
+ var topLevelNamesRoutesRef;
301
+ async function aggregateSubComponentProps(exportName) {
302
+ const typesDir = resolve3(getDataDir(), "docs/types");
303
+ let files;
304
+ try {
305
+ files = await readdir(typesDir);
306
+ } catch {
307
+ return [];
308
+ }
309
+ const manifest = await getRouteManifest();
310
+ if (!topLevelNamesCache || topLevelNamesRoutesRef !== manifest.routes) {
311
+ topLevelNamesCache = new Set(
312
+ manifest.routes.filter((r) => CATALOG_CATEGORIES.has(r.category)).map((r) => (r.exportName ?? r.title).toLowerCase())
313
+ );
314
+ topLevelNamesRoutesRef = manifest.routes;
315
+ }
316
+ const topLevelNames = topLevelNamesCache;
317
+ const prefix = exportName.toLowerCase();
318
+ const subFiles = files.filter((f) => {
319
+ const base = f.replace(/\.json$/, "");
320
+ const baseLower = base.toLowerCase();
321
+ return f.endsWith(".json") && baseLower.startsWith(prefix) && baseLower !== prefix && // exclude the top-level file itself
322
+ !base.includes(".") && // exclude method exports (e.g. FieldErrors.getBuiltInMessage)
323
+ !base.endsWith("Props") && // exclude type-only duplicates (e.g. StepsRootProps)
324
+ !topLevelNames.has(baseLower);
325
+ });
326
+ const settled = await Promise.allSettled(
327
+ subFiles.map(async (file) => {
328
+ const subName = file.replace(/\.json$/, "");
329
+ const typeData = await getTypeData(subName);
330
+ return filterProps(typeData).map((p) => ({
331
+ ...p,
332
+ subComponent: subName
333
+ }));
334
+ })
335
+ );
336
+ return settled.filter((r) => r.status === "fulfilled").flatMap((r) => r.value);
337
+ }
338
+ var CATALOG_CATEGORIES = /* @__PURE__ */ new Set(["Components", "Patterns"]);
339
+ async function resolveComponent(name) {
340
+ const manifest = await getRouteManifest();
341
+ const needle = name.toLowerCase();
342
+ if (!resolveCatalogCache || resolveCatalogRoutesRef !== manifest.routes) {
343
+ resolveCatalogCache = manifest.routes.filter(
344
+ (r) => CATALOG_CATEGORIES.has(r.category) && r.menu.length === 3
345
+ );
346
+ resolveCatalogRoutesRef = manifest.routes;
347
+ }
348
+ const catalog = resolveCatalogCache;
349
+ const exact = catalog.find((r) => {
350
+ if (r.exportName?.toLowerCase() === needle) return true;
351
+ if (r.title.toLowerCase() === needle) return true;
352
+ const idName = r.id.replace(/^(Components|Patterns)-/, "");
353
+ return idName.toLowerCase() === needle;
354
+ });
355
+ if (exact) return exact;
356
+ return fuzzyResolveName(name, catalog, (r) => {
357
+ const names = [r.title];
358
+ if (r.exportName) names.push(r.exportName);
359
+ return names;
360
+ });
361
+ }
362
+ function pathToSlug(path) {
363
+ return path.replace(/^\//, "").replace(/\//g, "-");
364
+ }
365
+ function buildMetadataResponse(entry, availableSections) {
366
+ const meta = {
367
+ name: entry.title,
368
+ description: entry.description,
369
+ path: entry.path,
370
+ sections: availableSections
371
+ };
372
+ if (entry.exportName) meta.exportName = entry.exportName;
373
+ const subcategory = entry.menu[1];
374
+ if (subcategory) meta.subcategory = subcategory;
375
+ if (entry.tags.length > 0) meta.tags = entry.tags;
376
+ return meta;
377
+ }
378
+ function registerGetComponent(server) {
379
+ server.registerTool(
380
+ "get_component",
381
+ {
382
+ title: "Get Component",
383
+ description: "Returns detailed information about a Nimbus component or pattern. With name only: returns metadata and available sections. With name + section: returns section content (overview, guidelines, implementation, accessibility, props).",
384
+ inputSchema: {
385
+ name: z.string().describe(
386
+ 'Component or pattern name, e.g. "Button", "TextInput", "MoneyInputField". Case-insensitive.'
387
+ ),
388
+ section: z.enum(SECTION_KEYS).optional().describe(
389
+ "Section to retrieve. Omit to get metadata + section list."
390
+ )
391
+ }
392
+ },
393
+ async ({ name, section }) => {
394
+ try {
395
+ const entry = await resolveComponent(name);
396
+ if (!entry) {
397
+ return {
398
+ content: [
399
+ {
400
+ type: "text",
401
+ text: `Component "${name}" not found. Use list_components to see available components.`
402
+ }
403
+ ],
404
+ isError: true
405
+ };
406
+ }
407
+ const slug = pathToSlug(entry.path);
408
+ const routeData = await getRouteData(slug);
409
+ const viewSections = Object.keys(routeData.views ?? {}).map((key) => {
410
+ const canonical = Object.entries(VIEW_KEY_MAP).find(
411
+ ([, v]) => v === key
412
+ );
413
+ return canonical ? canonical[0] : key;
414
+ });
415
+ const availableSections = [...viewSections, "props"];
416
+ if (!section) {
417
+ const metadata = buildMetadataResponse(entry, availableSections);
418
+ return {
419
+ content: [
420
+ {
421
+ type: "text",
422
+ text: JSON.stringify(metadata)
423
+ }
424
+ ]
425
+ };
426
+ }
427
+ if (section === "props") {
428
+ const exportName = entry.exportName ?? entry.title;
429
+ try {
430
+ const typeData = await getTypeData(exportName);
431
+ let filtered = filterProps(typeData);
432
+ if (filtered.length === 0) {
433
+ filtered = await aggregateSubComponentProps(exportName);
434
+ }
435
+ return {
436
+ content: [
437
+ {
438
+ type: "text",
439
+ text: JSON.stringify({
440
+ component: exportName,
441
+ propCount: filtered.length,
442
+ props: filtered
443
+ })
444
+ }
445
+ ]
446
+ };
447
+ } catch {
448
+ return {
449
+ content: [
450
+ {
451
+ type: "text",
452
+ text: `Type data not available for "${exportName}".`
453
+ }
454
+ ],
455
+ isError: true
456
+ };
457
+ }
458
+ }
459
+ const viewKey = VIEW_KEY_MAP[section];
460
+ if (!viewKey) {
461
+ return {
462
+ content: [
463
+ {
464
+ type: "text",
465
+ text: `Unknown section "${section}". Available: ${availableSections.join(", ")}`
466
+ }
467
+ ],
468
+ isError: true
469
+ };
470
+ }
471
+ const view = routeData.views?.[viewKey];
472
+ if (!view) {
473
+ return {
474
+ content: [
475
+ {
476
+ type: "text",
477
+ text: `Section "${section}" is not available for "${entry.title}". Available: ${availableSections.join(", ")}`
478
+ }
479
+ ],
480
+ isError: true
481
+ };
482
+ }
483
+ return {
484
+ content: [
485
+ {
486
+ type: "text",
487
+ text: stripMarkdown(view.mdx)
488
+ }
489
+ ]
490
+ };
491
+ } catch {
492
+ return {
493
+ content: [
494
+ {
495
+ type: "text",
496
+ text: "Component data is not available in this environment."
497
+ }
498
+ ],
499
+ isError: true
500
+ };
501
+ }
502
+ }
503
+ );
504
+ }
505
+
506
+ // src/tools/get-tokens.ts
507
+ import { z as z2 } from "zod";
508
+ var LARGE_CATEGORY_THRESHOLD = 55;
509
+ var DEFAULT_PAGE_SIZE = 20;
510
+ var CATEGORY_PRIORITY = [
511
+ "color",
512
+ "colorPalettes",
513
+ "spacing",
514
+ "fontSize",
515
+ "fontWeight",
516
+ "lineHeight",
517
+ "borderRadius",
518
+ "shadow",
519
+ "size",
520
+ "borderWidth",
521
+ "border",
522
+ "zIndex",
523
+ "opacity",
524
+ "textStyle"
525
+ ];
526
+ function listCategories(data, virtualCategories = []) {
527
+ const priorityIndex = new Map(CATEGORY_PRIORITY.map((c, i) => [c, i]));
528
+ return Object.entries(data.byCategory).map(([category, tokens]) => ({ category, count: tokens.length })).concat(virtualCategories).sort((a, b) => {
529
+ const pa = priorityIndex.get(a.category) ?? CATEGORY_PRIORITY.length;
530
+ const pb = priorityIndex.get(b.category) ?? CATEGORY_PRIORITY.length;
531
+ if (pa !== pb) return pa - pb;
532
+ return a.category.localeCompare(b.category);
533
+ });
534
+ }
535
+ function findCategoryKey(data, category) {
536
+ const needle = category.toLowerCase();
537
+ return Object.keys(data.byCategory).find((k) => k.toLowerCase() === needle);
538
+ }
539
+ var PALETTE_GROUP_ORDER = [
540
+ "semantic-palettes",
541
+ "brand-palettes",
542
+ "system-palettes",
543
+ "blacks-and-whites"
544
+ ];
545
+ function isExcludedAlphaPalette(token) {
546
+ return token.path[2]?.endsWith("Alpha") === true && token.path[1] !== "blacks-and-whites";
547
+ }
548
+ function extractPalettes(tokens) {
549
+ const groups = {};
550
+ for (const token of tokens) {
551
+ const group = token.path[1];
552
+ const palette = token.path[2];
553
+ const step = token.path[3];
554
+ if (!group || !palette || step !== "9" || isExcludedAlphaPalette(token))
555
+ continue;
556
+ if (!groups[group]) groups[group] = /* @__PURE__ */ new Map();
557
+ groups[group].set(palette, { name: palette, solid: token.value });
558
+ }
559
+ const toSorted = (group) => [...groups[group]?.values() ?? []].sort(
560
+ (a, b) => a.name.localeCompare(b.name)
561
+ );
562
+ return Object.fromEntries(
563
+ PALETTE_GROUP_ORDER.map((group) => [group, toSorted(group)])
564
+ );
565
+ }
566
+ var cachedPalettes;
567
+ function getCachedPalettes(colorTokens) {
568
+ if (!cachedPalettes) {
569
+ cachedPalettes = extractPalettes(colorTokens);
570
+ }
571
+ return cachedPalettes;
572
+ }
573
+ function toResponseTokens(tokens) {
574
+ return tokens.map(({ name, value }) => ({ name, value }));
575
+ }
576
+ function buildCategoryResponse(matchKey, tokens, offset, limit) {
577
+ const isLarge = tokens.length > LARGE_CATEGORY_THRESHOLD;
578
+ const pageSize = limit ?? (isLarge ? DEFAULT_PAGE_SIZE : void 0);
579
+ const page = pageSize ? tokens.slice(offset, offset + pageSize) : tokens.slice(offset);
580
+ const response = {
581
+ category: matchKey,
582
+ total: tokens.length,
583
+ showing: page.length,
584
+ tokens: toResponseTokens(page)
585
+ };
586
+ const nextOffset = offset + page.length;
587
+ if (nextOffset < tokens.length) {
588
+ response.hint = `Use \`offset: ${nextOffset}\` to retrieve more, or \`limit: ${tokens.length}\` to retrieve all`;
589
+ }
590
+ return response;
591
+ }
592
+ function registerGetTokens(server) {
593
+ server.registerTool(
594
+ "get_tokens",
595
+ {
596
+ title: "Get Tokens",
597
+ description: 'Returns Nimbus design tokens. No params: lists all categories with counts. With category: returns tokens in that category (large categories are paginated by default). With value: reverse-lookup to find which tokens resolve to that value (e.g. "16px" \u2192 spacing.400).',
598
+ inputSchema: {
599
+ category: z2.string().optional().describe(
600
+ 'Token category to retrieve, e.g. "spacing", "color", "fontSize". Use "colorPalettes" to list available palette names for the colorPalette prop. Case-insensitive.'
601
+ ),
602
+ value: z2.string().optional().describe(
603
+ 'Reverse-lookup: find tokens whose resolved value matches this string, e.g. "16px" or "#0969DA". Case-insensitive.'
604
+ ),
605
+ offset: z2.number().int().min(0).default(0).describe(
606
+ "Starting index for paginated results. Only applies when category is provided. Omit or pass 0 for the first page."
607
+ ),
608
+ limit: z2.number().int().positive().optional().describe(
609
+ `Maximum number of tokens to return per page. Only applies when category is provided. Defaults to all for small categories, ${DEFAULT_PAGE_SIZE} for large categories (> ${LARGE_CATEGORY_THRESHOLD} tokens).`
610
+ )
611
+ }
612
+ },
613
+ async ({ category, value, offset, limit }) => {
614
+ try {
615
+ const data = await getFlatTokenData();
616
+ if (value !== void 0) {
617
+ const matches = reverseLookup(data, value);
618
+ if (matches.length === 0) {
619
+ return {
620
+ content: [
621
+ {
622
+ type: "text",
623
+ text: `No tokens found for value "${value}".`
624
+ }
625
+ ]
626
+ };
627
+ }
628
+ const payload2 = {
629
+ value,
630
+ tokens: matches
631
+ };
632
+ return {
633
+ content: [{ type: "text", text: JSON.stringify(payload2) }]
634
+ };
635
+ }
636
+ if (category !== void 0 && category.toLowerCase() === "colorpalettes") {
637
+ const colorTokens2 = data.byCategory["color"];
638
+ if (!colorTokens2) {
639
+ return {
640
+ content: [
641
+ {
642
+ type: "text",
643
+ text: "No color tokens available."
644
+ }
645
+ ],
646
+ isError: true
647
+ };
648
+ }
649
+ const palettes = getCachedPalettes(colorTokens2);
650
+ return {
651
+ content: [
652
+ { type: "text", text: JSON.stringify(palettes) }
653
+ ]
654
+ };
655
+ }
656
+ if (category !== void 0) {
657
+ const matchKey = findCategoryKey(data, category);
658
+ if (!matchKey) {
659
+ const available = Object.keys(data.byCategory).sort().join(", ");
660
+ return {
661
+ content: [
662
+ {
663
+ type: "text",
664
+ text: `Category "${category}" not found. Available categories: ${available}`
665
+ }
666
+ ],
667
+ isError: true
668
+ };
669
+ }
670
+ let tokens = data.byCategory[matchKey];
671
+ if (matchKey === "color") {
672
+ tokens = tokens.filter((t) => !isExcludedAlphaPalette(t));
673
+ }
674
+ const payload2 = buildCategoryResponse(
675
+ matchKey,
676
+ tokens,
677
+ offset,
678
+ limit
679
+ );
680
+ return {
681
+ content: [{ type: "text", text: JSON.stringify(payload2) }]
682
+ };
683
+ }
684
+ const virtualCategories = [];
685
+ const colorTokens = data.byCategory["color"];
686
+ if (colorTokens) {
687
+ const palettes = getCachedPalettes(colorTokens);
688
+ const paletteCount = Object.values(palettes).reduce(
689
+ (sum, group) => sum + group.length,
690
+ 0
691
+ );
692
+ virtualCategories.push({
693
+ category: "colorPalettes",
694
+ count: paletteCount
695
+ });
696
+ }
697
+ const payload = listCategories(data, virtualCategories);
698
+ return {
699
+ content: [{ type: "text", text: JSON.stringify(payload) }]
700
+ };
701
+ } catch {
702
+ return {
703
+ content: [
704
+ {
705
+ type: "text",
706
+ text: "Token data is not available in this environment."
707
+ }
708
+ ],
709
+ isError: true
710
+ };
711
+ }
712
+ }
713
+ );
714
+ }
715
+
716
+ // src/tools/list-components.ts
717
+ import { z as z3 } from "zod";
718
+ function toSummary(route) {
719
+ const summary = {
720
+ title: route.title,
721
+ description: route.description,
722
+ path: route.path
723
+ };
724
+ if (route.exportName) summary.exportName = route.exportName;
725
+ const subcategory = route.menu[1];
726
+ if (subcategory) summary.subcategory = subcategory;
727
+ if (route.tags.length > 0) summary.tags = route.tags;
728
+ return summary;
729
+ }
730
+ function toLowered(r) {
731
+ const title = r.title.toLowerCase();
732
+ const description = r.description.toLowerCase();
733
+ const tags = [...r.tags, r.exportName ?? ""].join(" ").toLowerCase();
734
+ return {
735
+ title,
736
+ description,
737
+ tags,
738
+ content: "",
739
+ combined: title + " " + description + " " + tags
740
+ };
741
+ }
742
+ function registerListComponents(server) {
743
+ server.registerTool(
744
+ "list_components",
745
+ {
746
+ title: "List Components",
747
+ description: "Returns Nimbus components. Optionally filter by subcategory or fuzzy-search by name, description, or tags.",
748
+ inputSchema: {
749
+ category: z3.string().optional().describe(
750
+ 'Filter by subcategory, e.g. "Inputs", "Buttons", "Navigation". Case-insensitive.'
751
+ ),
752
+ query: z3.string().optional().describe(
753
+ "Fuzzy search query over component name, description, and tags."
754
+ )
755
+ }
756
+ },
757
+ async ({ category, query }) => {
758
+ try {
759
+ const manifest = await getRouteManifest();
760
+ let routes = manifest.routes.filter(
761
+ (r) => r.category === "Components" && r.menu.length === 3
762
+ );
763
+ if (category) {
764
+ const needle = category.toLowerCase();
765
+ routes = routes.filter((r) => r.menu[1]?.toLowerCase() === needle);
766
+ }
767
+ if (query) {
768
+ const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
769
+ const loweredMap = /* @__PURE__ */ new Map();
770
+ for (const r of routes) {
771
+ loweredMap.set(r, toLowered(r));
772
+ }
773
+ const exactMatches = filterAndRankPreLowered(
774
+ routes,
775
+ tokens,
776
+ (r) => loweredMap.get(r)
777
+ );
778
+ if (exactMatches.length > 0) {
779
+ routes = exactMatches;
780
+ } else {
781
+ const fuzzyScored = [];
782
+ for (const r of routes) {
783
+ const score = fuzzyScorePreLowered(loweredMap.get(r), tokens);
784
+ if (score > 0) {
785
+ fuzzyScored.push({ route: r, score });
786
+ }
787
+ }
788
+ fuzzyScored.sort((a, b) => b.score - a.score);
789
+ routes = fuzzyScored.map(({ route }) => route);
790
+ }
791
+ }
792
+ const summaries = routes.map(toSummary);
793
+ return {
794
+ content: [
795
+ {
796
+ type: "text",
797
+ text: summaries.length > 0 ? JSON.stringify(summaries) : "No components found."
798
+ }
799
+ ]
800
+ };
801
+ } catch {
802
+ return {
803
+ content: [
804
+ {
805
+ type: "text",
806
+ text: "Component data is not available in this environment."
807
+ }
808
+ ],
809
+ isError: true
810
+ };
811
+ }
812
+ }
813
+ );
814
+ }
815
+
816
+ // src/tools/search-docs.ts
817
+ import { z as z4 } from "zod";
818
+ var MAX_RESULTS = 10;
819
+ function deriveToolHint(route) {
820
+ if (route.includes("design-tokens")) return "get_tokens";
821
+ if (route.startsWith("components/") || route.startsWith("patterns/"))
822
+ return "get_component";
823
+ if (route.startsWith("icons")) return "search_icons";
824
+ return void 0;
825
+ }
826
+ var SNIPPET_LENGTH = 200;
827
+ var SNIPPET_LEAD = 80;
828
+ var PHASE2_CANDIDATE_LIMIT = 30;
829
+ var MIN_CANDIDATES = 10;
830
+ var loweredFieldsCache;
831
+ var loweredFieldsIndexRef;
832
+ function getLoweredFields(index) {
833
+ if (loweredFieldsCache && loweredFieldsIndexRef === index)
834
+ return loweredFieldsCache;
835
+ const map = /* @__PURE__ */ new Map();
836
+ for (const entry of index) {
837
+ if (entry._lower) {
838
+ map.set(entry, entry._lower);
839
+ } else {
840
+ const title = entry.title.toLowerCase();
841
+ const description = entry.description.toLowerCase();
842
+ const tags = entry.tags.join(" ").toLowerCase();
843
+ const content = entry.content?.toLowerCase() ?? "";
844
+ map.set(entry, {
845
+ title,
846
+ description,
847
+ tags,
848
+ content,
849
+ combined: title + " " + description + " " + tags + " " + content,
850
+ titleNoSpaces: title.replace(/\s+/g, ""),
851
+ descriptionNoSpaces: description.replace(/\s+/g, ""),
852
+ tagsNoSpaces: tags.replace(/\s+/g, ""),
853
+ titleWords: title.split(/\s+/).filter(Boolean),
854
+ descriptionWords: description.split(/\s+/).filter(Boolean),
855
+ tagsWords: tags.split(/\s+/).filter(Boolean)
856
+ });
857
+ }
858
+ }
859
+ loweredFieldsCache = map;
860
+ loweredFieldsIndexRef = index;
861
+ return map;
862
+ }
863
+ function extractSnippet(content, tokens) {
864
+ const lower = content.toLowerCase();
865
+ let bestIndex = -1;
866
+ for (const token of tokens) {
867
+ const idx = lower.indexOf(token);
868
+ if (idx !== -1 && (bestIndex === -1 || idx < bestIndex)) {
869
+ bestIndex = idx;
870
+ }
871
+ }
872
+ if (bestIndex === -1) {
873
+ return content.slice(0, SNIPPET_LENGTH).trim() + (content.length > SNIPPET_LENGTH ? "\u2026" : "");
874
+ }
875
+ const start = Math.max(0, bestIndex - SNIPPET_LEAD);
876
+ const end = Math.min(content.length, start + SNIPPET_LENGTH);
877
+ let snippet = content.slice(start, end).trim();
878
+ if (start > 0) snippet = "\u2026" + snippet;
879
+ if (end < content.length) snippet = snippet + "\u2026";
880
+ return snippet;
881
+ }
882
+ function routeToSlug(route) {
883
+ return route.replace(/\//g, "-");
884
+ }
885
+ var viewContentCache = /* @__PURE__ */ new WeakMap();
886
+ function getCachedViewContent(viewObj) {
887
+ let cached = viewContentCache.get(viewObj);
888
+ if (!cached) {
889
+ const stripped = stripMarkdown(viewObj.mdx);
890
+ cached = { stripped, lower: stripped.toLowerCase() };
891
+ viewContentCache.set(viewObj, cached);
892
+ }
893
+ return cached;
894
+ }
895
+ function findCandidates(index, query, tokens, loweredMap) {
896
+ const exactMatches = filterAndRankPreLowered(
897
+ index,
898
+ tokens,
899
+ (entry) => loweredMap.get(entry)
900
+ );
901
+ if (exactMatches.length >= MIN_CANDIDATES) {
902
+ return { matched: exactMatches, expanded: [] };
903
+ }
904
+ const seen = new Set(exactMatches.map((e) => e.id));
905
+ const partialScored = [];
906
+ for (const entry of index) {
907
+ if (seen.has(entry.id)) continue;
908
+ const fields = loweredMap.get(entry);
909
+ const score = scorePreLowered(fields, tokens);
910
+ if (score > 0) {
911
+ partialScored.push({ entry, score });
912
+ }
913
+ }
914
+ partialScored.sort((a, b) => b.score - a.score);
915
+ const matched = [...exactMatches];
916
+ for (const { entry } of partialScored) {
917
+ seen.add(entry.id);
918
+ matched.push(entry);
919
+ }
920
+ if (matched.length < MIN_CANDIDATES) {
921
+ const fuzzyScored = [];
922
+ for (const entry of index) {
923
+ if (seen.has(entry.id)) continue;
924
+ const fields = loweredMap.get(entry);
925
+ const score = fuzzyScorePreLowered(fields, tokens);
926
+ if (score > 0) {
927
+ fuzzyScored.push({ entry, score });
928
+ }
929
+ }
930
+ fuzzyScored.sort((a, b) => b.score - a.score);
931
+ for (const { entry } of fuzzyScored) {
932
+ seen.add(entry.id);
933
+ matched.push(entry);
934
+ }
935
+ }
936
+ const expanded = [];
937
+ if (matched.length < MIN_CANDIDATES) {
938
+ for (const entry of index) {
939
+ if (!seen.has(entry.id) && entry.tags.includes("component")) {
940
+ seen.add(entry.id);
941
+ expanded.push(entry);
942
+ }
943
+ }
944
+ }
945
+ return { matched, expanded };
946
+ }
947
+ var routeViewsCache = /* @__PURE__ */ new Map();
948
+ async function getRouteViews(route) {
949
+ const slug = routeToSlug(route);
950
+ const cached = routeViewsCache.get(slug);
951
+ if (cached) return cached;
952
+ let routeData;
953
+ try {
954
+ routeData = await getRouteData(slug);
955
+ } catch {
956
+ const empty = { views: [], combinedLower: "" };
957
+ routeViewsCache.set(slug, empty);
958
+ return empty;
959
+ }
960
+ const MATCH_LIMIT = 2048;
961
+ const rawViews = [];
962
+ if (routeData.views) {
963
+ for (const [key, view] of Object.entries(routeData.views)) {
964
+ if (view.mdx) {
965
+ const { stripped, lower } = getCachedViewContent(view);
966
+ rawViews.push({
967
+ key,
968
+ content: stripped,
969
+ lower,
970
+ matchLower: lower.length > MATCH_LIMIT ? lower.slice(0, MATCH_LIMIT) : lower
971
+ });
972
+ }
973
+ }
974
+ } else if (routeData.mdx) {
975
+ const { stripped, lower } = getCachedViewContent({ mdx: routeData.mdx });
976
+ rawViews.push({
977
+ key: "overview",
978
+ content: stripped,
979
+ lower,
980
+ matchLower: lower.length > MATCH_LIMIT ? lower.slice(0, MATCH_LIMIT) : lower
981
+ });
982
+ }
983
+ rawViews.sort((a, b) => a.matchLower.length - b.matchLower.length);
984
+ const views = rawViews;
985
+ const result = {
986
+ views,
987
+ combinedLower: views.map((v) => v.lower.slice(0, MATCH_LIMIT)).join(" ")
988
+ };
989
+ routeViewsCache.set(slug, result);
990
+ return result;
991
+ }
992
+ function searchRouteViewsSync(route, tokens) {
993
+ const slug = routeToSlug(route);
994
+ const cached = routeViewsCache.get(slug);
995
+ if (!cached) return null;
996
+ const { views } = cached;
997
+ if (views.length === 0) return null;
998
+ const tokenCount = tokens.length;
999
+ let bestView = null;
1000
+ let bestHits = 0;
1001
+ for (const view of views) {
1002
+ let hits = 0;
1003
+ for (let i = 0; i < tokenCount; i++) {
1004
+ if (view.matchLower.includes(tokens[i])) hits++;
1005
+ }
1006
+ if (hits === tokenCount) {
1007
+ return { viewKey: view.key, content: view.content };
1008
+ }
1009
+ if (hits > bestHits) {
1010
+ bestHits = hits;
1011
+ bestView = view;
1012
+ }
1013
+ }
1014
+ return bestView && bestHits > 0 ? { viewKey: bestView.key, content: bestView.content } : null;
1015
+ }
1016
+ async function warmAndSearchViews(candidates, tokens) {
1017
+ await Promise.all(candidates.map((e) => getRouteViews(e.route)));
1018
+ const results = /* @__PURE__ */ new Map();
1019
+ for (const entry of candidates) {
1020
+ results.set(entry.id, searchRouteViewsSync(entry.route, tokens));
1021
+ }
1022
+ return results;
1023
+ }
1024
+ function registerSearchDocs(server) {
1025
+ server.registerTool(
1026
+ "search_docs",
1027
+ {
1028
+ title: "Search Docs",
1029
+ description: "Search all Nimbus docs (components, patterns, hooks, icons, tokens) including guidelines and accessibility views. Returns matching pages with content snippets. Props are not searchable here \u2014 use get_component with section='props' for prop details. Results include a toolHint field indicating which tool to call for deeper info (e.g. get_component, get_tokens, search_icons).",
1030
+ inputSchema: {
1031
+ query: z4.string().describe(
1032
+ 'Search query to find relevant documentation pages. e.g. "form validation", "color tokens", "accessibility", "onChange".'
1033
+ )
1034
+ }
1035
+ },
1036
+ async ({ query }) => {
1037
+ try {
1038
+ const index = await getSearchIndex();
1039
+ const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
1040
+ const loweredMap = getLoweredFields(index);
1041
+ const { matched, expanded } = findCandidates(
1042
+ index,
1043
+ query,
1044
+ tokens,
1045
+ loweredMap
1046
+ );
1047
+ const matchedCapped = matched.slice(0, PHASE2_CANDIDATE_LIMIT);
1048
+ const expandedCapped = expanded.slice(
1049
+ 0,
1050
+ Math.max(0, PHASE2_CANDIDATE_LIMIT - matchedCapped.length)
1051
+ );
1052
+ const allCandidates = [...matchedCapped, ...expandedCapped];
1053
+ const matchedIds = new Set(matched.map((e) => e.id));
1054
+ const phase1Scores = /* @__PURE__ */ new Map();
1055
+ for (const entry of allCandidates) {
1056
+ phase1Scores.set(
1057
+ entry.id,
1058
+ scorePreLowered(loweredMap.get(entry), tokens)
1059
+ );
1060
+ }
1061
+ const viewResults = await warmAndSearchViews(allCandidates, tokens);
1062
+ const loaded = allCandidates.map((entry) => ({
1063
+ entry,
1064
+ viewMatch: viewResults.get(entry.id) ?? null,
1065
+ wasMatched: matchedIds.has(entry.id),
1066
+ phase1Score: phase1Scores.get(entry.id)
1067
+ }));
1068
+ const relevant = loaded.filter(
1069
+ ({ viewMatch, wasMatched }) => wasMatched || viewMatch !== null
1070
+ );
1071
+ relevant.sort((a, b) => {
1072
+ const aScore = (a.viewMatch ? 1e3 : 0) + a.phase1Score;
1073
+ const bScore = (b.viewMatch ? 1e3 : 0) + b.phase1Score;
1074
+ return bScore - aScore;
1075
+ });
1076
+ const output = relevant.slice(0, MAX_RESULTS).map(({ entry, viewMatch }) => {
1077
+ const category = entry.menu[0];
1078
+ const toolHint = deriveToolHint(entry.route);
1079
+ return {
1080
+ title: entry.title,
1081
+ description: entry.description,
1082
+ path: entry.route,
1083
+ ...category ? { category } : {},
1084
+ ...viewMatch && viewMatch.viewKey !== "overview" ? { matchedView: viewMatch.viewKey } : {},
1085
+ snippet: viewMatch ? extractSnippet(viewMatch.content, tokens) : extractSnippet(stripMarkdown(entry.content), tokens),
1086
+ ...toolHint ? { toolHint } : {}
1087
+ };
1088
+ });
1089
+ return {
1090
+ content: [
1091
+ {
1092
+ type: "text",
1093
+ text: output.length > 0 ? JSON.stringify(output) : "No matching documentation found."
1094
+ }
1095
+ ]
1096
+ };
1097
+ } catch {
1098
+ return {
1099
+ content: [
1100
+ {
1101
+ type: "text",
1102
+ text: "Search index is not available in this environment."
1103
+ }
1104
+ ],
1105
+ isError: true
1106
+ };
1107
+ }
1108
+ }
1109
+ );
1110
+ }
1111
+
1112
+ // src/tools/search-icons.ts
1113
+ import { z as z5 } from "zod";
1114
+ var PAGE_SIZE = 10;
1115
+ var MIN_KEYWORD_LENGTH = 2;
1116
+ var MIN_CANDIDATES2 = 10;
1117
+ var loweredCache;
1118
+ var loweredCacheIcons;
1119
+ async function getLoweredIconFields() {
1120
+ const catalog = await getIconCatalog();
1121
+ if (loweredCache && loweredCacheIcons === catalog.icons) {
1122
+ return { icons: catalog.icons, loweredMap: loweredCache };
1123
+ }
1124
+ const map = /* @__PURE__ */ new Map();
1125
+ for (const icon of catalog.icons) {
1126
+ const title = icon.name.toLowerCase();
1127
+ const tags = icon.keywords.filter((kw) => kw.length >= MIN_KEYWORD_LENGTH).join(" ").toLowerCase();
1128
+ map.set(icon, {
1129
+ title,
1130
+ description: "",
1131
+ tags,
1132
+ content: "",
1133
+ combined: title + " " + tags
1134
+ });
1135
+ }
1136
+ loweredCache = map;
1137
+ loweredCacheIcons = catalog.icons;
1138
+ return { icons: catalog.icons, loweredMap: map };
1139
+ }
1140
+ async function searchIcons(query) {
1141
+ const { icons, loweredMap } = await getLoweredIconFields();
1142
+ const tokens = query.toLowerCase().split(/\s+/).filter(Boolean);
1143
+ const exactMatches = filterAndRankPreLowered(
1144
+ icons,
1145
+ tokens,
1146
+ (icon) => loweredMap.get(icon)
1147
+ );
1148
+ if (exactMatches.length >= MIN_CANDIDATES2) {
1149
+ return exactMatches;
1150
+ }
1151
+ const seen = new Set(exactMatches.map((e) => e.name));
1152
+ const fuzzyScored = [];
1153
+ for (const icon of icons) {
1154
+ if (seen.has(icon.name)) continue;
1155
+ const fields = loweredMap.get(icon);
1156
+ const score = fuzzyScorePreLowered(fields, tokens);
1157
+ if (score > 0) {
1158
+ fuzzyScored.push({ icon, score });
1159
+ }
1160
+ }
1161
+ fuzzyScored.sort((a, b) => b.score - a.score);
1162
+ return [...exactMatches, ...fuzzyScored.map(({ icon }) => icon)];
1163
+ }
1164
+ function registerSearchIcons(server) {
1165
+ server.registerTool(
1166
+ "search_icons",
1167
+ {
1168
+ title: "Search Icons",
1169
+ description: `Fuzzy-search Nimbus icons by name or keyword. Returns matching icon names with import paths from @commercetools/nimbus-icons. Results are paginated (${PAGE_SIZE} per page). Use the offset parameter to retrieve additional results.`,
1170
+ inputSchema: {
1171
+ query: z5.string().min(1).describe(
1172
+ 'Search query to match against icon names and keywords, e.g. "checkmark", "arrow", "settings".'
1173
+ ),
1174
+ offset: z5.number().int().min(0).default(0).describe(
1175
+ "Starting index for paginated results. Omit or pass 0 for the first page."
1176
+ )
1177
+ }
1178
+ },
1179
+ async ({ query, offset }) => {
1180
+ try {
1181
+ const allResults = await searchIcons(query);
1182
+ const page = allResults.slice(offset, offset + PAGE_SIZE);
1183
+ const hasMore = offset + PAGE_SIZE < allResults.length;
1184
+ const payload = {
1185
+ query,
1186
+ importPath: "@commercetools/nimbus-icons",
1187
+ totalResults: allResults.length,
1188
+ offset,
1189
+ pageSize: PAGE_SIZE,
1190
+ hasMore,
1191
+ results: page.map(({ name, category, keywords }) => ({
1192
+ name,
1193
+ category,
1194
+ keywords
1195
+ }))
1196
+ };
1197
+ if (hasMore) {
1198
+ payload.hint = `Use \`offset: ${offset + PAGE_SIZE}\` for more results (${allResults.length} total).`;
1199
+ }
1200
+ return {
1201
+ content: [
1202
+ {
1203
+ type: "text",
1204
+ text: JSON.stringify(payload)
1205
+ }
1206
+ ]
1207
+ };
1208
+ } catch {
1209
+ return {
1210
+ content: [
1211
+ {
1212
+ type: "text",
1213
+ text: "Icon catalog is not available in this environment."
1214
+ }
1215
+ ],
1216
+ isError: true
1217
+ };
1218
+ }
1219
+ }
1220
+ );
1221
+ }
1222
+
1223
+ // src/tools/migrate-from-uikit.ts
1224
+ import { readFile as readFile3 } from "fs/promises";
1225
+ import { z as z6 } from "zod";
1226
+
1227
+ // src/data/uikit-migration.ts
1228
+ var MIGRATION_DATA = [
1229
+ // -------------------------------------------------------------------------
1230
+ // Buttons
1231
+ // -------------------------------------------------------------------------
1232
+ {
1233
+ uiKitName: "AccessibleButton",
1234
+ nimbusEquivalent: "Button",
1235
+ importPath: "@commercetools/nimbus",
1236
+ mappingType: "variant",
1237
+ notes: "Use <Button> directly. Nimbus Button is accessible by default; no wrapper needed. UI Kit used a required label prop for button text; Nimbus uses children.",
1238
+ breakingChanges: [
1239
+ "Remove AccessibleButton wrapper, use <Button> directly",
1240
+ "label prop replaced by children"
1241
+ ]
1242
+ },
1243
+ {
1244
+ uiKitName: "FlatButton",
1245
+ nimbusEquivalent: "Button",
1246
+ importPath: "@commercetools/nimbus",
1247
+ mappingType: "variant",
1248
+ notes: `Use <Button variant="ghost"> for flat styling. UI Kit tone prop ('primary'|'secondary'|'inverted'|'critical') maps to Nimbus colorPalette/variant.`,
1249
+ breakingChanges: [
1250
+ "Replace FlatButton with <Button>",
1251
+ "label prop replaced by children",
1252
+ "tone prop replaced by variant/colorPalette",
1253
+ "iconPosition prop removed; pass icon as a child of <Button>"
1254
+ ]
1255
+ },
1256
+ {
1257
+ uiKitName: "LinkButton",
1258
+ nimbusEquivalent: "Button",
1259
+ importPath: "@commercetools/nimbus",
1260
+ mappingType: "variant",
1261
+ notes: 'Use <Button variant="link" asChild> wrapping a router Link, or use <Button as="a" href="...">. UI Kit used a to prop (React Router LocationDescriptor); Nimbus uses href or asChild pattern.',
1262
+ breakingChanges: [
1263
+ "Replace LinkButton with <Button asChild> or <Button as='a'>",
1264
+ "label prop replaced by children",
1265
+ "to prop replaced by href (or use asChild with router Link)",
1266
+ "isExternal prop replaced by target='_blank' rel='noopener noreferrer'",
1267
+ "iconLeft prop removed; pass icon as a child of <Button>"
1268
+ ]
1269
+ },
1270
+ {
1271
+ uiKitName: "PrimaryButton",
1272
+ nimbusEquivalent: "Button",
1273
+ importPath: "@commercetools/nimbus",
1274
+ mappingType: "variant",
1275
+ notes: 'Use <Button variant="solid">. Note: the default Button variant is "subtle", so variant="solid" must be set explicitly. UI Kit used a required label prop; Nimbus uses children for button text.',
1276
+ breakingChanges: [
1277
+ "Replace PrimaryButton with <Button variant='solid'>",
1278
+ "label prop replaced by children",
1279
+ "iconLeft/iconRight props removed; pass icon as a child of <Button>",
1280
+ "tone prop ('urgent'|'primary'|'critical') replaced by colorPalette"
1281
+ ]
1282
+ },
1283
+ {
1284
+ uiKitName: "SecondaryButton",
1285
+ nimbusEquivalent: "Button",
1286
+ importPath: "@commercetools/nimbus",
1287
+ mappingType: "variant",
1288
+ notes: 'Use <Button variant="outline"> for the secondary style. UI Kit used a required label prop; Nimbus uses children.',
1289
+ breakingChanges: [
1290
+ "Replace SecondaryButton with <Button variant='outline'>",
1291
+ "label prop replaced by children",
1292
+ "iconLeft/iconRight props removed; pass icon as a child of <Button>",
1293
+ "theme prop ('default'|'info') replaced by colorPalette"
1294
+ ]
1295
+ },
1296
+ {
1297
+ uiKitName: "IconButton",
1298
+ nimbusEquivalent: "IconButton",
1299
+ importPath: "@commercetools/nimbus",
1300
+ mappingType: "direct",
1301
+ notes: "Direct replacement. UI Kit passed the icon via an icon prop and used label for accessibility; Nimbus passes icon as children and uses aria-label.",
1302
+ breakingChanges: [
1303
+ "label prop replaced by aria-label",
1304
+ "icon prop replaced by icon as children",
1305
+ "theme prop replaced by variant/colorPalette"
1306
+ ]
1307
+ },
1308
+ {
1309
+ uiKitName: "SecondaryIconButton",
1310
+ nimbusEquivalent: "IconButton",
1311
+ importPath: "@commercetools/nimbus",
1312
+ mappingType: "variant",
1313
+ notes: `Use <IconButton variant="outline"> or equivalent. UI Kit used a color prop ('solid'|'primary'|'info'); Nimbus uses variant/colorPalette.`,
1314
+ breakingChanges: [
1315
+ "Replace SecondaryIconButton with <IconButton>",
1316
+ "color prop ('solid'|'primary'|'info') replaced by variant/colorPalette",
1317
+ "icon prop replaced by icon as children",
1318
+ "label prop replaced by aria-label"
1319
+ ]
1320
+ },
1321
+ {
1322
+ uiKitName: "PrimaryActionDropdown",
1323
+ nimbusEquivalent: "SplitButton",
1324
+ importPath: "@commercetools/nimbus",
1325
+ mappingType: "direct",
1326
+ notes: "SplitButton combines a primary action button with a dropdown menu. Compose using SplitButton + Menu.",
1327
+ breakingChanges: [
1328
+ "Rename to SplitButton",
1329
+ "Menu items now use Nimbus Menu composition pattern"
1330
+ ]
1331
+ },
1332
+ // -------------------------------------------------------------------------
1333
+ // Form inputs — text
1334
+ // -------------------------------------------------------------------------
1335
+ {
1336
+ uiKitName: "TextInput",
1337
+ nimbusEquivalent: "TextInput",
1338
+ importPath: "@commercetools/nimbus",
1339
+ mappingType: "direct",
1340
+ notes: "Direct replacement. UI Kit onChange was ChangeEvent<HTMLInputElement>; Nimbus (React Aria) onChange receives a string value directly. hasError/hasWarning replaced by isInvalid. isAutofocussed replaced by autoFocus.",
1341
+ breakingChanges: [
1342
+ "onChange now receives a string value instead of ChangeEvent<HTMLInputElement>",
1343
+ "hasError prop replaced by isInvalid",
1344
+ "hasWarning prop removed",
1345
+ "isAutofocussed replaced by autoFocus",
1346
+ "isCondensed prop replaced by size='sm'"
1347
+ ]
1348
+ },
1349
+ {
1350
+ uiKitName: "TextField",
1351
+ nimbusEquivalent: "TextInputField",
1352
+ importPath: "@commercetools/nimbus",
1353
+ mappingType: "direct",
1354
+ notes: "TextInputField wraps TextInput with label, description, and error message slots. UI Kit used title for the label text, hint for helper text, and errors (Record) for validation.",
1355
+ breakingChanges: [
1356
+ "Rename to TextInputField",
1357
+ "title prop renamed to label",
1358
+ "hint prop renamed to description",
1359
+ "errors (Record<string, boolean>) replaced by passing <FieldErrors> to the errorMessage prop",
1360
+ "warnings prop removed",
1361
+ "touched prop removed",
1362
+ "onChange now receives a string value instead of ChangeEvent<HTMLInputElement>"
1363
+ ]
1364
+ },
1365
+ {
1366
+ uiKitName: "MultilineTextInput",
1367
+ nimbusEquivalent: "MultilineTextInput",
1368
+ importPath: "@commercetools/nimbus",
1369
+ mappingType: "direct",
1370
+ notes: "Direct replacement. UI Kit onChange was ChangeEvent<HTMLTextAreaElement>; Nimbus onChange receives a string value. hasError replaced by isInvalid.",
1371
+ breakingChanges: [
1372
+ "onChange now receives a string value instead of ChangeEvent<HTMLTextAreaElement>",
1373
+ "hasError prop replaced by isInvalid",
1374
+ "hasWarning prop removed",
1375
+ "isAutofocussed replaced by autoFocus"
1376
+ ]
1377
+ },
1378
+ {
1379
+ uiKitName: "MultilineTextField",
1380
+ nimbusEquivalent: "MultilineTextInputField",
1381
+ importPath: "@commercetools/nimbus",
1382
+ mappingType: "direct",
1383
+ notes: "Wraps MultilineTextInput with label, description, and error message. UI Kit used title for the label text and hint for helper text.",
1384
+ breakingChanges: [
1385
+ "Rename to MultilineTextInputField",
1386
+ "title prop renamed to label",
1387
+ "hint prop renamed to description",
1388
+ "errors (Record) replaced by passing <FieldErrors> to the errorMessage prop",
1389
+ "warnings prop removed",
1390
+ "onChange now receives a string value instead of ChangeEvent<HTMLTextAreaElement>"
1391
+ ]
1392
+ },
1393
+ {
1394
+ uiKitName: "PasswordInput",
1395
+ nimbusEquivalent: "PasswordInput",
1396
+ importPath: "@commercetools/nimbus",
1397
+ mappingType: "direct",
1398
+ notes: "Direct replacement. Toggle visibility button is built in. UI Kit onChange was ChangeEvent<HTMLInputElement>; Nimbus onChange receives a string.",
1399
+ breakingChanges: [
1400
+ "onChange now receives a string value instead of ChangeEvent<HTMLInputElement>",
1401
+ "hasError prop replaced by isInvalid",
1402
+ "isAutofocussed replaced by autoFocus"
1403
+ ]
1404
+ },
1405
+ {
1406
+ uiKitName: "PasswordField",
1407
+ nimbusEquivalent: "PasswordInputField",
1408
+ importPath: "@commercetools/nimbus",
1409
+ mappingType: "direct",
1410
+ notes: "Wraps PasswordInput with label and error message slots.",
1411
+ breakingChanges: [
1412
+ "Rename to PasswordInputField",
1413
+ "title prop renamed to label",
1414
+ "hint prop renamed to description",
1415
+ "errors (Record) replaced by passing <FieldErrors> to the errorMessage prop"
1416
+ ]
1417
+ },
1418
+ {
1419
+ uiKitName: "SearchSelectInput",
1420
+ nimbusEquivalent: "ComboBox",
1421
+ importPath: "@commercetools/nimbus",
1422
+ mappingType: "direct",
1423
+ notes: "Use ComboBox for a searchable select dropdown. Pass options via the items prop and render each with ComboBox.Item. ComboBox handles filtering natively.",
1424
+ breakingChanges: [
1425
+ "Rename to ComboBox",
1426
+ "options array replaced by items prop with ComboBox.Item render function",
1427
+ "onChange received TCustomEvent; now receives selected key directly"
1428
+ ]
1429
+ },
1430
+ {
1431
+ uiKitName: "SearchSelectField",
1432
+ nimbusEquivalent: "ComboBox + FormField",
1433
+ importPath: "@commercetools/nimbus",
1434
+ mappingType: "compound",
1435
+ notes: "Wrap ComboBox in a FormField to add label, description, and error message. There is no standalone ComboBoxField component.",
1436
+ breakingChanges: [
1437
+ "Compose FormField + ComboBox manually",
1438
+ "title prop replaced by FormField label",
1439
+ "hint prop replaced by FormField description",
1440
+ "errors (Record) replaced by passing <FieldErrors> as a child of FormField.Error"
1441
+ ]
1442
+ },
1443
+ {
1444
+ uiKitName: "SelectableSearchInput",
1445
+ nimbusEquivalent: "ScopedSearchInput",
1446
+ importPath: "@commercetools/nimbus",
1447
+ mappingType: "direct",
1448
+ notes: "ScopedSearchInput adds a scope/category selector alongside the search field.",
1449
+ breakingChanges: [
1450
+ "Rename to ScopedSearchInput",
1451
+ "scope options now use items prop with ScopedSearchInput.Item children"
1452
+ ]
1453
+ },
1454
+ // -------------------------------------------------------------------------
1455
+ // Form inputs — select / combobox
1456
+ // -------------------------------------------------------------------------
1457
+ {
1458
+ uiKitName: "SelectInput",
1459
+ nimbusEquivalent: "Select",
1460
+ importPath: "@commercetools/nimbus",
1461
+ mappingType: "direct",
1462
+ notes: "Select accepts an items prop with a Select.Item render function. UI Kit onChange received a TCustomEvent with target.value (string); Nimbus onChange receives the selected key directly. UI Kit option shape: { value: string, label: ReactNode, isDisabled?: boolean }.",
1463
+ breakingChanges: [
1464
+ "Rename to Select",
1465
+ "options array ({value, label}) replaced by items prop with Select.Item render function",
1466
+ "onChange received TCustomEvent (target.value); now receives selected key directly",
1467
+ "isMulti support changed; check Nimbus Select API for multi-select",
1468
+ "appearance prop ('default'|'quiet'|'filter') replaced by variant"
1469
+ ]
1470
+ },
1471
+ {
1472
+ uiKitName: "CreatableSelectInput",
1473
+ nimbusEquivalent: "ComboBox",
1474
+ importPath: "@commercetools/nimbus",
1475
+ mappingType: "direct",
1476
+ notes: "ComboBox supports both selection and free-text entry. Use allowsCustomOptions prop for creatable behavior. UI Kit onCreateOption callback is replaced by handling new values in onInputChange.",
1477
+ breakingChanges: [
1478
+ "Rename to ComboBox",
1479
+ "options array replaced by items prop with ComboBox.Item render function",
1480
+ "onCreateOption replaced by allowsCustomOptions + custom onInputChange logic",
1481
+ "onChange received TCustomEvent; now receives selected key directly"
1482
+ ]
1483
+ },
1484
+ {
1485
+ uiKitName: "AsyncCreatableSelectInput",
1486
+ nimbusEquivalent: "ComboBox",
1487
+ importPath: "@commercetools/nimbus",
1488
+ mappingType: "variant",
1489
+ notes: "Use ComboBox with allowsCustomOptions and manage async loading via onInputChange + external state. UI Kit provided a loadOptions callback; in Nimbus this is managed externally.",
1490
+ breakingChanges: [
1491
+ "Rename to ComboBox",
1492
+ "loadOptions callback replaced by onInputChange + external async fetch + items state",
1493
+ "onCreateOption replaced by allowsCustomOptions + custom logic",
1494
+ "onChange received TCustomEvent; now receives selected key directly"
1495
+ ]
1496
+ },
1497
+ {
1498
+ uiKitName: "AsyncSelectInput",
1499
+ nimbusEquivalent: "ComboBox",
1500
+ importPath: "@commercetools/nimbus",
1501
+ mappingType: "variant",
1502
+ notes: "Use ComboBox and manage async options loading via onInputChange + external state. UI Kit provided a loadOptions callback; in Nimbus this is managed externally.",
1503
+ breakingChanges: [
1504
+ "Rename to ComboBox",
1505
+ "loadOptions callback replaced by onInputChange + external async fetch + items state",
1506
+ "onChange received TCustomEvent; now receives selected key directly"
1507
+ ]
1508
+ },
1509
+ // -------------------------------------------------------------------------
1510
+ // Form inputs — number / money
1511
+ // -------------------------------------------------------------------------
1512
+ {
1513
+ uiKitName: "NumberInput",
1514
+ nimbusEquivalent: "NumberInput",
1515
+ importPath: "@commercetools/nimbus",
1516
+ mappingType: "direct",
1517
+ notes: "Direct replacement. UI Kit value was string|number and onChange was ChangeEvent<HTMLInputElement>; Nimbus value is a number and onChange receives a number directly. min/max/step prop names unchanged.",
1518
+ breakingChanges: [
1519
+ "onChange now receives a number instead of ChangeEvent<HTMLInputElement>",
1520
+ "value was string|number; now must be a number",
1521
+ "hasError prop replaced by isInvalid",
1522
+ "isAutofocussed replaced by autoFocus"
1523
+ ]
1524
+ },
1525
+ {
1526
+ uiKitName: "NumberField",
1527
+ nimbusEquivalent: "NumberInputField",
1528
+ importPath: "@commercetools/nimbus",
1529
+ mappingType: "direct",
1530
+ notes: "Wraps NumberInput with label, description, and error message. UI Kit used title for the label text and hint for helper text.",
1531
+ breakingChanges: [
1532
+ "Rename to NumberInputField",
1533
+ "title prop renamed to label",
1534
+ "hint prop renamed to description",
1535
+ "errors (Record) replaced by passing <FieldErrors> to the errorMessage prop"
1536
+ ]
1537
+ },
1538
+ {
1539
+ uiKitName: "MoneyInput",
1540
+ nimbusEquivalent: "MoneyInput",
1541
+ importPath: "@commercetools/nimbus",
1542
+ mappingType: "direct",
1543
+ notes: "Direct replacement. Currency selector and amount field are composed internally. UI Kit value shape was { amount: string, currencyCode: string }; Nimbus keeps the same shape. UI Kit onChange received a TCustomEvent (not a plain object); check Nimbus onChange signature.",
1544
+ breakingChanges: [
1545
+ "onChange received TCustomEvent; now receives { amount, currencyCode } directly",
1546
+ "currencies prop for available currency options unchanged",
1547
+ "hasError prop replaced by isInvalid"
1548
+ ]
1549
+ },
1550
+ {
1551
+ uiKitName: "MoneyField",
1552
+ nimbusEquivalent: "MoneyInputField",
1553
+ importPath: "@commercetools/nimbus",
1554
+ mappingType: "direct",
1555
+ notes: "Wraps MoneyInput with label, description, and error message. UI Kit used title for the label text and hint for helper text.",
1556
+ breakingChanges: [
1557
+ "Rename to MoneyInputField",
1558
+ "title prop renamed to label",
1559
+ "hint prop renamed to description",
1560
+ "errors (Record) replaced by passing <FieldErrors> to the errorMessage prop"
1561
+ ]
1562
+ },
1563
+ // -------------------------------------------------------------------------
1564
+ // Form inputs — date / time
1565
+ // -------------------------------------------------------------------------
1566
+ {
1567
+ uiKitName: "DateInput",
1568
+ nimbusEquivalent: "DatePicker",
1569
+ importPath: "@commercetools/nimbus",
1570
+ mappingType: "direct",
1571
+ notes: "DatePicker uses @internationalized/date value types (CalendarDate). UI Kit value was a string ('YYYY-MM-DD' or ''); onChange received a TCustomEvent with a string value. Nimbus value is a CalendarDate object and onChange receives a CalendarDate.",
1572
+ breakingChanges: [
1573
+ "Rename to DatePicker",
1574
+ "value changed from 'YYYY-MM-DD' string to CalendarDate from @internationalized/date",
1575
+ "onChange received TCustomEvent with string; now receives CalendarDate directly",
1576
+ "minValue/maxValue changed from strings to CalendarDate objects"
1577
+ ]
1578
+ },
1579
+ {
1580
+ uiKitName: "DateTimeInput",
1581
+ nimbusEquivalent: "DatePicker",
1582
+ importPath: "@commercetools/nimbus",
1583
+ mappingType: "variant",
1584
+ notes: "Use DatePicker with granularity='minute' or 'second' to include time selection.",
1585
+ breakingChanges: [
1586
+ "Rename to DatePicker",
1587
+ "value must be a ZonedDateTime or CalendarDateTime",
1588
+ "Use granularity prop to enable time fields"
1589
+ ]
1590
+ },
1591
+ {
1592
+ uiKitName: "DateRangeInput",
1593
+ nimbusEquivalent: "DateRangePicker",
1594
+ importPath: "@commercetools/nimbus",
1595
+ mappingType: "direct",
1596
+ notes: "DateRangePicker uses { start: CalendarDate, end: CalendarDate } value shape.",
1597
+ breakingChanges: [
1598
+ "Rename to DateRangePicker",
1599
+ "value shape changed to { start, end } using CalendarDate"
1600
+ ]
1601
+ },
1602
+ {
1603
+ uiKitName: "DateRangeField",
1604
+ nimbusEquivalent: "DateRangePickerField",
1605
+ importPath: "@commercetools/nimbus",
1606
+ mappingType: "direct",
1607
+ notes: "Wraps DateRangePicker with label and error message.",
1608
+ breakingChanges: ["Rename to DateRangePickerField"]
1609
+ },
1610
+ {
1611
+ uiKitName: "TimeInput",
1612
+ nimbusEquivalent: "TimeInput",
1613
+ importPath: "@commercetools/nimbus",
1614
+ mappingType: "direct",
1615
+ notes: "Direct replacement. value must be a Time object from @internationalized/date.",
1616
+ breakingChanges: ["value must be a Time from @internationalized/date"]
1617
+ },
1618
+ // -------------------------------------------------------------------------
1619
+ // Form inputs — checkbox / radio / toggle
1620
+ // -------------------------------------------------------------------------
1621
+ {
1622
+ uiKitName: "CheckboxInput",
1623
+ nimbusEquivalent: "Checkbox",
1624
+ importPath: "@commercetools/nimbus",
1625
+ mappingType: "direct",
1626
+ notes: "Rename to Checkbox. UI Kit used isChecked and onChange: ChangeEventHandler<HTMLInputElement>; Nimbus uses isSelected and onChange receives a boolean directly.",
1627
+ breakingChanges: [
1628
+ "Rename to Checkbox",
1629
+ "isChecked prop renamed to isSelected",
1630
+ "onChange received ChangeEvent<HTMLInputElement>; now receives boolean isSelected directly"
1631
+ ]
1632
+ },
1633
+ {
1634
+ uiKitName: "RadioInput",
1635
+ nimbusEquivalent: "RadioInput",
1636
+ importPath: "@commercetools/nimbus",
1637
+ mappingType: "direct",
1638
+ notes: "Direct replacement. Group radios with RadioGroup parent for accessible keyboard navigation.",
1639
+ breakingChanges: ["Wrap in RadioGroup for group behavior"]
1640
+ },
1641
+ {
1642
+ uiKitName: "ToggleInput",
1643
+ nimbusEquivalent: "Switch",
1644
+ importPath: "@commercetools/nimbus",
1645
+ mappingType: "direct",
1646
+ notes: "Rename to Switch. UI Kit used isChecked and onChange: ChangeEventHandler<HTMLInputElement> (target.checked); Nimbus Switch uses isSelected and onChange receives a boolean directly.",
1647
+ breakingChanges: [
1648
+ "Rename to Switch",
1649
+ "isChecked prop renamed to isSelected",
1650
+ "onChange received ChangeEvent (target.checked); now receives boolean isSelected directly",
1651
+ "size prop ('small'|'big') replaced by Nimbus size tokens"
1652
+ ]
1653
+ },
1654
+ // -------------------------------------------------------------------------
1655
+ // Form inputs — localized
1656
+ // -------------------------------------------------------------------------
1657
+ {
1658
+ uiKitName: "LocalizedTextInput",
1659
+ nimbusEquivalent: "LocalizedField",
1660
+ importPath: "@commercetools/nimbus",
1661
+ mappingType: "variant",
1662
+ notes: 'Use <LocalizedField type="text"> (the default type). LocalizedField manages all locale inputs internally via its type prop.',
1663
+ breakingChanges: [
1664
+ "Replace LocalizedTextInput with <LocalizedField> (type='text' is the default)",
1665
+ "selectedLanguage prop replaced by defaultLocaleOrCurrency",
1666
+ "value per locale replaced by valuesByLocaleOrCurrency object",
1667
+ "onChange receives a LocalizedFieldChangeEvent with target.locale"
1668
+ ]
1669
+ },
1670
+ {
1671
+ uiKitName: "LocalizedTextField",
1672
+ nimbusEquivalent: "LocalizedField",
1673
+ importPath: "@commercetools/nimbus",
1674
+ mappingType: "variant",
1675
+ notes: 'Use <LocalizedField type="text"> with label, description, and error props. LocalizedField is already a field-level component with built-in label and error slots.',
1676
+ breakingChanges: [
1677
+ "Replace LocalizedTextField with <LocalizedField> (type='text' is the default)",
1678
+ "title prop renamed to label",
1679
+ "hint prop renamed to description",
1680
+ "errors (Record) replaced by errorsByLocaleOrCurrency",
1681
+ "onChange receives a LocalizedFieldChangeEvent with target.locale"
1682
+ ]
1683
+ },
1684
+ {
1685
+ uiKitName: "LocalizedMultilineTextInput",
1686
+ nimbusEquivalent: "LocalizedField",
1687
+ importPath: "@commercetools/nimbus",
1688
+ mappingType: "variant",
1689
+ notes: 'Use <LocalizedField type="multiLine">. The type prop controls the input variant; no child composition needed.',
1690
+ breakingChanges: [
1691
+ "Replace LocalizedMultilineTextInput with <LocalizedField type='multiLine'>",
1692
+ "selectedLanguage prop replaced by defaultLocaleOrCurrency",
1693
+ "value per locale replaced by valuesByLocaleOrCurrency object",
1694
+ "onChange receives a LocalizedFieldChangeEvent with target.locale"
1695
+ ]
1696
+ },
1697
+ {
1698
+ uiKitName: "LocalizedMultilineTextField",
1699
+ nimbusEquivalent: "LocalizedField",
1700
+ importPath: "@commercetools/nimbus",
1701
+ mappingType: "variant",
1702
+ notes: 'Use <LocalizedField type="multiLine"> with label, description, and error props. LocalizedField is already a field-level component with built-in label and error slots.',
1703
+ breakingChanges: [
1704
+ "Replace LocalizedMultilineTextField with <LocalizedField type='multiLine'>",
1705
+ "title prop renamed to label",
1706
+ "hint prop renamed to description",
1707
+ "errors (Record) replaced by errorsByLocaleOrCurrency",
1708
+ "onChange receives a LocalizedFieldChangeEvent with target.locale"
1709
+ ]
1710
+ },
1711
+ {
1712
+ uiKitName: "LocalizedMoneyInput",
1713
+ nimbusEquivalent: "LocalizedField",
1714
+ importPath: "@commercetools/nimbus",
1715
+ mappingType: "variant",
1716
+ notes: 'Use <LocalizedField type="money">. valuesByLocaleOrCurrency accepts a LocalizedCurrency object keyed by currency code.',
1717
+ breakingChanges: [
1718
+ "Replace LocalizedMoneyInput with <LocalizedField type='money'>",
1719
+ "selectedLanguage prop replaced by defaultLocaleOrCurrency (currency code)",
1720
+ "value per currency replaced by valuesByLocaleOrCurrency object",
1721
+ "onChange receives a LocalizedFieldChangeEvent with target.currency"
1722
+ ]
1723
+ },
1724
+ {
1725
+ uiKitName: "LocalizedRichTextInput",
1726
+ nimbusEquivalent: "LocalizedField",
1727
+ importPath: "@commercetools/nimbus",
1728
+ mappingType: "variant",
1729
+ notes: 'Use <LocalizedField type="richText">. The type prop controls the input variant; no child composition needed.',
1730
+ breakingChanges: [
1731
+ "Replace LocalizedRichTextInput with <LocalizedField type='richText'>",
1732
+ "selectedLanguage prop replaced by defaultLocaleOrCurrency",
1733
+ "value per locale replaced by valuesByLocaleOrCurrency object",
1734
+ "onChange receives a LocalizedFieldChangeEvent with target.locale"
1735
+ ]
1736
+ },
1737
+ // -------------------------------------------------------------------------
1738
+ // Form structure
1739
+ // -------------------------------------------------------------------------
1740
+ {
1741
+ uiKitName: "FieldErrors",
1742
+ nimbusEquivalent: "FieldErrors",
1743
+ importPath: "@commercetools/nimbus",
1744
+ mappingType: "direct",
1745
+ notes: "Direct replacement. Used inside *Field components for error display.",
1746
+ breakingChanges: []
1747
+ },
1748
+ {
1749
+ uiKitName: "AdditionalInfoMessage",
1750
+ nimbusEquivalent: "Text + FormField",
1751
+ importPath: "@commercetools/nimbus",
1752
+ mappingType: "compound",
1753
+ notes: "Compose FormField with a description prop, or use <Text size='sm' color='neutral.500'>.",
1754
+ breakingChanges: [
1755
+ "Replace AdditionalInfoMessage with FormField description prop or Text component"
1756
+ ]
1757
+ },
1758
+ {
1759
+ uiKitName: "ErrorMessage",
1760
+ nimbusEquivalent: "Text + FormField",
1761
+ importPath: "@commercetools/nimbus",
1762
+ mappingType: "compound",
1763
+ notes: "Use <FieldErrors> passed to a *Field component's errorMessage prop, or as a child of FormField.Error.",
1764
+ breakingChanges: [
1765
+ "Replace ErrorMessage with <FieldErrors> inside a Field errorMessage prop or FormField.Error"
1766
+ ]
1767
+ },
1768
+ {
1769
+ uiKitName: "WarningMessage",
1770
+ nimbusEquivalent: "Text + FormField",
1771
+ importPath: "@commercetools/nimbus",
1772
+ mappingType: "compound",
1773
+ notes: "Use <Text color='warning.500'> or a FormField description for warnings.",
1774
+ breakingChanges: [
1775
+ "Replace WarningMessage with Text + appropriate color token"
1776
+ ]
1777
+ },
1778
+ // -------------------------------------------------------------------------
1779
+ // Rich text
1780
+ // -------------------------------------------------------------------------
1781
+ {
1782
+ uiKitName: "RichTextInput",
1783
+ nimbusEquivalent: "RichTextInput",
1784
+ importPath: "@commercetools/nimbus",
1785
+ mappingType: "direct",
1786
+ notes: "Direct replacement. Editor toolbar configuration API has changed.",
1787
+ breakingChanges: [
1788
+ "toolbar configuration prop shape has changed; consult Nimbus docs"
1789
+ ]
1790
+ },
1791
+ // -------------------------------------------------------------------------
1792
+ // Data display
1793
+ // -------------------------------------------------------------------------
1794
+ {
1795
+ uiKitName: "Avatar",
1796
+ nimbusEquivalent: "Avatar",
1797
+ importPath: "@commercetools/nimbus",
1798
+ mappingType: "direct",
1799
+ notes: "Direct replacement. name prop is still used for initials fallback.",
1800
+ breakingChanges: []
1801
+ },
1802
+ {
1803
+ uiKitName: "Stamp",
1804
+ nimbusEquivalent: "Badge",
1805
+ importPath: "@commercetools/nimbus",
1806
+ mappingType: "direct",
1807
+ notes: "Rename to Badge. Both use a tone prop, but the tone values differ. UI Kit tones: 'critical'|'warning'|'positive'|'information'|'primary'|'secondary'. Nimbus tones: 'danger'|'warning'|'success'|'info'.",
1808
+ breakingChanges: [
1809
+ "Rename to Badge",
1810
+ "tone value 'critical' \u2192 'danger'",
1811
+ "tone value 'positive' \u2192 'success'",
1812
+ "tone value 'information' \u2192 'info'",
1813
+ "tone values 'primary' and 'secondary' have no direct equivalent; use 'neutral' or default",
1814
+ "isCondensed prop replaced by size='sm'"
1815
+ ]
1816
+ },
1817
+ {
1818
+ uiKitName: "Tag",
1819
+ nimbusEquivalent: "TagGroup",
1820
+ importPath: "@commercetools/nimbus",
1821
+ mappingType: "variant",
1822
+ notes: "Use TagGroup.Root with TagGroup.TagList and a single TagGroup.Tag for a standalone tag. TagGroup manages selection/removal state.",
1823
+ breakingChanges: [
1824
+ "Wrap single Tag in <TagGroup.Root><TagGroup.TagList><TagGroup.Tag>...</TagGroup.Tag></TagGroup.TagList></TagGroup.Root>",
1825
+ "onRemove now receives a key-based Set"
1826
+ ]
1827
+ },
1828
+ {
1829
+ uiKitName: "TagList",
1830
+ nimbusEquivalent: "TagGroup",
1831
+ importPath: "@commercetools/nimbus",
1832
+ mappingType: "direct",
1833
+ notes: "Replace TagList with TagGroup.Root + TagGroup.TagList. Each tag becomes a TagGroup.Tag child.",
1834
+ breakingChanges: [
1835
+ "Rename to TagGroup (use TagGroup.Root, TagGroup.TagList, TagGroup.Tag)",
1836
+ "items array replaced by TagGroup.Tag children inside TagGroup.TagList"
1837
+ ]
1838
+ },
1839
+ {
1840
+ uiKitName: "ProgressBar",
1841
+ nimbusEquivalent: "ProgressBar",
1842
+ importPath: "@commercetools/nimbus",
1843
+ mappingType: "direct",
1844
+ notes: "Direct replacement. value is a 0\u2013100 number.",
1845
+ breakingChanges: []
1846
+ },
1847
+ {
1848
+ uiKitName: "LoadingSpinner",
1849
+ nimbusEquivalent: "LoadingSpinner",
1850
+ importPath: "@commercetools/nimbus",
1851
+ mappingType: "direct",
1852
+ notes: "Direct replacement.",
1853
+ breakingChanges: []
1854
+ },
1855
+ {
1856
+ uiKitName: "DataTable",
1857
+ nimbusEquivalent: "DataTable",
1858
+ importPath: "@commercetools/nimbus",
1859
+ mappingType: "direct",
1860
+ notes: "Direct replacement. Column definitions use the new columns prop with accessor keys.",
1861
+ breakingChanges: [
1862
+ "columns prop shape changed to use accessor and header fields",
1863
+ "Row selection API updated to use onSelectionChange with a Set of keys"
1864
+ ]
1865
+ },
1866
+ {
1867
+ uiKitName: "DataTableManager",
1868
+ nimbusEquivalent: "DataTableManager",
1869
+ importPath: "@commercetools/nimbus",
1870
+ mappingType: "direct",
1871
+ notes: "Direct replacement. Works alongside DataTable for column management.",
1872
+ breakingChanges: []
1873
+ },
1874
+ // -------------------------------------------------------------------------
1875
+ // Navigation
1876
+ // -------------------------------------------------------------------------
1877
+ {
1878
+ uiKitName: "Link",
1879
+ nimbusEquivalent: "Link",
1880
+ importPath: "@commercetools/nimbus",
1881
+ mappingType: "direct",
1882
+ notes: "Direct replacement. Use asChild for router library integration.",
1883
+ breakingChanges: [
1884
+ "isExternal prop renamed to target='_blank' + rel='noopener'"
1885
+ ]
1886
+ },
1887
+ {
1888
+ uiKitName: "DropdownMenu",
1889
+ nimbusEquivalent: "Menu",
1890
+ importPath: "@commercetools/nimbus",
1891
+ mappingType: "direct",
1892
+ notes: "Rename to Menu. Uses composable Menu.Root, Menu.Trigger, Menu.Content, and Menu.Item.",
1893
+ breakingChanges: [
1894
+ "Rename to Menu (use Menu.Root, Menu.Trigger, Menu.Content, Menu.Item)",
1895
+ "options array replaced by Menu.Item children inside Menu.Content",
1896
+ "onSelect replaced by onAction on Menu.Item or Menu"
1897
+ ]
1898
+ },
1899
+ {
1900
+ uiKitName: "Pagination",
1901
+ nimbusEquivalent: "Pagination",
1902
+ importPath: "@commercetools/nimbus",
1903
+ mappingType: "direct",
1904
+ notes: "Direct replacement. page/totalPages prop names are unchanged.",
1905
+ breakingChanges: ["onPageChange receives a page number directly"]
1906
+ },
1907
+ // -------------------------------------------------------------------------
1908
+ // Overlays
1909
+ // -------------------------------------------------------------------------
1910
+ {
1911
+ uiKitName: "Tooltip",
1912
+ nimbusEquivalent: "Tooltip",
1913
+ importPath: "@commercetools/nimbus",
1914
+ mappingType: "direct",
1915
+ notes: "Tooltip wraps a trigger element. Use Tooltip.Root (wraps the trigger child) and Tooltip.Content composition.",
1916
+ breakingChanges: [
1917
+ "Compositional API: replace single prop with Tooltip.Root + Tooltip.Content"
1918
+ ]
1919
+ },
1920
+ // -------------------------------------------------------------------------
1921
+ // Feedback
1922
+ // -------------------------------------------------------------------------
1923
+ {
1924
+ uiKitName: "ContentNotification",
1925
+ nimbusEquivalent: "Alert",
1926
+ importPath: "@commercetools/nimbus",
1927
+ mappingType: "direct",
1928
+ notes: "Rename to Alert. tone prop replaces type prop for semantic intent.",
1929
+ breakingChanges: [
1930
+ "Rename to Alert",
1931
+ "type prop replaced by tone ('info', 'success', 'warning', 'danger')"
1932
+ ]
1933
+ },
1934
+ // -------------------------------------------------------------------------
1935
+ // Layout
1936
+ // -------------------------------------------------------------------------
1937
+ {
1938
+ uiKitName: "Grid",
1939
+ nimbusEquivalent: "Grid",
1940
+ importPath: "@commercetools/nimbus",
1941
+ mappingType: "direct",
1942
+ notes: "Direct replacement. Uses Chakra UI Grid props (columns, gap, etc.).",
1943
+ breakingChanges: []
1944
+ },
1945
+ {
1946
+ uiKitName: "Constraints.Horizontal",
1947
+ nimbusEquivalent: "Design tokens",
1948
+ importPath: "@commercetools/nimbus-tokens",
1949
+ mappingType: "pattern",
1950
+ notes: "Replace Constraints.Horizontal with maxWidth design tokens or the Box/Container component.",
1951
+ breakingChanges: [
1952
+ "Remove Constraints.Horizontal",
1953
+ "Use maxWidth prop with design token values on Box or Container"
1954
+ ]
1955
+ },
1956
+ {
1957
+ uiKitName: "Spacings.Inline",
1958
+ nimbusEquivalent: "Stack",
1959
+ importPath: "@commercetools/nimbus",
1960
+ mappingType: "pattern",
1961
+ notes: 'Use <Stack direction="row" gap={...}> with nimbus spacing tokens.',
1962
+ breakingChanges: [
1963
+ "Replace Spacings.Inline with <Stack direction='row'>",
1964
+ "Spacing values use design token scale (e.g. gap='300')"
1965
+ ]
1966
+ },
1967
+ {
1968
+ uiKitName: "Spacings.Inset",
1969
+ nimbusEquivalent: "Box",
1970
+ importPath: "@commercetools/nimbus",
1971
+ mappingType: "pattern",
1972
+ notes: "Use <Box padding={...}> with nimbus spacing tokens for inset padding.",
1973
+ breakingChanges: [
1974
+ "Replace Spacings.Inset with padding prop on Box",
1975
+ "Spacing values use design token scale"
1976
+ ]
1977
+ },
1978
+ {
1979
+ uiKitName: "Spacings.InsetSquish",
1980
+ nimbusEquivalent: "Box",
1981
+ importPath: "@commercetools/nimbus",
1982
+ mappingType: "pattern",
1983
+ notes: "Use <Box paddingX={...} paddingY={...}> with asymmetric nimbus spacing tokens.",
1984
+ breakingChanges: [
1985
+ "Replace Spacings.InsetSquish with paddingX/paddingY props on Box"
1986
+ ]
1987
+ },
1988
+ {
1989
+ uiKitName: "Spacings.Stack",
1990
+ nimbusEquivalent: "Stack",
1991
+ importPath: "@commercetools/nimbus",
1992
+ mappingType: "pattern",
1993
+ notes: 'Use <Stack direction="column" gap={...}> with nimbus spacing tokens.',
1994
+ breakingChanges: [
1995
+ "Replace Spacings.Stack with <Stack direction='column'>",
1996
+ "Spacing values use design token scale"
1997
+ ]
1998
+ },
1999
+ // -------------------------------------------------------------------------
2000
+ // Structure / containers
2001
+ // -------------------------------------------------------------------------
2002
+ {
2003
+ uiKitName: "Card",
2004
+ nimbusEquivalent: "Card",
2005
+ importPath: "@commercetools/nimbus",
2006
+ mappingType: "direct",
2007
+ notes: "Direct replacement. Composable with Card.Root, Card.Header, Card.Content.",
2008
+ breakingChanges: [
2009
+ "Adopt compositional slot API (Card.Root, Card.Header, Card.Content)"
2010
+ ]
2011
+ },
2012
+ {
2013
+ uiKitName: "CollapsiblePanel",
2014
+ nimbusEquivalent: "Accordion",
2015
+ importPath: "@commercetools/nimbus",
2016
+ mappingType: "direct",
2017
+ notes: "Rename to Accordion. Uses Accordion.Root, Accordion.Item, Accordion.Header, Accordion.Content composition. UI Kit used isClosed (controlled) + onToggle; the header was a prop, not a child slot.",
2018
+ breakingChanges: [
2019
+ "Rename to Accordion",
2020
+ "Adopt compositional slot API (Accordion.Root, Accordion.Item, Accordion.Header, Accordion.Content)",
2021
+ "isClosed prop replaced by React Aria controlled/uncontrolled pattern",
2022
+ "header prop replaced by Accordion.Header child",
2023
+ "condensed prop removed",
2024
+ "tone prop ('urgent'|'primary') replaced by Nimbus design tokens"
2025
+ ]
2026
+ },
2027
+ {
2028
+ uiKitName: "CollapsibleMotion",
2029
+ nimbusEquivalent: "CollapsibleMotion",
2030
+ importPath: "@commercetools/nimbus",
2031
+ mappingType: "compound",
2032
+ notes: "Uses compound pattern: CollapsibleMotion.Root, CollapsibleMotion.Trigger, CollapsibleMotion.Content. UI Kit used a render prop with isClosed/toggle; Nimbus manages state internally.",
2033
+ breakingChanges: [
2034
+ "Adopt compositional API (CollapsibleMotion.Root, CollapsibleMotion.Trigger, CollapsibleMotion.Content)",
2035
+ "Render prop pattern replaced by compound component children"
2036
+ ]
2037
+ },
2038
+ // -------------------------------------------------------------------------
2039
+ // Typography
2040
+ // -------------------------------------------------------------------------
2041
+ {
2042
+ uiKitName: "Text.Body",
2043
+ nimbusEquivalent: "Text",
2044
+ importPath: "@commercetools/nimbus",
2045
+ mappingType: "variant",
2046
+ notes: 'Use <Text size="md"> (default size).',
2047
+ breakingChanges: ["Replace Text.Body with <Text> (default size is body)"]
2048
+ },
2049
+ {
2050
+ uiKitName: "Text.Caption",
2051
+ nimbusEquivalent: "Text",
2052
+ importPath: "@commercetools/nimbus",
2053
+ mappingType: "variant",
2054
+ notes: 'Use <Text size="xs"> for caption-sized text.',
2055
+ breakingChanges: ["Replace Text.Caption with <Text size='xs'>"]
2056
+ },
2057
+ {
2058
+ uiKitName: "Text.Detail",
2059
+ nimbusEquivalent: "Text",
2060
+ importPath: "@commercetools/nimbus",
2061
+ mappingType: "variant",
2062
+ notes: 'Use <Text size="sm"> for detail/small text.',
2063
+ breakingChanges: ["Replace Text.Detail with <Text size='sm'>"]
2064
+ },
2065
+ {
2066
+ uiKitName: "Text.Headline",
2067
+ nimbusEquivalent: "Text",
2068
+ importPath: "@commercetools/nimbus",
2069
+ mappingType: "variant",
2070
+ notes: 'Use <Text size="2xl" fontWeight="bold"> or the Heading component.',
2071
+ breakingChanges: [
2072
+ "Replace Text.Headline with <Text size='2xl' fontWeight='bold'> or <Heading>"
2073
+ ]
2074
+ },
2075
+ {
2076
+ uiKitName: "Text.Subheadline",
2077
+ nimbusEquivalent: "Text",
2078
+ importPath: "@commercetools/nimbus",
2079
+ mappingType: "variant",
2080
+ notes: 'Use <Text size="xl">.',
2081
+ breakingChanges: ["Replace Text.Subheadline with <Text size='xl'>"]
2082
+ },
2083
+ {
2084
+ uiKitName: "Text.Wrap",
2085
+ nimbusEquivalent: "Text",
2086
+ importPath: "@commercetools/nimbus",
2087
+ mappingType: "variant",
2088
+ notes: "Use <Text> with the wrapping element set via the as prop.",
2089
+ breakingChanges: [
2090
+ "Replace Text.Wrap with <Text> and control wrapping via CSS/props"
2091
+ ]
2092
+ },
2093
+ {
2094
+ uiKitName: "Label",
2095
+ nimbusEquivalent: "Text",
2096
+ importPath: "@commercetools/nimbus",
2097
+ mappingType: "variant",
2098
+ notes: 'Use <Text as="label" size="sm" fontWeight="medium"> or FormField label prop.',
2099
+ breakingChanges: [
2100
+ "Replace Label with <Text as='label'> or use FormField label prop"
2101
+ ]
2102
+ },
2103
+ // -------------------------------------------------------------------------
2104
+ // Icons
2105
+ // -------------------------------------------------------------------------
2106
+ {
2107
+ uiKitName: "CustomIcon",
2108
+ nimbusEquivalent: "Icon",
2109
+ importPath: "@commercetools/nimbus",
2110
+ mappingType: "variant",
2111
+ notes: "Use <Icon> component wrapping an SVG, or use InlineSvg for custom SVGs.",
2112
+ breakingChanges: [
2113
+ "Replace CustomIcon with <Icon> or <InlineSvg>",
2114
+ "SVG must be passed as a child or via as prop"
2115
+ ]
2116
+ },
2117
+ {
2118
+ uiKitName: "LeadingIcon",
2119
+ nimbusEquivalent: "Icon",
2120
+ importPath: "@commercetools/nimbus",
2121
+ mappingType: "variant",
2122
+ notes: "Pass icon as a child to the parent component (e.g. as a child of <Button>) rather than using a wrapper.",
2123
+ breakingChanges: [
2124
+ "Remove LeadingIcon wrapper",
2125
+ "Pass icon directly to the parent component's icon slot"
2126
+ ]
2127
+ },
2128
+ {
2129
+ uiKitName: "InlineSvg",
2130
+ nimbusEquivalent: "InlineSvg",
2131
+ importPath: "@commercetools/nimbus",
2132
+ mappingType: "direct",
2133
+ notes: "Direct replacement for custom SVG icons not in the icon library.",
2134
+ breakingChanges: []
2135
+ },
2136
+ {
2137
+ uiKitName: "Icon Library",
2138
+ nimbusEquivalent: "Material Icon Library",
2139
+ importPath: "@commercetools/nimbus-icons",
2140
+ mappingType: "pattern",
2141
+ notes: "Import icons from @commercetools/nimbus-icons. Icons are named SvgIconName (e.g. SvgAccountCircle).",
2142
+ breakingChanges: [
2143
+ "Update import paths to @commercetools/nimbus-icons",
2144
+ "Icon names follow Svg prefix convention"
2145
+ ]
2146
+ },
2147
+ // -------------------------------------------------------------------------
2148
+ // Accessibility utilities
2149
+ // -------------------------------------------------------------------------
2150
+ {
2151
+ uiKitName: "HiddenInput",
2152
+ nimbusEquivalent: "VisuallyHidden",
2153
+ importPath: "@commercetools/nimbus",
2154
+ mappingType: "direct",
2155
+ notes: "VisuallyHidden renders content that is visually hidden but accessible to screen readers.",
2156
+ breakingChanges: ["Rename to VisuallyHidden"]
2157
+ },
2158
+ {
2159
+ uiKitName: "AccessibleHidden",
2160
+ nimbusEquivalent: "VisuallyHidden",
2161
+ importPath: "@commercetools/nimbus",
2162
+ mappingType: "variant",
2163
+ notes: "Use VisuallyHidden for content that should be screen-reader accessible only.",
2164
+ breakingChanges: ["Replace AccessibleHidden with VisuallyHidden"]
2165
+ },
2166
+ // -------------------------------------------------------------------------
2167
+ // Provider
2168
+ // -------------------------------------------------------------------------
2169
+ {
2170
+ uiKitName: "ThemeProvider",
2171
+ nimbusEquivalent: "NimbusProvider",
2172
+ importPath: "@commercetools/nimbus",
2173
+ mappingType: "direct",
2174
+ notes: "Rename to NimbusProvider. Wrap your app root once; passes theme and i18n context.",
2175
+ breakingChanges: [
2176
+ "Rename to NimbusProvider",
2177
+ "theme prop configuration has changed; see NimbusProvider docs"
2178
+ ]
2179
+ }
2180
+ ];
2181
+ var MIGRATION_MAP = new Map(
2182
+ MIGRATION_DATA.map((entry) => [entry.uiKitName, entry])
2183
+ );
2184
+ function getUiKitMigration(uiKitName) {
2185
+ return MIGRATION_MAP.get(uiKitName);
2186
+ }
2187
+ function getAllUiKitMigrations() {
2188
+ return MIGRATION_DATA;
2189
+ }
2190
+ var COMPOUND_ROOT_MAP = /* @__PURE__ */ new Map();
2191
+ for (const entry of MIGRATION_DATA) {
2192
+ const dotIdx = entry.uiKitName.indexOf(".");
2193
+ if (dotIdx > 0) {
2194
+ const root = entry.uiKitName.slice(0, dotIdx);
2195
+ const existing = COMPOUND_ROOT_MAP.get(root);
2196
+ if (existing) {
2197
+ existing.push(entry);
2198
+ } else {
2199
+ COMPOUND_ROOT_MAP.set(root, [entry]);
2200
+ }
2201
+ }
2202
+ }
2203
+ function getUiKitCompoundMigrations(rootName) {
2204
+ return COMPOUND_ROOT_MAP.get(rootName);
2205
+ }
2206
+
2207
+ // src/tools/migrate-from-uikit.ts
2208
+ var UIKIT_IMPORT_REGEX = /import\s+(?!type\s)(?:(\w+)(?:\s*,\s*\{([^}]*?)\})?\s+from\s+|\{([^}]*?)\}\s+from\s+)['"]@commercetools-uikit\/([^'"]+)['"]/gs;
2209
+ var UIKIT_BARREL_IMPORT_REGEX = /import\s+(?!type\s)\{([^}]+)\}\s+from\s+['"]@commercetools-frontend\/ui-kit['"]/g;
2210
+ var PACKAGE_TO_COMPONENT = {
2211
+ // Packages whose name differs from the exported component
2212
+ buttons: "PrimaryButton",
2213
+ // multi-export; we'll use named imports instead
2214
+ "flat-button": "FlatButton",
2215
+ "link-button": "LinkButton",
2216
+ "primary-button": "PrimaryButton",
2217
+ "secondary-button": "SecondaryButton",
2218
+ "icon-button": "IconButton",
2219
+ "text-input": "TextInput",
2220
+ "number-input": "NumberInput",
2221
+ "money-input": "MoneyInput",
2222
+ "password-input": "PasswordInput",
2223
+ "multiline-text-input": "MultilineTextInput",
2224
+ "rich-text-input": "RichTextInput",
2225
+ "date-input": "DateInput",
2226
+ "date-time-input": "DateTimeInput",
2227
+ "date-range-input": "DateRangeInput",
2228
+ "time-input": "TimeInput",
2229
+ "search-text-input": "SearchTextInput",
2230
+ "checkbox-input": "CheckboxInput",
2231
+ "radio-input": "RadioInput",
2232
+ "toggle-input": "ToggleInput",
2233
+ "localized-text-input": "LocalizedTextInput",
2234
+ "localized-multiline-text-input": "LocalizedMultilineTextInput",
2235
+ "localized-rich-text-input": "LocalizedRichTextInput",
2236
+ "loading-spinner": "LoadingSpinner",
2237
+ "progress-bar": "ProgressBar",
2238
+ "data-table": "DataTable",
2239
+ "data-table-manager": "DataTableManager",
2240
+ "dropdown-menu": "DropdownMenu",
2241
+ "content-notification": "ContentNotification",
2242
+ "accessible-button": "AccessibleButton",
2243
+ "accessible-hidden": "AccessibleHidden",
2244
+ "hidden-input": "HiddenInput",
2245
+ "collapsible-panel": "CollapsiblePanel",
2246
+ "collapsible-motion": "CollapsibleMotion",
2247
+ "field-errors": "FieldErrors",
2248
+ text: "Text",
2249
+ label: "Label",
2250
+ tag: "Tag",
2251
+ stamp: "Stamp",
2252
+ link: "Link",
2253
+ card: "Card",
2254
+ grid: "Grid",
2255
+ avatar: "Avatar",
2256
+ tooltip: "Tooltip",
2257
+ pagination: "Pagination",
2258
+ spacings: "Spacings",
2259
+ constraints: "Constraints",
2260
+ icons: "Icon Library",
2261
+ "inline-svg": "InlineSvg"
2262
+ };
2263
+ function extractUiKitComponents(fileContent) {
2264
+ const components = /* @__PURE__ */ new Set();
2265
+ let match;
2266
+ UIKIT_IMPORT_REGEX.lastIndex = 0;
2267
+ while ((match = UIKIT_IMPORT_REGEX.exec(fileContent)) !== null) {
2268
+ const defaultImport = match[1];
2269
+ const namedImports = match[2] || match[3];
2270
+ const packageName = match[4];
2271
+ if (defaultImport) {
2272
+ const mapped = PACKAGE_TO_COMPONENT[packageName];
2273
+ if (mapped) {
2274
+ components.add(mapped);
2275
+ } else {
2276
+ components.add(defaultImport);
2277
+ }
2278
+ }
2279
+ if (namedImports) {
2280
+ for (const name of namedImports.split(",")) {
2281
+ const trimmed = name.trim().split(/\s+as\s+/)[0].trim();
2282
+ if (trimmed && !trimmed.startsWith("type ")) components.add(trimmed);
2283
+ }
2284
+ }
2285
+ }
2286
+ UIKIT_BARREL_IMPORT_REGEX.lastIndex = 0;
2287
+ while ((match = UIKIT_BARREL_IMPORT_REGEX.exec(fileContent)) !== null) {
2288
+ for (const name of match[1].split(",")) {
2289
+ const trimmed = name.trim().split(/\s+as\s+/)[0].trim();
2290
+ if (trimmed) components.add(trimmed);
2291
+ }
2292
+ }
2293
+ return [...components];
2294
+ }
2295
+ var _caseInsensitiveMap;
2296
+ function getCaseInsensitiveMap() {
2297
+ if (!_caseInsensitiveMap) {
2298
+ _caseInsensitiveMap = new Map(
2299
+ getAllUiKitMigrations().map((e) => [
2300
+ e.uiKitName.toLowerCase(),
2301
+ e.uiKitName
2302
+ ])
2303
+ );
2304
+ }
2305
+ return _caseInsensitiveMap;
2306
+ }
2307
+ function deriveToolHint2(uiKitName, nimbusEquivalent, importPath, notes) {
2308
+ if (importPath === "@commercetools/nimbus-icons") {
2309
+ return 'Use the search_icons tool to find Nimbus icons by name (e.g. search_icons(query: "arrow"))';
2310
+ }
2311
+ if (uiKitName === "CustomIcon" || uiKitName === "LeadingIcon" || uiKitName === "InlineSvg") {
2312
+ return 'Use the search_icons tool to find the Nimbus equivalent icon (e.g. search_icons(query: "checkmark"))';
2313
+ }
2314
+ if (importPath === "@commercetools/nimbus-tokens") {
2315
+ return 'Use the get_tokens tool to browse available design tokens (e.g. get_tokens(category: "spacing"))';
2316
+ }
2317
+ if (notes.includes("spacing token") || notes.includes("design token")) {
2318
+ return 'Use the get_tokens tool to find the correct token values (e.g. get_tokens(category: "spacing"))';
2319
+ }
2320
+ if (importPath === "@commercetools/nimbus" && nimbusEquivalent) {
2321
+ return `Use the get_component tool to see full API docs (e.g. get_component(name: "${nimbusEquivalent}"))`;
2322
+ }
2323
+ return void 0;
2324
+ }
2325
+ function buildComponentResult(uiKitName) {
2326
+ const entry = getUiKitMigration(uiKitName);
2327
+ if (!entry) return null;
2328
+ const result = {
2329
+ uiKitName: entry.uiKitName,
2330
+ nimbusEquivalent: entry.nimbusEquivalent,
2331
+ importPath: entry.importPath,
2332
+ mappingType: entry.mappingType,
2333
+ notes: entry.notes,
2334
+ breakingChanges: entry.breakingChanges
2335
+ };
2336
+ const hint = deriveToolHint2(
2337
+ uiKitName,
2338
+ entry.nimbusEquivalent,
2339
+ entry.importPath,
2340
+ entry.notes
2341
+ );
2342
+ if (hint) result.hint = hint;
2343
+ return result;
2344
+ }
2345
+ function registerMigrateFromUiKit(server) {
2346
+ server.registerTool(
2347
+ "migrate_from_uikit",
2348
+ {
2349
+ title: "Migrate from UI Kit",
2350
+ description: "Returns migration mapping data for UI Kit components to their Nimbus equivalents. Use componentName for a single lookup, or filePath to extract all UI Kit imports from a file and get mappings for each. The MCP provides data; the LLM does the actual code rewriting.",
2351
+ inputSchema: {
2352
+ componentName: z6.string().optional().describe(
2353
+ 'UI Kit component name to look up, e.g. "PrimaryButton", "TextInput", "CollapsiblePanel".'
2354
+ ),
2355
+ filePath: z6.string().optional().describe(
2356
+ "Absolute path to a source file. Extracts @commercetools-uikit/* imports and returns mappings for all found components."
2357
+ )
2358
+ }
2359
+ },
2360
+ async ({ componentName, filePath }) => {
2361
+ if (!componentName && !filePath) {
2362
+ return {
2363
+ content: [
2364
+ {
2365
+ type: "text",
2366
+ text: 'Either "componentName" or "filePath" must be provided.'
2367
+ }
2368
+ ],
2369
+ isError: true
2370
+ };
2371
+ }
2372
+ if (componentName) {
2373
+ const result = buildComponentResult(componentName);
2374
+ if (result) {
2375
+ return {
2376
+ content: [
2377
+ {
2378
+ type: "text",
2379
+ text: JSON.stringify(result)
2380
+ }
2381
+ ]
2382
+ };
2383
+ }
2384
+ const compoundEntries = getUiKitCompoundMigrations(componentName);
2385
+ if (compoundEntries) {
2386
+ const response2 = {
2387
+ compoundRoot: componentName,
2388
+ note: `"${componentName}" is used as a namespace (e.g. ${compoundEntries.map((e) => e.uiKitName).join(", ")}). Each sub-component has its own mapping.`,
2389
+ mappings: compoundEntries.map(
2390
+ (e) => buildComponentResult(e.uiKitName)
2391
+ )
2392
+ };
2393
+ return {
2394
+ content: [
2395
+ {
2396
+ type: "text",
2397
+ text: JSON.stringify(response2)
2398
+ }
2399
+ ]
2400
+ };
2401
+ }
2402
+ const fuzzy = getCaseInsensitiveMap().get(componentName.toLowerCase());
2403
+ if (fuzzy) {
2404
+ return {
2405
+ content: [
2406
+ {
2407
+ type: "text",
2408
+ text: JSON.stringify(buildComponentResult(fuzzy))
2409
+ }
2410
+ ]
2411
+ };
2412
+ }
2413
+ return {
2414
+ content: [
2415
+ {
2416
+ type: "text",
2417
+ text: `No migration mapping found for "${componentName}". Use a UI Kit component name like "PrimaryButton", "TextInput", etc.`
2418
+ }
2419
+ ],
2420
+ isError: true
2421
+ };
2422
+ }
2423
+ let fileContent;
2424
+ try {
2425
+ fileContent = await readFile3(filePath, "utf-8");
2426
+ } catch {
2427
+ return {
2428
+ content: [
2429
+ {
2430
+ type: "text",
2431
+ text: `Could not read file "${filePath}".`
2432
+ }
2433
+ ],
2434
+ isError: true
2435
+ };
2436
+ }
2437
+ const componentNames = extractUiKitComponents(fileContent);
2438
+ if (componentNames.length === 0) {
2439
+ const emptyResponse = {
2440
+ filePath,
2441
+ mappings: [],
2442
+ unmapped: []
2443
+ };
2444
+ return {
2445
+ content: [
2446
+ {
2447
+ type: "text",
2448
+ text: JSON.stringify(emptyResponse)
2449
+ }
2450
+ ]
2451
+ };
2452
+ }
2453
+ const mappings = [];
2454
+ const unmapped = [];
2455
+ for (const name of componentNames) {
2456
+ const result = buildComponentResult(name);
2457
+ if (result) {
2458
+ mappings.push(result);
2459
+ continue;
2460
+ }
2461
+ const compoundEntries = getUiKitCompoundMigrations(name);
2462
+ if (compoundEntries) {
2463
+ const used = compoundEntries.filter(
2464
+ (entry) => fileContent.includes(entry.uiKitName)
2465
+ );
2466
+ const toInclude = used.length > 0 ? used : compoundEntries;
2467
+ for (const entry of toInclude) {
2468
+ mappings.push(buildComponentResult(entry.uiKitName));
2469
+ }
2470
+ continue;
2471
+ }
2472
+ unmapped.push(name);
2473
+ }
2474
+ const response = {
2475
+ filePath,
2476
+ mappings,
2477
+ unmapped
2478
+ };
2479
+ return {
2480
+ content: [
2481
+ {
2482
+ type: "text",
2483
+ text: JSON.stringify(response)
2484
+ }
2485
+ ]
2486
+ };
2487
+ }
2488
+ );
2489
+ }
2490
+
2491
+ // src/server.ts
2492
+ function createServer() {
2493
+ const server = new McpServer(
2494
+ {
2495
+ name: "nimbus-mcp",
2496
+ version: "0.1.0"
2497
+ },
2498
+ {
2499
+ capabilities: {
2500
+ tools: {}
2501
+ }
2502
+ }
2503
+ );
2504
+ registerGetComponent(server);
2505
+ registerGetTokens(server);
2506
+ registerListComponents(server);
2507
+ registerSearchDocs(server);
2508
+ registerSearchIcons(server);
2509
+ registerMigrateFromUiKit(server);
2510
+ return server;
2511
+ }
2512
+
2513
+ // src/index.ts
15
2514
  async function main() {
16
- const server = createServer();
17
- const transport = new StdioServerTransport();
18
- await server.connect(transport);
2515
+ const server = createServer();
2516
+ const transport = new StdioServerTransport();
2517
+ await server.connect(transport);
19
2518
  }
20
2519
  main().catch((error) => {
21
- console.error("Nimbus MCP server error:", error);
22
- process.exit(1);
2520
+ console.error("Nimbus MCP server error:", error);
2521
+ process.exit(1);
23
2522
  });