@epilot/zenith-react 0.2.0-next.3 → 0.2.0-next.5

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 (274) hide show
  1. package/README.md +37 -1
  2. package/codemods/README.md +182 -0
  3. package/codemods/format.ts +86 -0
  4. package/codemods/migrate/base-elements/accordion.ts +132 -0
  5. package/codemods/migrate/base-elements/alert.ts +81 -0
  6. package/codemods/migrate/base-elements/avatar.ts +116 -0
  7. package/codemods/migrate/base-elements/button.ts +188 -0
  8. package/codemods/migrate/base-elements/checkbox.ts +17 -0
  9. package/codemods/migrate/base-elements/chip.ts +87 -0
  10. package/codemods/migrate/base-elements/chip360.ts +162 -0
  11. package/codemods/migrate/base-elements/circular-progress.ts +73 -0
  12. package/codemods/migrate/base-elements/dialog.ts +323 -0
  13. package/codemods/migrate/base-elements/divider.ts +61 -0
  14. package/codemods/migrate/base-elements/feedback-message.ts +95 -0
  15. package/codemods/migrate/base-elements/icon-button.ts +203 -0
  16. package/codemods/migrate/base-elements/index.ts +55 -0
  17. package/codemods/migrate/base-elements/mui-props.ts +29 -0
  18. package/codemods/migrate/base-elements/notification.ts +98 -0
  19. package/codemods/migrate/base-elements/paper.ts +78 -0
  20. package/codemods/migrate/base-elements/select.ts +328 -0
  21. package/codemods/migrate/base-elements/shared.ts +910 -0
  22. package/codemods/migrate/base-elements/skeleton.ts +83 -0
  23. package/codemods/migrate/base-elements/switch.ts +19 -0
  24. package/codemods/migrate/base-elements/tabs.ts +222 -0
  25. package/codemods/migrate/base-elements/text-field.ts +425 -0
  26. package/codemods/migrate/base-elements/toggle-button.ts +185 -0
  27. package/codemods/migrate/base-elements/tooltip.ts +231 -0
  28. package/codemods/migrate/base-elements/typography.ts +247 -0
  29. package/codemods/migrate/base-elements/unsupported.ts +277 -0
  30. package/codemods/migrate/from-base-elements.ts +26 -0
  31. package/codemods/migrate/from-volt.ts +26 -0
  32. package/codemods/migrate/lib/imports.ts +399 -0
  33. package/codemods/migrate/lib/jsx.ts +313 -0
  34. package/codemods/migrate/lib/run-migration.ts +528 -0
  35. package/codemods/migrate/lib/source.ts +6 -0
  36. package/codemods/migrate/lib/todo.ts +107 -0
  37. package/codemods/migrate/lib/types.ts +114 -0
  38. package/codemods/migrate/volt/class-helpers.ts +37 -0
  39. package/codemods/migrate/volt/index.ts +18 -0
  40. package/codemods/migrate/volt/pagination.ts +26 -0
  41. package/codemods/migrate/volt/same-name.ts +293 -0
  42. package/codemods/migrate/volt/stylesheets.ts +18 -0
  43. package/codemods/migrate/volt/tanstack-types.ts +20 -0
  44. package/codemods/radix-to-base-ui.ts +677 -0
  45. package/dist/_virtual/_zenith-runtime-family_accordion.js +7 -0
  46. package/dist/_virtual/_zenith-runtime-family_accordion.js.map +1 -0
  47. package/dist/_virtual/_zenith-runtime-family_alert-dialog.js +7 -0
  48. package/dist/_virtual/_zenith-runtime-family_alert-dialog.js.map +1 -0
  49. package/dist/_virtual/_zenith-runtime-family_avatar.js +7 -0
  50. package/dist/_virtual/_zenith-runtime-family_avatar.js.map +1 -0
  51. package/dist/_virtual/_zenith-runtime-family_button.js +7 -0
  52. package/dist/_virtual/_zenith-runtime-family_button.js.map +1 -0
  53. package/dist/_virtual/_zenith-runtime-family_checkbox.js +7 -0
  54. package/dist/_virtual/_zenith-runtime-family_checkbox.js.map +1 -0
  55. package/dist/_virtual/_zenith-runtime-family_csp-provider.js +7 -0
  56. package/dist/_virtual/_zenith-runtime-family_csp-provider.js.map +1 -0
  57. package/dist/_virtual/_zenith-runtime-family_dialog.js +7 -0
  58. package/dist/_virtual/_zenith-runtime-family_dialog.js.map +1 -0
  59. package/dist/_virtual/_zenith-runtime-family_direction-provider.js +8 -0
  60. package/dist/_virtual/_zenith-runtime-family_direction-provider.js.map +1 -0
  61. package/dist/_virtual/_zenith-runtime-family_menu.js +7 -0
  62. package/dist/_virtual/_zenith-runtime-family_menu.js.map +1 -0
  63. package/dist/_virtual/_zenith-runtime-family_merge-props.js +11 -0
  64. package/dist/_virtual/_zenith-runtime-family_merge-props.js.map +1 -0
  65. package/dist/_virtual/_zenith-runtime-family_popover.js +7 -0
  66. package/dist/_virtual/_zenith-runtime-family_popover.js.map +1 -0
  67. package/dist/_virtual/_zenith-runtime-family_radio-group.js +7 -0
  68. package/dist/_virtual/_zenith-runtime-family_radio-group.js.map +1 -0
  69. package/dist/_virtual/_zenith-runtime-family_radio.js +7 -0
  70. package/dist/_virtual/_zenith-runtime-family_radio.js.map +1 -0
  71. package/dist/_virtual/_zenith-runtime-family_scroll-area.js +7 -0
  72. package/dist/_virtual/_zenith-runtime-family_scroll-area.js.map +1 -0
  73. package/dist/_virtual/_zenith-runtime-family_select.js +7 -0
  74. package/dist/_virtual/_zenith-runtime-family_select.js.map +1 -0
  75. package/dist/_virtual/_zenith-runtime-family_separator.js +7 -0
  76. package/dist/_virtual/_zenith-runtime-family_separator.js.map +1 -0
  77. package/dist/_virtual/_zenith-runtime-family_switch.js +7 -0
  78. package/dist/_virtual/_zenith-runtime-family_switch.js.map +1 -0
  79. package/dist/_virtual/_zenith-runtime-family_tabs.js +7 -0
  80. package/dist/_virtual/_zenith-runtime-family_tabs.js.map +1 -0
  81. package/dist/_virtual/_zenith-runtime-family_toast.js +7 -0
  82. package/dist/_virtual/_zenith-runtime-family_toast.js.map +1 -0
  83. package/dist/_virtual/_zenith-runtime-family_toggle-group.js +7 -0
  84. package/dist/_virtual/_zenith-runtime-family_toggle-group.js.map +1 -0
  85. package/dist/_virtual/_zenith-runtime-family_toggle.js +7 -0
  86. package/dist/_virtual/_zenith-runtime-family_toggle.js.map +1 -0
  87. package/dist/_virtual/_zenith-runtime-family_tooltip.js +7 -0
  88. package/dist/_virtual/_zenith-runtime-family_tooltip.js.map +1 -0
  89. package/dist/_virtual/_zenith-runtime-family_use-render.js +7 -0
  90. package/dist/_virtual/_zenith-runtime-family_use-render.js.map +1 -0
  91. package/dist/components/accordion/accordion.js +179 -96
  92. package/dist/components/accordion/accordion.js.map +1 -1
  93. package/dist/components/alert-dialog/alert-dialog.js +243 -206
  94. package/dist/components/alert-dialog/alert-dialog.js.map +1 -1
  95. package/dist/components/avatar/avatar.js +94 -82
  96. package/dist/components/avatar/avatar.js.map +1 -1
  97. package/dist/components/badge/badge.js +11 -11
  98. package/dist/components/breadcrumb/breadcrumb.js +69 -70
  99. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  100. package/dist/components/button/button.js +119 -102
  101. package/dist/components/button/button.js.map +1 -1
  102. package/dist/components/checkbox/checkbox.js +68 -51
  103. package/dist/components/checkbox/checkbox.js.map +1 -1
  104. package/dist/components/date-range-picker/date-range-picker.js +100 -90
  105. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  106. package/dist/components/date-time-picker/date-time-picker-input.js +118 -108
  107. package/dist/components/date-time-picker/date-time-picker-input.js.map +1 -1
  108. package/dist/components/date-time-picker/date-time-picker-panel.js +91 -94
  109. package/dist/components/date-time-picker/date-time-picker-panel.js.map +1 -1
  110. package/dist/components/dialog/dialog.js +238 -228
  111. package/dist/components/dialog/dialog.js.map +1 -1
  112. package/dist/components/drawer/drawer.js +259 -321
  113. package/dist/components/drawer/drawer.js.map +1 -1
  114. package/dist/components/dropdown-menu/dropdown-menu.js +533 -279
  115. package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -1
  116. package/dist/components/field/field-combobox.js +205 -186
  117. package/dist/components/field/field-combobox.js.map +1 -1
  118. package/dist/components/field/field-select.js +37 -22
  119. package/dist/components/field/field-select.js.map +1 -1
  120. package/dist/components/list/list-sortable.js +104 -0
  121. package/dist/components/list/list-sortable.js.map +1 -0
  122. package/dist/components/list/list.js +246 -324
  123. package/dist/components/list/list.js.map +1 -1
  124. package/dist/components/option-card/option-card.js +121 -117
  125. package/dist/components/option-card/option-card.js.map +1 -1
  126. package/dist/components/pill/pill.js +7 -7
  127. package/dist/components/popover/popover.js +223 -127
  128. package/dist/components/popover/popover.js.map +1 -1
  129. package/dist/components/radio/radio-group-base.js +54 -0
  130. package/dist/components/radio/radio-group-base.js.map +1 -0
  131. package/dist/components/radio/radio.js +71 -60
  132. package/dist/components/radio/radio.js.map +1 -1
  133. package/dist/components/scroll-area/scroll-area.js +142 -108
  134. package/dist/components/scroll-area/scroll-area.js.map +1 -1
  135. package/dist/components/scroll-overflow/scroll-overflow.js +156 -127
  136. package/dist/components/scroll-overflow/scroll-overflow.js.map +1 -1
  137. package/dist/components/segmented-control/segmented-control.js +93 -81
  138. package/dist/components/segmented-control/segmented-control.js.map +1 -1
  139. package/dist/components/select/select.js +485 -310
  140. package/dist/components/select/select.js.map +1 -1
  141. package/dist/components/separator/separator.js.map +1 -1
  142. package/dist/components/slot/compose-as-child.js +15 -12
  143. package/dist/components/slot/compose-as-child.js.map +1 -1
  144. package/dist/components/switch/switch.js +75 -68
  145. package/dist/components/switch/switch.js.map +1 -1
  146. package/dist/components/table/table-pagination.js +212 -175
  147. package/dist/components/table/table-pagination.js.map +1 -1
  148. package/dist/components/tabs/tabs.js +193 -190
  149. package/dist/components/tabs/tabs.js.map +1 -1
  150. package/dist/components/toast/toast.js +610 -148
  151. package/dist/components/toast/toast.js.map +1 -1
  152. package/dist/components/toggle/toggle-group.js +143 -32
  153. package/dist/components/toggle/toggle-group.js.map +1 -1
  154. package/dist/components/toggle/toggle.js +82 -49
  155. package/dist/components/toggle/toggle.js.map +1 -1
  156. package/dist/components/tooltip/tooltip.js +298 -138
  157. package/dist/components/tooltip/tooltip.js.map +1 -1
  158. package/dist/index.d.ts +2336 -2130
  159. package/dist/index.js +24 -23
  160. package/dist/list/sortable/index.d.ts +29 -0
  161. package/dist/list/sortable/index.js +5 -0
  162. package/dist/{_virtual → list/sortable}/index.js.map +1 -1
  163. package/dist/packages/tokens/dist/delivery/index.js +10 -10
  164. package/dist/packages/tokens/dist/delivery/index.js.map +1 -1
  165. package/dist/packages/tokens/dist/generated/core.generated.js +6 -15
  166. package/dist/packages/tokens/dist/generated/core.generated.js.map +1 -1
  167. package/dist/packages/tokens/dist/generated/palette.generated.js +4 -5
  168. package/dist/packages/tokens/dist/generated/palette.generated.js.map +1 -1
  169. package/dist/packages/tokens/dist/generated/palette.meta.generated.js +5 -0
  170. package/dist/packages/tokens/dist/generated/palette.meta.generated.js.map +1 -0
  171. package/dist/packages/tokens/dist/install.js +40 -17
  172. package/dist/packages/tokens/dist/install.js.map +1 -1
  173. package/dist/renderer/runtime-contract.generated.js +8 -0
  174. package/dist/renderer/runtime-contract.generated.js.map +1 -0
  175. package/dist/renderer/served.js +39 -0
  176. package/dist/renderer/served.js.map +1 -0
  177. package/dist/tokens/core.meta.generated.js +2 -2
  178. package/dist/tokens/core.meta.generated.js.map +1 -1
  179. package/dist/tokens/index.d.ts +1028 -1028
  180. package/dist/tokens/index.js +863 -863
  181. package/dist/tokens/index.js.map +1 -1
  182. package/dist/tokens/palette.meta.generated.js +5 -0
  183. package/dist/tokens/palette.meta.generated.js.map +1 -0
  184. package/dist/tokens.json +1 -1
  185. package/dist/vendor/.bun/@radix-ui_react-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-dialog/dist/index.js +57 -62
  186. package/dist/vendor/.bun/@radix-ui_react-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-dialog/dist/index.js.map +1 -1
  187. package/dist/vendor/.bun/@radix-ui_react-slot@1.2.3_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js +32 -38
  188. package/dist/vendor/.bun/@radix-ui_react-slot@1.2.3_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js.map +1 -1
  189. package/package.json +29 -21
  190. package/scripts/migration-diagnostics-core.mjs +302 -10
  191. package/scripts/migration-diagnostics.mjs +31 -8
  192. package/scripts/migration-sweep.mjs +10 -10
  193. package/testing/setup.cjs +87 -0
  194. package/dist/_virtual/index.js +0 -6
  195. package/dist/_virtual/index2.js +0 -5
  196. package/dist/_virtual/index2.js.map +0 -1
  197. package/dist/_virtual/use-sync-external-store-shim.development.js +0 -5
  198. package/dist/_virtual/use-sync-external-store-shim.development.js.map +0 -1
  199. package/dist/_virtual/use-sync-external-store-shim.production.js +0 -5
  200. package/dist/_virtual/use-sync-external-store-shim.production.js.map +0 -1
  201. package/dist/tokens/palette.generated.js +0 -5
  202. package/dist/tokens/palette.generated.js.map +0 -1
  203. package/dist/vendor/.bun/@floating-ui_core@1.8.0/vendor/@floating-ui/core/dist/floating-ui.core.js +0 -512
  204. package/dist/vendor/.bun/@floating-ui_core@1.8.0/vendor/@floating-ui/core/dist/floating-ui.core.js.map +0 -1
  205. package/dist/vendor/.bun/@floating-ui_dom@1.8.0/vendor/@floating-ui/dom/dist/floating-ui.dom.js +0 -396
  206. package/dist/vendor/.bun/@floating-ui_dom@1.8.0/vendor/@floating-ui/dom/dist/floating-ui.dom.js.map +0 -1
  207. package/dist/vendor/.bun/@floating-ui_react-dom@2.1.9_6f4b9a1cfb20c0ae/vendor/@floating-ui/react-dom/dist/floating-ui.react-dom.js +0 -233
  208. package/dist/vendor/.bun/@floating-ui_react-dom@2.1.9_6f4b9a1cfb20c0ae/vendor/@floating-ui/react-dom/dist/floating-ui.react-dom.js.map +0 -1
  209. package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.dom.js +0 -137
  210. package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +0 -1
  211. package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.js +0 -129
  212. package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.js.map +0 -1
  213. package/dist/vendor/.bun/@radix-ui_number@1.1.1/vendor/@radix-ui/number/dist/index.js +0 -7
  214. package/dist/vendor/.bun/@radix-ui_number@1.1.1/vendor/@radix-ui/number/dist/index.js.map +0 -1
  215. package/dist/vendor/.bun/@radix-ui_react-accordion@1.2.12_2b23df507bdda662/vendor/@radix-ui/react-accordion/dist/index.js +0 -240
  216. package/dist/vendor/.bun/@radix-ui_react-accordion@1.2.12_2b23df507bdda662/vendor/@radix-ui/react-accordion/dist/index.js.map +0 -1
  217. package/dist/vendor/.bun/@radix-ui_react-alert-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-alert-dialog/dist/index.js +0 -128
  218. package/dist/vendor/.bun/@radix-ui_react-alert-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-alert-dialog/dist/index.js.map +0 -1
  219. package/dist/vendor/.bun/@radix-ui_react-arrow@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-arrow/dist/index.js +0 -25
  220. package/dist/vendor/.bun/@radix-ui_react-arrow@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-arrow/dist/index.js.map +0 -1
  221. package/dist/vendor/.bun/@radix-ui_react-avatar@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-avatar/dist/index.js +0 -76
  222. package/dist/vendor/.bun/@radix-ui_react-avatar@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-avatar/dist/index.js.map +0 -1
  223. package/dist/vendor/.bun/@radix-ui_react-checkbox@1.3.3_2b23df507bdda662/vendor/@radix-ui/react-checkbox/dist/index.js +0 -252
  224. package/dist/vendor/.bun/@radix-ui_react-checkbox@1.3.3_2b23df507bdda662/vendor/@radix-ui/react-checkbox/dist/index.js.map +0 -1
  225. package/dist/vendor/.bun/@radix-ui_react-collapsible@1.1.12_2b23df507bdda662/vendor/@radix-ui/react-collapsible/dist/index.js +0 -121
  226. package/dist/vendor/.bun/@radix-ui_react-collapsible@1.1.12_2b23df507bdda662/vendor/@radix-ui/react-collapsible/dist/index.js.map +0 -1
  227. package/dist/vendor/.bun/@radix-ui_react-collection@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-collection/dist/index.js +0 -49
  228. package/dist/vendor/.bun/@radix-ui_react-collection@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-collection/dist/index.js.map +0 -1
  229. package/dist/vendor/.bun/@radix-ui_react-direction@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-direction/dist/index.js +0 -11
  230. package/dist/vendor/.bun/@radix-ui_react-direction@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-direction/dist/index.js.map +0 -1
  231. package/dist/vendor/.bun/@radix-ui_react-dropdown-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-dropdown-menu/dist/index.js +0 -228
  232. package/dist/vendor/.bun/@radix-ui_react-dropdown-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-dropdown-menu/dist/index.js.map +0 -1
  233. package/dist/vendor/.bun/@radix-ui_react-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-menu/dist/index.js +0 -653
  234. package/dist/vendor/.bun/@radix-ui_react-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-menu/dist/index.js.map +0 -1
  235. package/dist/vendor/.bun/@radix-ui_react-popover@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-popover/dist/index.js +0 -244
  236. package/dist/vendor/.bun/@radix-ui_react-popover@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-popover/dist/index.js.map +0 -1
  237. package/dist/vendor/.bun/@radix-ui_react-popper@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-popper/dist/index.js +0 -222
  238. package/dist/vendor/.bun/@radix-ui_react-popper@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-popper/dist/index.js.map +0 -1
  239. package/dist/vendor/.bun/@radix-ui_react-radio-group@1.3.8_2b23df507bdda662/vendor/@radix-ui/react-radio-group/dist/index.js +0 -239
  240. package/dist/vendor/.bun/@radix-ui_react-radio-group@1.3.8_2b23df507bdda662/vendor/@radix-ui/react-radio-group/dist/index.js.map +0 -1
  241. package/dist/vendor/.bun/@radix-ui_react-roving-focus@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-roving-focus/dist/index.js +0 -184
  242. package/dist/vendor/.bun/@radix-ui_react-roving-focus@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-roving-focus/dist/index.js.map +0 -1
  243. package/dist/vendor/.bun/@radix-ui_react-scroll-area@1.2.10_2b23df507bdda662/vendor/@radix-ui/react-scroll-area/dist/index.js +0 -535
  244. package/dist/vendor/.bun/@radix-ui_react-scroll-area@1.2.10_2b23df507bdda662/vendor/@radix-ui/react-scroll-area/dist/index.js.map +0 -1
  245. package/dist/vendor/.bun/@radix-ui_react-select@2.2.6_2b23df507bdda662/vendor/@radix-ui/react-select/dist/index.js +0 -863
  246. package/dist/vendor/.bun/@radix-ui_react-select@2.2.6_2b23df507bdda662/vendor/@radix-ui/react-select/dist/index.js.map +0 -1
  247. package/dist/vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js +0 -63
  248. package/dist/vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js.map +0 -1
  249. package/dist/vendor/.bun/@radix-ui_react-switch@1.2.6_2b23df507bdda662/vendor/@radix-ui/react-switch/dist/index.js +0 -133
  250. package/dist/vendor/.bun/@radix-ui_react-switch@1.2.6_2b23df507bdda662/vendor/@radix-ui/react-switch/dist/index.js.map +0 -1
  251. package/dist/vendor/.bun/@radix-ui_react-tabs@1.1.13_2b23df507bdda662/vendor/@radix-ui/react-tabs/dist/index.js +0 -164
  252. package/dist/vendor/.bun/@radix-ui_react-tabs@1.1.13_2b23df507bdda662/vendor/@radix-ui/react-tabs/dist/index.js.map +0 -1
  253. package/dist/vendor/.bun/@radix-ui_react-toggle-group@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-toggle-group/dist/index.js +0 -138
  254. package/dist/vendor/.bun/@radix-ui_react-toggle-group@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-toggle-group/dist/index.js.map +0 -1
  255. package/dist/vendor/.bun/@radix-ui_react-toggle@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-toggle/dist/index.js +0 -34
  256. package/dist/vendor/.bun/@radix-ui_react-toggle@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-toggle/dist/index.js.map +0 -1
  257. package/dist/vendor/.bun/@radix-ui_react-tooltip@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-tooltip/dist/index.js +0 -340
  258. package/dist/vendor/.bun/@radix-ui_react-tooltip@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-tooltip/dist/index.js.map +0 -1
  259. package/dist/vendor/.bun/@radix-ui_react-use-is-hydrated@0.1.0_0ac650c021fb1b59/vendor/@radix-ui/react-use-is-hydrated/dist/index.js +0 -16
  260. package/dist/vendor/.bun/@radix-ui_react-use-is-hydrated@0.1.0_0ac650c021fb1b59/vendor/@radix-ui/react-use-is-hydrated/dist/index.js.map +0 -1
  261. package/dist/vendor/.bun/@radix-ui_react-use-previous@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-previous/dist/index.js +0 -9
  262. package/dist/vendor/.bun/@radix-ui_react-use-previous@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-previous/dist/index.js.map +0 -1
  263. package/dist/vendor/.bun/@radix-ui_react-use-size@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-size/dist/index.js +0 -28
  264. package/dist/vendor/.bun/@radix-ui_react-use-size@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-size/dist/index.js.map +0 -1
  265. package/dist/vendor/.bun/@radix-ui_react-visually-hidden@1.2.3_2b23df507bdda662/vendor/@radix-ui/react-visually-hidden/dist/index.js +0 -33
  266. package/dist/vendor/.bun/@radix-ui_react-visually-hidden@1.2.3_2b23df507bdda662/vendor/@radix-ui/react-visually-hidden/dist/index.js.map +0 -1
  267. package/dist/vendor/.bun/sonner@2.0.7_6f4b9a1cfb20c0ae/vendor/sonner/dist/index.js +0 -747
  268. package/dist/vendor/.bun/sonner@2.0.7_6f4b9a1cfb20c0ae/vendor/sonner/dist/index.js.map +0 -1
  269. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.development.js +0 -68
  270. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +0 -1
  271. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.production.js +0 -56
  272. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +0 -1
  273. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/shim/index.js +0 -11
  274. package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/shim/index.js.map +0 -1
@@ -0,0 +1,910 @@
1
+ /**
2
+ * Helpers shared by the structural base-elements rules: build parts, move props between
3
+ * elements, and rewrite MUI's `(event, value)` handlers into the value-only callbacks Zenith's
4
+ * primitives take. Not a rule: the registry does not list it.
5
+ */
6
+ import type {
7
+ ASTNode,
8
+ ASTPath,
9
+ JSCodeshift,
10
+ JSXAttribute,
11
+ JSXElement,
12
+ JSXSpreadAttribute,
13
+ } from "jscodeshift"
14
+ import { detectQuote } from "../lib/source"
15
+ import type { MigrateContext } from "../lib/types"
16
+
17
+ export type Child = NonNullable<JSXElement["children"]>[number]
18
+ type Expression = Parameters<JSCodeshift["expressionStatement"]>[0]
19
+ type Fn = {
20
+ type: string
21
+ params: { type: string; name?: string; typeAnnotation?: unknown }[]
22
+ body: ASTNode
23
+ }
24
+
25
+ /** Source text of a node as it prints now (its original text when unchanged). */
26
+ export function source(j: JSCodeshift, node: ASTNode): string {
27
+ return j(node as never).toSource()
28
+ }
29
+
30
+ /**
31
+ * Parses `code` into an expression that prints as written: recast reuses the text of parsed
32
+ * nodes, where it would lay out a built `{ width: "100%" }` over three lines.
33
+ */
34
+ export function parseExpression(j: JSCodeshift, code: string): Expression {
35
+ const declarator = j(`const value = ${code}`)
36
+ .find(j.VariableDeclarator)
37
+ .paths()[0]
38
+ return declarator.node.init as Expression
39
+ }
40
+
41
+ /** A string literal in the file's own quote style, for expressions (JSX attributes use `"`). */
42
+ export function stringIn(ctx: MigrateContext, value: string) {
43
+ return ctx.jsx.str(
44
+ value,
45
+ detectQuote(ctx.file.source) === "single" ? "'" : '"'
46
+ )
47
+ }
48
+
49
+ /**
50
+ * A JSX element that was an expression root (`return (<X />)`) keeps recast's `parenthesized`
51
+ * mark; among JSX children those parentheses would print as text.
52
+ */
53
+ function unparenthesize(children: Child[]): Child[] {
54
+ for (const child of children) {
55
+ const extra = (child as { extra?: { parenthesized?: boolean } }).extra
56
+ if (extra?.parenthesized) extra.parenthesized = false
57
+ }
58
+ return children
59
+ }
60
+
61
+ /** `<tag {...attrs}>{children}</tag>`, self-closing when there are no children. */
62
+ export function element(
63
+ j: JSCodeshift,
64
+ tag: string,
65
+ attrs: (JSXAttribute | JSXSpreadAttribute)[] = [],
66
+ children: Child[] = []
67
+ ): JSXElement {
68
+ const name = j.jsxIdentifier(tag)
69
+ if (children.length === 0)
70
+ return j.jsxElement(j.jsxOpeningElement(name, attrs, true), null, [])
71
+ return j.jsxElement(
72
+ j.jsxOpeningElement(name, attrs),
73
+ j.jsxClosingElement(j.jsxIdentifier(tag)),
74
+ unparenthesize(normalizeChildren(j, children))
75
+ )
76
+ }
77
+
78
+ /**
79
+ * Re-splits text children so recast keeps them when it reprints the element: it trims every
80
+ * text child, which would drop the space in `<b>x</b> world`. A line break becomes its own
81
+ * `"\n"` text (recast indents it) and a significant edge space becomes `{" "}`.
82
+ */
83
+ export function normalizeChildren(j: JSCodeshift, children: Child[]): Child[] {
84
+ const out: Child[] = []
85
+ const lineBreak = () => {
86
+ const prev = out[out.length - 1]
87
+ if (!(prev?.type === "JSXText" && prev.value === "\n"))
88
+ out.push(j.jsxText("\n"))
89
+ }
90
+ const space = () => out.push(j.jsxExpressionContainer(j.stringLiteral(" ")))
91
+ for (const child of children) {
92
+ if (child.type !== "JSXText") {
93
+ out.push(child)
94
+ continue
95
+ }
96
+ if (!/\S/.test(child.value)) {
97
+ if (child.value.includes("\n")) lineBreak()
98
+ else out.push(child)
99
+ continue
100
+ }
101
+ const [, lead, body, trail] = child.value.match(/^(\s*)([\s\S]*?)(\s*)$/)!
102
+ if (lead.includes("\n")) lineBreak()
103
+ else if (lead) space()
104
+ out.push(j.jsxText(body))
105
+ if (trail.includes("\n")) lineBreak()
106
+ else if (trail) space()
107
+ }
108
+ return out
109
+ }
110
+
111
+ /** Whether the children span lines (any text child holds a line break). */
112
+ export function isMultiline(children: Child[] | undefined): boolean {
113
+ return (children ?? []).some(
114
+ (c) => c.type === "JSXText" && c.value.includes("\n")
115
+ )
116
+ }
117
+
118
+ /**
119
+ * Sets the element's children, opening it up when it was self-closing. When the new array is
120
+ * as long as the parsed one, recast patches it slot by slot and loses the indentation of the
121
+ * new line breaks; an empty text child (it prints as nothing) makes it reprint the element.
122
+ */
123
+ export function setChildren(
124
+ j: JSCodeshift,
125
+ el: JSXElement,
126
+ children: Child[]
127
+ ): void {
128
+ const parsed = (el as { original?: JSXElement | null }).original
129
+ if (children.length && parsed?.children?.length === children.length)
130
+ children = [...children, j.jsxText("")]
131
+ el.children = children
132
+ if (children.length === 0) {
133
+ el.openingElement.selfClosing = true
134
+ el.closingElement = null
135
+ return
136
+ }
137
+ el.openingElement.selfClosing = false
138
+ if (!el.closingElement)
139
+ el.closingElement = j.jsxClosingElement(el.openingElement.name)
140
+ }
141
+
142
+ /** `[child]`, or `["\n", child, "\n"]` when the surrounding children spanned lines. */
143
+ export function onlyChild(
144
+ j: JSCodeshift,
145
+ child: Child,
146
+ multiline: boolean
147
+ ): Child[] {
148
+ return multiline ? [j.jsxText("\n"), child, j.jsxText("\n")] : [child]
149
+ }
150
+
151
+ /** Moves `el`'s children into a new `<tag {...attrs}>`, which becomes `el`'s only child. */
152
+ export function nestChildren(
153
+ j: JSCodeshift,
154
+ el: JSXElement,
155
+ tag: string,
156
+ attrs: (JSXAttribute | JSXSpreadAttribute)[] = []
157
+ ): JSXElement {
158
+ const multiline = isMultiline(el.children)
159
+ const inner = element(j, tag, attrs, el.children ?? [])
160
+ setChildren(j, el, onlyChild(j, inner, multiline))
161
+ return inner
162
+ }
163
+
164
+ /** Adds `child` first or last, on its own line when the element's children span lines. */
165
+ export function insertChild(
166
+ j: JSCodeshift,
167
+ el: JSXElement,
168
+ child: Child,
169
+ at: "start" | "end"
170
+ ): void {
171
+ const multiline = isMultiline(el.children)
172
+ const children = normalizeChildren(j, el.children ?? [])
173
+ const nl = () => j.jsxText("\n")
174
+ if (children.length === 0) setChildren(j, el, [child])
175
+ else if (!multiline)
176
+ setChildren(
177
+ j,
178
+ el,
179
+ at === "start" ? [child, ...children] : [...children, child]
180
+ )
181
+ else if (at === "start") setChildren(j, el, [nl(), child, ...children])
182
+ else setChildren(j, el, [...children, child, nl()])
183
+ }
184
+
185
+ /** Maps a string literal, or a conditional whose branches are string literals, through `map`. */
186
+ export function mapStringExpression(
187
+ j: JSCodeshift,
188
+ expression: Expression | undefined,
189
+ map: (value: string) => string | undefined,
190
+ literal: (value: string) => Expression = (value) => j.stringLiteral(value)
191
+ ): Expression | undefined {
192
+ if (!expression) return undefined
193
+ if (
194
+ expression.type === "StringLiteral" ||
195
+ (expression.type === "Literal" &&
196
+ typeof (expression as { value: unknown }).value === "string")
197
+ ) {
198
+ const next = map(String((expression as { value: unknown }).value))
199
+ return next === undefined ? undefined : literal(next)
200
+ }
201
+ if (expression.type === "ConditionalExpression") {
202
+ const consequent = mapStringExpression(
203
+ j,
204
+ expression.consequent,
205
+ map,
206
+ literal
207
+ )
208
+ const alternate = mapStringExpression(j, expression.alternate, map, literal)
209
+ if (!consequent || !alternate) return undefined
210
+ return j.conditionalExpression(
211
+ expression.test,
212
+ consequent as never,
213
+ alternate as never
214
+ )
215
+ }
216
+ return undefined
217
+ }
218
+
219
+ /**
220
+ * `jsx.mapAttrValue` (literals and ternaries of literals) with a Zenith default and a rename: a
221
+ * value mapping to `fallback` drops the attribute (`undefined` in a ternary), and a mapped
222
+ * attribute takes the name `rename`, replacing one of that name. Returns `false`, leaving the
223
+ * attribute as it was, when the value is dynamic or unmapped (the caller reports it); `true`
224
+ * when mapped or absent.
225
+ */
226
+ export function mapAttr(
227
+ ctx: MigrateContext,
228
+ el: JSXElement,
229
+ name: string,
230
+ map: Readonly<Record<string, string>>,
231
+ { rename = name, fallback }: { rename?: string; fallback?: string } = {}
232
+ ): boolean {
233
+ const table: Record<string, string | null> = {}
234
+ for (const [key, value] of Object.entries(map))
235
+ table[key] = value === fallback ? null : value
236
+ const result = ctx.jsx.mapAttrValue(el, name, table)
237
+ if (result === "dynamic" || result === "unknown") return false
238
+ if (result === "mapped" && rename !== name && ctx.jsx.attr(el, name)) {
239
+ ctx.jsx.removeAttr(el, rename)
240
+ ctx.jsx.renameAttr(el, name, rename)
241
+ }
242
+ return true
243
+ }
244
+
245
+ /**
246
+ * MUI's ButtonBase renders `type="button"` unless told otherwise; a Zenith Button renders a
247
+ * bare `<button>`, which submits its form. Adds `type="button"` to an element that renders a
248
+ * native button and has no `type`, ahead of any spread so a spread `type` still wins.
249
+ */
250
+ export function defaultButtonType(ctx: MigrateContext, el: JSXElement): void {
251
+ if (ctx.jsx.attr(el, "type") || ctx.jsx.attr(el, "asChild")) return
252
+ el.openingElement.attributes = [
253
+ ctx.j.jsxAttribute(ctx.j.jsxIdentifier("type"), ctx.jsx.str("button")),
254
+ ...(el.openingElement.attributes ?? []),
255
+ ]
256
+ }
257
+
258
+ /** Children that are not whitespace-only text. */
259
+ export function contentChildren(el: JSXElement): Child[] {
260
+ return (el.children ?? []).filter(
261
+ (c) => !(c.type === "JSXText" && !c.value.trim())
262
+ )
263
+ }
264
+
265
+ /** Removes the named attributes and returns those present, in source order. */
266
+ export function takeAttrs(
267
+ ctx: MigrateContext,
268
+ el: JSXElement,
269
+ names: readonly string[]
270
+ ): JSXAttribute[] {
271
+ const taken = ctx.jsx
272
+ .attrs(el)
273
+ .filter((a) => names.includes(ctx.jsx.attrName(a)))
274
+ for (const a of taken) ctx.jsx.removeAttr(el, ctx.jsx.attrName(a))
275
+ return taken
276
+ }
277
+
278
+ /** Removes every attribute not in `keep` (spreads stay) and returns the removed ones. */
279
+ export function takeAttrsExcept(
280
+ ctx: MigrateContext,
281
+ el: JSXElement,
282
+ keep: (name: string) => boolean
283
+ ): JSXAttribute[] {
284
+ const names = ctx.jsx
285
+ .attrs(el)
286
+ .map((a) => ctx.jsx.attrName(a))
287
+ .filter((n) => !keep(n))
288
+ return takeAttrs(ctx, el, names)
289
+ }
290
+
291
+ /**
292
+ * One attribute as printed source, for a TODO message, which is one report line: a multi-line
293
+ * value is collapsed onto one line, a very long one prints as `name={…}`.
294
+ */
295
+ export function printAttr(ctx: MigrateContext, a: JSXAttribute): string {
296
+ // One line, so the report stays one line per TODO; long values abbreviate (the diff has them).
297
+ const printed = ctx.jsx.print(a).replace(/\s*\n\s*/g, " ")
298
+ if (printed.length <= 160) return printed
299
+ return `${ctx.jsx.attrName(a)}={…}`
300
+ }
301
+
302
+ /** `a={b} c="d"`: attributes as printed source, for a TODO message. */
303
+ export function printAttrs(
304
+ ctx: MigrateContext,
305
+ attrs: readonly JSXAttribute[]
306
+ ): string {
307
+ return attrs.map((a) => printAttr(ctx, a)).join(" ")
308
+ }
309
+
310
+ /** The expression inside `name={…}`, or `undefined` for a string or bare attribute. */
311
+ export function attrExpression(
312
+ a: JSXAttribute | undefined
313
+ ): Expression | undefined {
314
+ const v = a?.value
315
+ if (v?.type !== "JSXExpressionContainer") return undefined
316
+ if (v.expression.type === "JSXEmptyExpression") return undefined
317
+ return v.expression as Expression
318
+ }
319
+
320
+ /** The value of an attribute as an expression: `"x"` → `"x"`, `{e}` → `e`, bare → `true`. */
321
+ export function attrValue(j: JSCodeshift, a: JSXAttribute): Expression {
322
+ const v = a.value
323
+ if (v == null) return j.booleanLiteral(true)
324
+ if (v.type === "JSXExpressionContainer")
325
+ return v.expression as unknown as Expression
326
+ if (v.type === "StringLiteral" || v.type === "Literal")
327
+ return j.stringLiteral(String(v.value))
328
+ return v as unknown as Expression
329
+ }
330
+
331
+ /** A copy of `a` under a new name (the value node is shared, the attribute is not). */
332
+ export function renamedAttr(
333
+ j: JSCodeshift,
334
+ a: JSXAttribute,
335
+ name: string
336
+ ): JSXAttribute {
337
+ return j.jsxAttribute(j.jsxIdentifier(name), a.value)
338
+ }
339
+
340
+ /** Whether an attribute is `name`, `name={true}` (a literal `true`). */
341
+ export function isTrue(ctx: MigrateContext, a: JSXAttribute | undefined) {
342
+ return ctx.jsx.literal(a) === true
343
+ }
344
+
345
+ /** The nearest JSX element ancestor whose tag is `tag`. */
346
+ export function closestElement(
347
+ path: ASTPath,
348
+ tag: string
349
+ ): ASTPath<JSXElement> | undefined {
350
+ let current = path.parent as ASTPath | null
351
+ while (current) {
352
+ const node = current.node as JSXElement
353
+ if (
354
+ node.type === "JSXElement" &&
355
+ node.openingElement.name.type === "JSXIdentifier" &&
356
+ node.openingElement.name.name === tag
357
+ )
358
+ return current as ASTPath<JSXElement>
359
+ current = current.parent
360
+ }
361
+ return undefined
362
+ }
363
+
364
+ /** Whether `path` sits among JSX children, where an element may be replaced by `{expr}`. */
365
+ export function inJsxChildren(path: ASTPath): boolean {
366
+ const parent = path.parent?.node as { type?: string } | undefined
367
+ return parent?.type === "JSXElement" || parent?.type === "JSXFragment"
368
+ }
369
+
370
+ /** `cond && <el />`, as a JSX child `{…}` or as a plain expression elsewhere. */
371
+ export function renderWhen(
372
+ j: JSCodeshift,
373
+ path: ASTPath<JSXElement>,
374
+ condition: Expression,
375
+ el: JSXElement
376
+ ): void {
377
+ const expression = j.logicalExpression("&&", condition as never, el)
378
+ path.replace(
379
+ inJsxChildren(path) ? j.jsxExpressionContainer(expression) : expression
380
+ )
381
+ }
382
+
383
+ /** The names an expression references or declares, to pick a fresh parameter name. */
384
+ function namesIn(j: JSCodeshift, node: ASTNode): Set<string> {
385
+ const names = new Set<string>()
386
+ j(node as never)
387
+ .find(j.Identifier)
388
+ .forEach((p) => {
389
+ const parent = p.parent?.node
390
+ const property =
391
+ (parent?.type === "MemberExpression" ||
392
+ parent?.type === "OptionalMemberExpression") &&
393
+ parent.property === p.node &&
394
+ !parent.computed
395
+ if (!property) names.add(p.node.name)
396
+ })
397
+ return names
398
+ }
399
+
400
+ export function freshName(
401
+ j: JSCodeshift,
402
+ node: ASTNode,
403
+ preferred: string
404
+ ): string {
405
+ const taken = namesIn(j, node)
406
+ if (!taken.has(preferred)) return preferred
407
+ const next = `next${preferred[0].toUpperCase()}${preferred.slice(1)}`
408
+ if (!taken.has(next)) return next
409
+ let i = 2
410
+ while (taken.has(`${preferred}${i}`)) i += 1
411
+ return `${preferred}${i}`
412
+ }
413
+
414
+ function isFunction(node: ASTNode | undefined): node is ASTNode & Fn {
415
+ return (
416
+ !!node &&
417
+ (node.type === "ArrowFunctionExpression" ||
418
+ node.type === "FunctionExpression")
419
+ )
420
+ }
421
+
422
+ /** Identifier paths in `fn`'s body that reference the binding `name` (keys excluded). */
423
+ function references(
424
+ j: JSCodeshift,
425
+ fn: Fn,
426
+ name: string
427
+ ): ASTPath<ASTNode & { name: string }>[] {
428
+ return j(fn.body as never)
429
+ .find(j.Identifier, { name })
430
+ .filter((p) => {
431
+ const parent = p.parent.node
432
+ if (
433
+ (parent.type === "MemberExpression" ||
434
+ parent.type === "OptionalMemberExpression") &&
435
+ parent.property === p.node &&
436
+ !parent.computed
437
+ )
438
+ return false
439
+ if (
440
+ (parent.type === "ObjectProperty" || parent.type === "Property") &&
441
+ parent.key === p.node &&
442
+ !parent.computed &&
443
+ !parent.shorthand
444
+ )
445
+ return false
446
+ return true
447
+ })
448
+ .paths() as never
449
+ }
450
+
451
+ /** `event.target.<prop>` / `event.currentTarget.<prop>` around a reference path, if it is one. */
452
+ function targetRead(path: ASTPath, prop: string): ASTPath | undefined {
453
+ const inner = path.parent
454
+ const n = inner?.node
455
+ if (
456
+ !n ||
457
+ n.type !== "MemberExpression" ||
458
+ n.object !== path.node ||
459
+ n.computed ||
460
+ n.property.type !== "Identifier" ||
461
+ (n.property.name !== "target" && n.property.name !== "currentTarget")
462
+ )
463
+ return undefined
464
+ const outer = inner.parent
465
+ const m = outer?.node
466
+ if (
467
+ !m ||
468
+ m.type !== "MemberExpression" ||
469
+ m.object !== n ||
470
+ m.computed ||
471
+ m.property.type !== "Identifier" ||
472
+ m.property.name !== prop
473
+ )
474
+ return undefined
475
+ return outer
476
+ }
477
+
478
+ export type ValueHandlerOptions = {
479
+ /** What MUI's handler read from the event: `event.target.<prop>` becomes the value. */
480
+ targetProp?: string
481
+ /** Preferred name for the value parameter when the handler had none. */
482
+ valueName: string
483
+ /** Wraps every read of the value (`checked` → `checked === true` for a tri-state checkbox). */
484
+ mapValue?: (value: Expression) => Expression
485
+ }
486
+
487
+ /**
488
+ * Rewrites MUI's `(event, value) => …` into `(value) => …`, for an inline arrow or function
489
+ * whose event parameter is unused or read only as `event.target.<targetProp>`. Returns the
490
+ * rewritten function, or `undefined` for any other shape (a handler reference, a used event):
491
+ * the caller reports a TODO.
492
+ */
493
+ export function valueHandler(
494
+ j: JSCodeshift,
495
+ expression: Expression | undefined,
496
+ options: ValueHandlerOptions
497
+ ): Expression | undefined {
498
+ // `((_, v: T) => …) as never` only quietened MUI's handler type: unwrap the cast.
499
+ while (
500
+ expression &&
501
+ (expression.type === "TSAsExpression" ||
502
+ expression.type === "TSSatisfiesExpression" ||
503
+ expression.type === "TSNonNullExpression")
504
+ )
505
+ expression = expression.expression as Expression
506
+ if (!isFunction(expression as ASTNode)) return undefined
507
+ const fn = expression as unknown as Fn
508
+ const [event, value, ...rest] = fn.params
509
+ if (rest.length) return undefined
510
+ if (event && event.type !== "Identifier") return undefined
511
+ if (value && value.type !== "Identifier") return undefined
512
+
513
+ const eventReads: ASTPath[] = []
514
+ if (event) {
515
+ for (const ref of references(j, fn, event.name!)) {
516
+ const read = options.targetProp
517
+ ? targetRead(ref, options.targetProp)
518
+ : undefined
519
+ if (!read) return undefined
520
+ eventReads.push(read)
521
+ }
522
+ }
523
+
524
+ const valueName = value
525
+ ? value.name!
526
+ : freshName(j, fn.body, options.valueName)
527
+ // A narrower annotation than the primitive passes (`v: "a" | "b"`) becomes a cast at each
528
+ // read, since the parameter itself must accept what Zenith passes.
529
+ const annotation = (
530
+ value?.typeAnnotation as { typeAnnotation?: ASTNode } | undefined
531
+ )?.typeAnnotation
532
+ const cast =
533
+ annotation &&
534
+ !["TSStringKeyword", "TSBooleanKeyword", "TSAnyKeyword"].includes(
535
+ annotation.type
536
+ )
537
+ ? source(j, annotation)
538
+ : undefined
539
+ const valueRef = (): Expression =>
540
+ cast
541
+ ? parseExpression(j, `${valueName} as ${cast}`)
542
+ : j.identifier(valueName)
543
+ const mapped = () =>
544
+ options.mapValue ? options.mapValue(valueRef()) : valueRef()
545
+
546
+ if (value && (options.mapValue || cast))
547
+ for (const ref of references(j, fn, valueName)) ref.replace(mapped())
548
+ for (const read of eventReads) read.replace(mapped())
549
+
550
+ // Rebuilt from source text so the parameter keeps its parentheses and the body its layout.
551
+ const params = event || value ? valueName : ""
552
+ const body = source(j, fn.body)
553
+ return parseExpression(
554
+ j,
555
+ fn.type === "ArrowFunctionExpression"
556
+ ? `(${params}) => ${body}`
557
+ : `function (${params}) ${body}`
558
+ )
559
+ }
560
+
561
+ /**
562
+ * `onClose={fn}` → `(open) => { if (!open) fn() }`: MUI's close callback as a Radix
563
+ * `onOpenChange`. Inline functions must take no parameters (their body moves under the
564
+ * `if`); a reference is called with no arguments, so a handler that needs MUI's
565
+ * `(event, reason)` fails the typecheck instead of silently changing. `undefined` for other
566
+ * shapes.
567
+ */
568
+ export function closeAsOpenChange(
569
+ j: JSCodeshift,
570
+ expression: Expression | undefined
571
+ ): Expression | undefined {
572
+ if (!expression) return undefined
573
+ const open = freshName(j, expression as ASTNode, "open")
574
+ if (isFunction(expression as ASTNode)) {
575
+ const fn = expression as unknown as Fn
576
+ if (fn.params.length) return undefined
577
+ const body = source(j, fn.body)
578
+ return parseExpression(
579
+ j,
580
+ fn.body.type === "BlockStatement"
581
+ ? `(${open}) => {\n if (!${open}) ${body.replace(/\n/g, "\n ")}\n}`
582
+ : `(${open}) => { if (!${open}) ${body} }`
583
+ )
584
+ }
585
+ if (
586
+ expression.type === "Identifier" ||
587
+ expression.type === "MemberExpression"
588
+ )
589
+ return parseExpression(
590
+ j,
591
+ `(${open}) => { if (!${open}) ${source(j, expression)}() }`
592
+ )
593
+ return undefined
594
+ }
595
+
596
+ /**
597
+ * Replaces `path`'s element with `<tag {...attrs}>…before, element, …after</tag>` and returns the
598
+ * path of the (original) element inside it, whose source line a TODO can still report.
599
+ */
600
+ export function wrapElement(
601
+ j: JSCodeshift,
602
+ path: ASTPath<JSXElement>,
603
+ tag: string,
604
+ attrs: JSXAttribute[],
605
+ before: Child[],
606
+ after: Child[]
607
+ ): ASTPath<JSXElement> {
608
+ const node = path.node
609
+ const wrapper = element(j, tag, attrs, [...before, node, ...after])
610
+ const [wrapperPath] = path.replace(wrapper) as ASTPath<JSXElement>[]
611
+ return wrapperPath.get("children", wrapper.children!.indexOf(node))
612
+ }
613
+
614
+ export type CheckedControlOptions = {
615
+ /** Radix Checkbox passes `boolean | "indeterminate"`: reads of the value become `=== true`. */
616
+ tristate: boolean
617
+ /** MUI `size` → Zenith `size`; `undefined` drops the prop silently. */
618
+ sizes?: Record<string, string>
619
+ fallbackSize?: string
620
+ }
621
+
622
+ /**
623
+ * Switch / Checkbox: `onChange(event, checked)` → `onCheckedChange(checked)` for inline handlers
624
+ * that read only the second parameter or `event.target.checked`; base-elements' `label` and
625
+ * `labelPlacement` → a wrapping Zenith `<Label>`. Everything else is reported.
626
+ */
627
+ export function migrateCheckedControl(
628
+ ctx: MigrateContext,
629
+ path: ASTPath<JSXElement>,
630
+ component: string,
631
+ options: CheckedControlOptions
632
+ ): void {
633
+ const { j, jsx } = ctx
634
+ const el = path.node
635
+ const reported: string[] = []
636
+
637
+ const onChange = jsx.attr(el, "onChange")
638
+ if (onChange) {
639
+ const handler = valueHandler(j, attrExpression(onChange), {
640
+ targetProp: "checked",
641
+ valueName: "checked",
642
+ mapValue: options.tristate
643
+ ? (value) =>
644
+ j.binaryExpression("===", value as never, j.booleanLiteral(true))
645
+ : undefined,
646
+ })
647
+ if (handler) {
648
+ onChange.name = j.jsxIdentifier("onCheckedChange")
649
+ onChange.value = j.jsxExpressionContainer(handler as never)
650
+ } else {
651
+ jsx.removeAttr(el, "onChange")
652
+ reported.push(
653
+ `dropped ${printAttr(ctx, onChange)} (onCheckedChange(checked) passes only the new state${options.tristate ? ', true | false | "indeterminate"' : ""}; call your handler with it)`
654
+ )
655
+ }
656
+ }
657
+
658
+ if (options.tristate) {
659
+ const indeterminate = jsx.removeAttr(el, "indeterminate")
660
+ const checked = jsx.attr(el, "checked")
661
+ if (indeterminate && jsx.literal(indeterminate) !== false) {
662
+ const value = stringIn(ctx, "indeterminate")
663
+ if (isTrue(ctx, indeterminate))
664
+ jsx.setAttr(el, "checked", "indeterminate")
665
+ else
666
+ jsx.setAttr(
667
+ el,
668
+ "checked",
669
+ j.conditionalExpression(
670
+ attrValue(j, indeterminate) as never,
671
+ value as never,
672
+ (checked ? attrValue(j, checked) : j.booleanLiteral(false)) as never
673
+ )
674
+ )
675
+ }
676
+ }
677
+
678
+ if (options.sizes) {
679
+ if (
680
+ !mapAttr(ctx, el, "size", options.sizes, {
681
+ fallback: options.fallbackSize,
682
+ })
683
+ )
684
+ reported.push(
685
+ `dropped ${printAttrs(ctx, takeAttrs(ctx, el, ["size"]))} (size: ${Object.values(options.sizes).join(" | ")})`
686
+ )
687
+ } else takeAttrs(ctx, el, ["size"])
688
+ takeAttrs(ctx, el, ["color", "disableRipple", "disableFocusRipple"])
689
+
690
+ const unsupported = takeAttrs(ctx, el, [
691
+ "inputProps",
692
+ "inputRef",
693
+ "edge",
694
+ "icon",
695
+ "checkedIcon",
696
+ "indeterminateIcon",
697
+ "classes",
698
+ "checkboxPlacement",
699
+ ])
700
+ if (unsupported.length)
701
+ reported.push(
702
+ `dropped ${printAttrs(ctx, unsupported)} (no Zenith equivalent)`
703
+ )
704
+
705
+ // Spread props ({...field}, {...register("x")}) carry an onChange that Radix's button root
706
+ // never fires; the checked state has to be wired by hand.
707
+ for (const spread of el.openingElement.attributes ?? [])
708
+ if (spread.type === "JSXSpreadAttribute")
709
+ reported.push(
710
+ `${source(j, spread)} reaches Radix's button root, which never fires onChange: pass checked and onCheckedChange explicitly (react-hook-form: a Controller)`
711
+ )
712
+
713
+ const label = jsx.removeAttr(el, "label")
714
+ const placement = jsx.removeAttr(el, "labelPlacement")
715
+ let todoPath = path
716
+ if (label) {
717
+ const where = placement ? jsx.literal(placement) : "end"
718
+ if (where !== "end" && where !== "start")
719
+ reported.push(
720
+ `dropped ${printAttr(ctx, placement!)} (the Label lays control and text out in a row; stack them yourself)`
721
+ )
722
+ const text = jsx.childFromValue(label)
723
+ const nl = () => j.jsxText("\n")
724
+ todoPath =
725
+ where === "start"
726
+ ? wrapElement(
727
+ j,
728
+ path,
729
+ ctx.ensureZenith("Label"),
730
+ [],
731
+ [nl(), text, nl()],
732
+ [nl()]
733
+ )
734
+ : wrapElement(
735
+ j,
736
+ path,
737
+ ctx.ensureZenith("Label"),
738
+ [],
739
+ [nl()],
740
+ [nl(), text, nl()]
741
+ )
742
+ }
743
+ if (reported.length) ctx.todo(todoPath, component, reported.join("; "))
744
+ }
745
+
746
+ /**
747
+ * A close callback as a no-argument one (Callout `onDismiss`, Accordion `onValueChange` reads):
748
+ * a reference as is (the typecheck catches a handler that needs the event), an inline function
749
+ * whose parameters are unused without them. `undefined` when a parameter is read.
750
+ */
751
+ export function withoutParams(
752
+ j: JSCodeshift,
753
+ expression: Expression | undefined
754
+ ): Expression | undefined {
755
+ if (!expression) return undefined
756
+ if (
757
+ expression.type === "Identifier" ||
758
+ expression.type === "MemberExpression"
759
+ )
760
+ return expression
761
+ if (!isFunction(expression as ASTNode)) return undefined
762
+ const fn = expression as unknown as Fn
763
+ if (!fn.params.length) return expression
764
+ for (const param of fn.params) {
765
+ if (param.type !== "Identifier") return undefined
766
+ if (references(j, fn, param.name!).length) return undefined
767
+ }
768
+ const body = source(j, fn.body)
769
+ return parseExpression(
770
+ j,
771
+ fn.type === "ArrowFunctionExpression"
772
+ ? `() => ${body}`
773
+ : `function () ${body}`
774
+ )
775
+ }
776
+
777
+ /** MUI Alert severity → Callout variant. */
778
+ export const SEVERITY: Record<string, string> = {
779
+ success: "success",
780
+ info: "info",
781
+ warning: "warning",
782
+ error: "destructive",
783
+ }
784
+
785
+ export type CalloutParts = {
786
+ title?: JSXAttribute
787
+ /** Children of CalloutDescription. */
788
+ description: Child[]
789
+ /** `onClose` → `dismissible onDismiss`. */
790
+ onClose?: JSXAttribute
791
+ /** `action` → a trailing CalloutAction. */
792
+ action?: JSXAttribute
793
+ }
794
+
795
+ /**
796
+ * Fills a Callout element in place: title and description parts, a dismiss handler and an
797
+ * action. Returns what it could not carry over, for the caller's TODO.
798
+ */
799
+ export function fillCallout(
800
+ ctx: MigrateContext,
801
+ el: JSXElement,
802
+ parts: CalloutParts
803
+ ): string[] {
804
+ const { j, jsx } = ctx
805
+ const reported: string[] = []
806
+ const children: Child[] = []
807
+ const nl = () => j.jsxText("\n")
808
+ if (parts.title)
809
+ children.push(
810
+ nl(),
811
+ element(
812
+ j,
813
+ ctx.ensureZenith("CalloutTitle"),
814
+ [],
815
+ [jsx.childFromValue(parts.title)]
816
+ )
817
+ )
818
+ const description = parts.description.filter(
819
+ (c) => !(c.type === "JSXText" && !c.value.trim())
820
+ )
821
+ if (description.length)
822
+ children.push(
823
+ nl(),
824
+ element(j, ctx.ensureZenith("CalloutDescription"), [], parts.description)
825
+ )
826
+ if (parts.action)
827
+ children.push(
828
+ nl(),
829
+ element(
830
+ j,
831
+ ctx.ensureZenith("CalloutAction"),
832
+ [],
833
+ [jsx.childFromValue(parts.action)]
834
+ )
835
+ )
836
+ if (children.length) children.push(nl())
837
+ setChildren(j, el, children)
838
+
839
+ if (parts.onClose) {
840
+ const handler = withoutParams(j, attrExpression(parts.onClose))
841
+ if (handler) {
842
+ jsx.setAttr(el, "dismissible", null)
843
+ jsx.setAttr(el, "onDismiss", handler)
844
+ } else
845
+ reported.push(
846
+ `dropped ${printAttr(ctx, parts.onClose)} (Callout dismissible + onDismiss() takes no event)`
847
+ )
848
+ }
849
+ return reported
850
+ }
851
+
852
+ /**
853
+ * Reports each use of legacy `name` as a value (`styled(X)`, `component={X}`) on its statement,
854
+ * in the wording of the runner's `moveElements` plus `fix`, for a rule that keeps the name
855
+ * itself (a family that stays, a body that stays MUI's). Returns the number of uses.
856
+ */
857
+ export function reportValueUses(
858
+ ctx: MigrateContext,
859
+ name: string,
860
+ fix: string
861
+ ): number {
862
+ if (!ctx.names[name]) return 0
863
+ const { j } = ctx
864
+ const uses = ctx.valueUses(name)
865
+ uses.forEach((path) => {
866
+ let statement = (j(path).closest(j.Statement).paths()[0] ?? path) as ASTPath
867
+ if (
868
+ /^Export(Named|Default)Declaration$/.test(
869
+ String(statement.parent?.node.type ?? "")
870
+ )
871
+ )
872
+ statement = statement.parent
873
+ ctx.todo(
874
+ statement,
875
+ name,
876
+ `${source(j, path.parent.node)}: ${name} is used as a value here, so it stays on ${ctx.source}; ${fix}`
877
+ )
878
+ })
879
+ return uses.size()
880
+ }
881
+
882
+ /** The runner's `moveElements`, then `each` on every element it moved. */
883
+ export function moveElements(
884
+ ctx: MigrateContext,
885
+ name: string,
886
+ target: string,
887
+ each: (path: ASTPath<JSXElement>) => void
888
+ ): void {
889
+ const paths = ctx.elements(name).paths()
890
+ ctx.moveElements(name, target)
891
+ paths.forEach(each)
892
+ }
893
+
894
+ /**
895
+ * For a family whose Zenith parts need the Zenith root's context (Dialog, Tabs, Accordion,
896
+ * ToggleButtonGroup): when any member is used as a value (`styled(TabContext)`), nothing in the
897
+ * family is migrated, since a Zenith part inside a base-elements root breaks at runtime. The
898
+ * uses are reported with `fix` and every name stays silently; `true` when the family stays.
899
+ */
900
+ export function familyStays(
901
+ ctx: MigrateContext,
902
+ names: readonly string[],
903
+ fix: string
904
+ ): boolean {
905
+ const used = names.filter((n) => ctx.names[n] && ctx.valueUses(n).size() > 0)
906
+ if (!used.length) return false
907
+ for (const n of used) reportValueUses(ctx, n, fix)
908
+ for (const n of names) ctx.keep(n)
909
+ return true
910
+ }