@nadicodeai/ui 0.20.0 → 0.22.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 (350) hide show
  1. package/AGENTS.md +4 -3
  2. package/README.md +14 -21
  3. package/dist/agents.d.ts +10 -0
  4. package/dist/agents.d.ts.map +1 -0
  5. package/dist/agents.js +9 -0
  6. package/dist/components/badge.d.ts +1 -1
  7. package/dist/components/brand-icons/apple.d.ts +18 -0
  8. package/dist/components/brand-icons/apple.d.ts.map +1 -0
  9. package/dist/components/brand-icons/apple.js +22 -0
  10. package/dist/components/brand-icons/brand-icon.d.ts +22 -0
  11. package/dist/components/brand-icons/brand-icon.d.ts.map +1 -0
  12. package/dist/components/brand-icons/brand-icon.js +26 -0
  13. package/dist/components/brand-icons/linux.d.ts +18 -0
  14. package/dist/components/brand-icons/linux.d.ts.map +1 -0
  15. package/dist/components/brand-icons/linux.js +25 -0
  16. package/dist/components/brand-icons/windows.d.ts +18 -0
  17. package/dist/components/brand-icons/windows.d.ts.map +1 -0
  18. package/dist/components/brand-icons/windows.js +22 -0
  19. package/dist/components/brand-icons.d.ts +5 -0
  20. package/dist/components/brand-icons.d.ts.map +1 -0
  21. package/dist/components/brand-icons.js +10 -0
  22. package/dist/components/button.d.ts +1 -1
  23. package/dist/components/button.js +1 -1
  24. package/dist/components/card-marketing.js +2 -2
  25. package/dist/components/card.d.ts +4 -3
  26. package/dist/components/card.d.ts.map +1 -1
  27. package/dist/components/card.js +12 -2
  28. package/dist/components/chart-breakdown-table.js +1 -1
  29. package/dist/components/chart-bullet-bar.d.ts +18 -2
  30. package/dist/components/chart-bullet-bar.d.ts.map +1 -1
  31. package/dist/components/chart-bullet-bar.js +62 -9
  32. package/dist/components/chart-date-range-control.d.ts +11 -1
  33. package/dist/components/chart-date-range-control.d.ts.map +1 -1
  34. package/dist/components/chart-date-range-control.js +13 -3
  35. package/dist/components/chart-entity-colors.d.ts +7 -1
  36. package/dist/components/chart-entity-colors.d.ts.map +1 -1
  37. package/dist/components/chart-entity-colors.js +7 -1
  38. package/dist/components/chart-kpi-stat.d.ts.map +1 -1
  39. package/dist/components/chart-kpi-stat.js +1 -1
  40. package/dist/components/chart-time-series.d.ts.map +1 -1
  41. package/dist/components/chart-time-series.js +62 -4
  42. package/dist/components/chart.js +2 -2
  43. package/dist/components/code-editor-mockup.js +1 -1
  44. package/dist/components/nav-bar.js +1 -1
  45. package/dist/components/radio-group.d.ts +1 -1
  46. package/dist/components/radio-group.d.ts.map +1 -1
  47. package/dist/components/radio-group.js +2 -2
  48. package/dist/components/theme-mode-switcher.d.ts +10 -3
  49. package/dist/components/theme-mode-switcher.d.ts.map +1 -1
  50. package/dist/components/theme-mode-switcher.js +14 -7
  51. package/dist/components/use-case-bento.d.ts +2 -4
  52. package/dist/components/use-case-bento.d.ts.map +1 -1
  53. package/dist/components/use-case-bento.js +2 -3
  54. package/dist/eslint/index.js +91 -0
  55. package/dist/eslint/rules/jsx-class-utility.js +231 -0
  56. package/dist/eslint/rules/no-deprecated-zod-api.js +156 -0
  57. package/dist/eslint/rules/no-design-system-src-import.js +11 -0
  58. package/dist/eslint/rules/no-invalid-token-utility.js +46 -0
  59. package/dist/eslint/rules/no-native-visible-control.js +86 -0
  60. package/dist/eslint/rules/no-raw-color-utility.js +109 -0
  61. package/dist/eslint/rules/no-raw-focus-ring-width.js +30 -0
  62. package/dist/eslint/rules/no-raw-logo-import.js +41 -0
  63. package/dist/eslint/rules/no-shadcn-appearance-override.js +191 -0
  64. package/dist/eslint/rules/no-token-category-bypass.js +53 -0
  65. package/dist/eslint/rules/no-ui-src-import.js +10 -0
  66. package/dist/eslint/rules/no-unpinned-vercel-functions-import.js +100 -0
  67. package/dist/eslint/rules/src-import-boundary.js +207 -0
  68. package/dist/hooks/index.d.ts +0 -1
  69. package/dist/hooks/index.d.ts.map +1 -1
  70. package/dist/hooks/index.js +0 -1
  71. package/dist/index.d.ts +1 -16
  72. package/dist/index.d.ts.map +1 -1
  73. package/dist/index.js +1 -16
  74. package/dist/internal/assistant-ui/attachment.d.ts +5 -0
  75. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -0
  76. package/dist/internal/assistant-ui/attachment.js +93 -0
  77. package/dist/internal/assistant-ui/follow-up-suggestions.d.ts +3 -0
  78. package/dist/internal/assistant-ui/follow-up-suggestions.d.ts.map +1 -0
  79. package/dist/internal/assistant-ui/follow-up-suggestions.js +8 -0
  80. package/dist/internal/assistant-ui/markdown-text.d.ts +2 -0
  81. package/dist/internal/assistant-ui/markdown-text.d.ts.map +1 -0
  82. package/dist/internal/assistant-ui/markdown-text.js +54 -0
  83. package/dist/internal/assistant-ui/reasoning.d.ts +31 -0
  84. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -0
  85. package/dist/internal/assistant-ui/reasoning.js +118 -0
  86. package/dist/internal/assistant-ui/thread.d.ts +26 -0
  87. package/dist/internal/assistant-ui/thread.d.ts.map +1 -0
  88. package/dist/internal/assistant-ui/thread.js +118 -0
  89. package/dist/internal/assistant-ui/tool-fallback.d.ts +10 -0
  90. package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -0
  91. package/dist/internal/assistant-ui/tool-fallback.js +163 -0
  92. package/dist/internal/assistant-ui/tool-group.d.ts +18 -0
  93. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -0
  94. package/dist/internal/assistant-ui/tool-group.js +44 -0
  95. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts +8 -0
  96. package/dist/internal/assistant-ui/tooltip-icon-button.d.ts.map +1 -0
  97. package/dist/internal/assistant-ui/tooltip-icon-button.js +10 -0
  98. package/dist/styles/globals.css +3 -209
  99. package/docs/agents/nadicodeai-ui.md +4 -6
  100. package/docs/component-classification.md +1 -1
  101. package/docs/consuming-cross-repo.md +32 -3
  102. package/docs/contract.md +16 -6
  103. package/docs/migration/base-ui-migration.md +0 -11
  104. package/docs/product-compositions.md +1 -1
  105. package/llms.txt +5 -6
  106. package/package.json +17 -29
  107. package/skills/nadicodeai-ui/SKILL.md +5 -7
  108. package/dist/ai-elements.d.ts +0 -49
  109. package/dist/ai-elements.d.ts.map +0 -1
  110. package/dist/ai-elements.js +0 -48
  111. package/dist/components/agent-avatar.d.ts +0 -7
  112. package/dist/components/agent-avatar.d.ts.map +0 -1
  113. package/dist/components/agent-avatar.js +0 -6
  114. package/dist/components/agent-chat.d.ts +0 -20
  115. package/dist/components/agent-chat.d.ts.map +0 -1
  116. package/dist/components/agent-chat.js +0 -10
  117. package/dist/components/agent-composer.d.ts +0 -56
  118. package/dist/components/agent-composer.d.ts.map +0 -1
  119. package/dist/components/agent-composer.js +0 -56
  120. package/dist/components/agent-message.d.ts +0 -117
  121. package/dist/components/agent-message.d.ts.map +0 -1
  122. package/dist/components/agent-message.js +0 -99
  123. package/dist/components/agent-thread.d.ts +0 -26
  124. package/dist/components/agent-thread.d.ts.map +0 -1
  125. package/dist/components/agent-thread.js +0 -63
  126. package/dist/components/agent-tool-approval.d.ts +0 -27
  127. package/dist/components/agent-tool-approval.d.ts.map +0 -1
  128. package/dist/components/agent-tool-approval.js +0 -43
  129. package/dist/components/ai-elements/agent.d.ts +0 -27
  130. package/dist/components/ai-elements/agent.d.ts.map +0 -1
  131. package/dist/components/ai-elements/agent.js +0 -25
  132. package/dist/components/ai-elements/artifact.d.ts +0 -24
  133. package/dist/components/ai-elements/artifact.d.ts.map +0 -1
  134. package/dist/components/ai-elements/artifact.js +0 -20
  135. package/dist/components/ai-elements/attachments.d.ts +0 -55
  136. package/dist/components/ai-elements/attachments.d.ts.map +0 -1
  137. package/dist/components/ai-elements/attachments.js +0 -125
  138. package/dist/components/ai-elements/audio-player.d.ts +0 -30
  139. package/dist/components/ai-elements/audio-player.d.ts.map +0 -1
  140. package/dist/components/ai-elements/audio-player.js +0 -41
  141. package/dist/components/ai-elements/canvas.d.ts +0 -8
  142. package/dist/components/ai-elements/canvas.d.ts.map +0 -1
  143. package/dist/components/ai-elements/canvas.js +0 -5
  144. package/dist/components/ai-elements/chain-of-thought.d.ts +0 -30
  145. package/dist/components/ai-elements/chain-of-thought.d.ts.map +0 -1
  146. package/dist/components/ai-elements/chain-of-thought.js +0 -49
  147. package/dist/components/ai-elements/checkpoint.d.ts +0 -12
  148. package/dist/components/ai-elements/checkpoint.d.ts.map +0 -1
  149. package/dist/components/ai-elements/checkpoint.js +0 -10
  150. package/dist/components/ai-elements/code-block.d.ts +0 -53
  151. package/dist/components/ai-elements/code-block.d.ts.map +0 -1
  152. package/dist/components/ai-elements/code-block.js +0 -239
  153. package/dist/components/ai-elements/commit.d.ts +0 -65
  154. package/dist/components/ai-elements/commit.d.ts.map +0 -1
  155. package/dist/components/ai-elements/commit.js +0 -83
  156. package/dist/components/ai-elements/confirmation.d.ts +0 -50
  157. package/dist/components/ai-elements/confirmation.d.ts.map +0 -1
  158. package/dist/components/ai-elements/confirmation.js +0 -57
  159. package/dist/components/ai-elements/connection.d.ts +0 -6
  160. package/dist/components/ai-elements/connection.d.ts.map +0 -1
  161. package/dist/components/ai-elements/connection.js +0 -10
  162. package/dist/components/ai-elements/context.d.ts +0 -33
  163. package/dist/components/ai-elements/context.d.ts.map +0 -1
  164. package/dist/components/ai-elements/context.js +0 -147
  165. package/dist/components/ai-elements/controls.d.ts +0 -5
  166. package/dist/components/ai-elements/controls.d.ts.map +0 -1
  167. package/dist/components/ai-elements/controls.js +0 -5
  168. package/dist/components/ai-elements/conversation.d.ts +0 -24
  169. package/dist/components/ai-elements/conversation.d.ts.map +0 -1
  170. package/dist/components/ai-elements/conversation.js +0 -41
  171. package/dist/components/ai-elements/edge.d.ts +0 -6
  172. package/dist/components/ai-elements/edge.d.ts.map +0 -1
  173. package/dist/components/ai-elements/edge.js +0 -88
  174. package/dist/components/ai-elements/environment-variables.d.ts +0 -39
  175. package/dist/components/ai-elements/environment-variables.d.ts.map +0 -1
  176. package/dist/components/ai-elements/environment-variables.js +0 -60
  177. package/dist/components/ai-elements/file-tree.d.ts +0 -27
  178. package/dist/components/ai-elements/file-tree.d.ts.map +0 -1
  179. package/dist/components/ai-elements/file-tree.js +0 -73
  180. package/dist/components/ai-elements/image.d.ts +0 -7
  181. package/dist/components/ai-elements/image.d.ts.map +0 -1
  182. package/dist/components/ai-elements/image.js +0 -3
  183. package/dist/components/ai-elements/inline-citation.d.ts +0 -39
  184. package/dist/components/ai-elements/inline-citation.d.ts.map +0 -1
  185. package/dist/components/ai-elements/inline-citation.js +0 -86
  186. package/dist/components/ai-elements/jsx-preview.d.ts +0 -30
  187. package/dist/components/ai-elements/jsx-preview.d.ts.map +0 -1
  188. package/dist/components/ai-elements/jsx-preview.js +0 -159
  189. package/dist/components/ai-elements/message.d.ts +0 -38
  190. package/dist/components/ai-elements/message.d.ts.map +0 -1
  191. package/dist/components/ai-elements/message.js +0 -91
  192. package/dist/components/ai-elements/mic-selector.d.ts +0 -46
  193. package/dist/components/ai-elements/mic-selector.d.ts.map +0 -1
  194. package/dist/components/ai-elements/mic-selector.js +0 -180
  195. package/dist/components/ai-elements/model-selector.d.ts +0 -36
  196. package/dist/components/ai-elements/model-selector.d.ts.map +0 -1
  197. package/dist/components/ai-elements/model-selector.js +0 -18
  198. package/dist/components/ai-elements/node.d.ts +0 -22
  199. package/dist/components/ai-elements/node.d.ts.map +0 -1
  200. package/dist/components/ai-elements/node.js +0 -12
  201. package/dist/components/ai-elements/open-in-chat.d.ts +0 -27
  202. package/dist/components/ai-elements/open-in-chat.d.ts.map +0 -1
  203. package/dist/components/ai-elements/open-in-chat.js +0 -81
  204. package/dist/components/ai-elements/package-info.d.ts +0 -30
  205. package/dist/components/ai-elements/package-info.d.ts.map +0 -1
  206. package/dist/components/ai-elements/package-info.js +0 -50
  207. package/dist/components/ai-elements/panel.d.ts +0 -6
  208. package/dist/components/ai-elements/panel.d.ts.map +0 -1
  209. package/dist/components/ai-elements/panel.js +0 -5
  210. package/dist/components/ai-elements/persona.d.ts +0 -49
  211. package/dist/components/ai-elements/persona.d.ts.map +0 -1
  212. package/dist/components/ai-elements/persona.js +0 -175
  213. package/dist/components/ai-elements/plan.d.ts +0 -27
  214. package/dist/components/ai-elements/plan.d.ts.map +0 -1
  215. package/dist/components/ai-elements/plan.js +0 -34
  216. package/dist/components/ai-elements/prompt-input.d.ts +0 -149
  217. package/dist/components/ai-elements/prompt-input.d.ts.map +0 -1
  218. package/dist/components/ai-elements/prompt-input.js +0 -704
  219. package/dist/components/ai-elements/queue.d.ts +0 -62
  220. package/dist/components/ai-elements/queue.d.ts.map +0 -1
  221. package/dist/components/ai-elements/queue.js +0 -24
  222. package/dist/components/ai-elements/reasoning.d.ts +0 -27
  223. package/dist/components/ai-elements/reasoning.d.ts.map +0 -1
  224. package/dist/components/ai-elements/reasoning.js +0 -92
  225. package/dist/components/ai-elements/sandbox.d.ts +0 -25
  226. package/dist/components/ai-elements/sandbox.d.ts.map +0 -1
  227. package/dist/components/ai-elements/sandbox.js +0 -15
  228. package/dist/components/ai-elements/schema-display.d.ts +0 -56
  229. package/dist/components/ai-elements/schema-display.d.ts.map +0 -1
  230. package/dist/components/ai-elements/schema-display.js +0 -90
  231. package/dist/components/ai-elements/shimmer.d.ts +0 -10
  232. package/dist/components/ai-elements/shimmer.d.ts.map +0 -1
  233. package/dist/components/ai-elements/shimmer.js +0 -11
  234. package/dist/components/ai-elements/snippet.d.ts +0 -19
  235. package/dist/components/ai-elements/snippet.d.ts.map +0 -1
  236. package/dist/components/ai-elements/snippet.js +0 -32
  237. package/dist/components/ai-elements/sources.d.ts +0 -13
  238. package/dist/components/ai-elements/sources.d.ts.map +0 -1
  239. package/dist/components/ai-elements/sources.js +0 -9
  240. package/dist/components/ai-elements/speech-input.d.ts +0 -55
  241. package/dist/components/ai-elements/speech-input.d.ts.map +0 -1
  242. package/dist/components/ai-elements/speech-input.js +0 -187
  243. package/dist/components/ai-elements/stack-trace.d.ts +0 -38
  244. package/dist/components/ai-elements/stack-trace.d.ts.map +0 -1
  245. package/dist/components/ai-elements/stack-trace.js +0 -181
  246. package/dist/components/ai-elements/suggestion.d.ts +0 -11
  247. package/dist/components/ai-elements/suggestion.d.ts.map +0 -1
  248. package/dist/components/ai-elements/suggestion.js +0 -13
  249. package/dist/components/ai-elements/task.d.ts +0 -15
  250. package/dist/components/ai-elements/task.d.ts.map +0 -1
  251. package/dist/components/ai-elements/task.js +0 -10
  252. package/dist/components/ai-elements/terminal.d.ts +0 -28
  253. package/dist/components/ai-elements/terminal.d.ts.map +0 -1
  254. package/dist/components/ai-elements/terminal.js +0 -55
  255. package/dist/components/ai-elements/test-results.d.ts +0 -59
  256. package/dist/components/ai-elements/test-results.d.ts.map +0 -1
  257. package/dist/components/ai-elements/test-results.js +0 -98
  258. package/dist/components/ai-elements/tool.d.ts +0 -32
  259. package/dist/components/ai-elements/tool.d.ts.map +0 -1
  260. package/dist/components/ai-elements/tool.js +0 -49
  261. package/dist/components/ai-elements/toolbar.d.ts +0 -6
  262. package/dist/components/ai-elements/toolbar.d.ts.map +0 -1
  263. package/dist/components/ai-elements/toolbar.js +0 -5
  264. package/dist/components/ai-elements/transcription.d.ts +0 -17
  265. package/dist/components/ai-elements/transcription.d.ts.map +0 -1
  266. package/dist/components/ai-elements/transcription.js +0 -36
  267. package/dist/components/ai-elements/voice-selector.d.ts +0 -65
  268. package/dist/components/ai-elements/voice-selector.d.ts.map +0 -1
  269. package/dist/components/ai-elements/voice-selector.js +0 -224
  270. package/dist/components/ai-elements/web-preview.d.ts +0 -35
  271. package/dist/components/ai-elements/web-preview.d.ts.map +0 -1
  272. package/dist/components/ai-elements/web-preview.js +0 -66
  273. package/dist/components/artifact-panel.d.ts +0 -130
  274. package/dist/components/artifact-panel.d.ts.map +0 -1
  275. package/dist/components/artifact-panel.js +0 -180
  276. package/dist/components/attachment.d.ts +0 -24
  277. package/dist/components/attachment.d.ts.map +0 -1
  278. package/dist/components/attachment.js +0 -68
  279. package/dist/components/bubble.d.ts +0 -17
  280. package/dist/components/bubble.d.ts.map +0 -1
  281. package/dist/components/bubble.js +0 -59
  282. package/dist/components/demo-surface.d.ts +0 -34
  283. package/dist/components/demo-surface.d.ts.map +0 -1
  284. package/dist/components/demo-surface.js +0 -21
  285. package/dist/components/files-preview.d.ts +0 -36
  286. package/dist/components/files-preview.d.ts.map +0 -1
  287. package/dist/components/files-preview.js +0 -85
  288. package/dist/components/marker.d.ts +0 -11
  289. package/dist/components/marker.d.ts.map +0 -1
  290. package/dist/components/marker.js +0 -34
  291. package/dist/components/message-scroller.d.ts +0 -17
  292. package/dist/components/message-scroller.d.ts.map +0 -1
  293. package/dist/components/message-scroller.js +0 -29
  294. package/dist/components/message.d.ts +0 -11
  295. package/dist/components/message.d.ts.map +0 -1
  296. package/dist/components/message.js +0 -21
  297. package/dist/components/state-notice.d.ts +0 -13
  298. package/dist/components/state-notice.d.ts.map +0 -1
  299. package/dist/components/state-notice.js +0 -8
  300. package/dist/components/watch-it-work-band.d.ts +0 -12
  301. package/dist/components/watch-it-work-band.d.ts.map +0 -1
  302. package/dist/components/watch-it-work-band.js +0 -8
  303. package/dist/hooks/use-controllable-state.d.ts +0 -9
  304. package/dist/hooks/use-controllable-state.d.ts.map +0 -1
  305. package/dist/hooks/use-controllable-state.js +0 -23
  306. package/dist/lib/agent-attachment.d.ts +0 -11
  307. package/dist/lib/agent-attachment.d.ts.map +0 -1
  308. package/dist/lib/agent-attachment.js +0 -19
  309. package/dist/lib/agent-contracts.d.ts +0 -132
  310. package/dist/lib/agent-contracts.d.ts.map +0 -1
  311. package/dist/lib/agent-contracts.js +0 -6
  312. package/dist/lib/agent-state.d.ts +0 -22
  313. package/dist/lib/agent-state.d.ts.map +0 -1
  314. package/dist/lib/agent-state.js +0 -96
  315. package/dist/lib/agent-work-state.d.ts +0 -36
  316. package/dist/lib/agent-work-state.d.ts.map +0 -1
  317. package/dist/lib/agent-work-state.js +0 -36
  318. package/dist/lib/message-scroller-primitive/components.d.ts +0 -17
  319. package/dist/lib/message-scroller-primitive/components.d.ts.map +0 -1
  320. package/dist/lib/message-scroller-primitive/components.js +0 -204
  321. package/dist/lib/message-scroller-primitive/geometry.d.ts +0 -51
  322. package/dist/lib/message-scroller-primitive/geometry.d.ts.map +0 -1
  323. package/dist/lib/message-scroller-primitive/geometry.js +0 -199
  324. package/dist/lib/message-scroller-primitive/index.d.ts +0 -12
  325. package/dist/lib/message-scroller-primitive/index.d.ts.map +0 -1
  326. package/dist/lib/message-scroller-primitive/index.js +0 -12
  327. package/dist/lib/message-scroller-primitive/stores.d.ts +0 -6
  328. package/dist/lib/message-scroller-primitive/stores.d.ts.map +0 -1
  329. package/dist/lib/message-scroller-primitive/stores.js +0 -53
  330. package/dist/lib/message-scroller-primitive/types.d.ts +0 -88
  331. package/dist/lib/message-scroller-primitive/types.d.ts.map +0 -1
  332. package/dist/lib/message-scroller-primitive/types.js +0 -40
  333. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts +0 -19
  334. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.d.ts.map +0 -1
  335. package/dist/lib/message-scroller-primitive/use-message-scroller-commands.js +0 -188
  336. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts +0 -7
  337. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.d.ts.map +0 -1
  338. package/dist/lib/message-scroller-primitive/use-message-scroller-controller.js +0 -506
  339. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts +0 -49
  340. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.d.ts.map +0 -1
  341. package/dist/lib/message-scroller-primitive/use-message-scroller-refs.js +0 -90
  342. package/dist/lib/message-scroller-primitive/use-render.d.ts +0 -22
  343. package/dist/lib/message-scroller-primitive/use-render.d.ts.map +0 -1
  344. package/dist/lib/message-scroller-primitive/use-render.js +0 -113
  345. package/dist/lib/message-scroller-primitive/utils.d.ts +0 -4
  346. package/dist/lib/message-scroller-primitive/utils.d.ts.map +0 -1
  347. package/dist/lib/message-scroller-primitive/utils.js +0 -9
  348. package/docs/agent-work-surfaces.md +0 -132
  349. package/docs/migration/ai-elements-vendoring.md +0 -29
  350. package/docs/terminal-tui-semantics.md +0 -172
@@ -0,0 +1,91 @@
1
+ import { readFileSync } from "node:fs";
2
+
3
+ import { noDesignSystemSrcImport } from "./rules/no-design-system-src-import.js";
4
+ import { noDeprecatedZodApi } from "./rules/no-deprecated-zod-api.js";
5
+ import { noRawLogoImport } from "./rules/no-raw-logo-import.js";
6
+ import { noRawColorUtility } from "./rules/no-raw-color-utility.js";
7
+ import { noShadcnAppearanceOverride } from "./rules/no-shadcn-appearance-override.js";
8
+ import { noUnpinnedVercelFunctionsImport } from "./rules/no-unpinned-vercel-functions-import.js";
9
+ import { noUiSrcImport } from "./rules/no-ui-src-import.js";
10
+ import { noNativeVisibleControl } from "./rules/no-native-visible-control.js";
11
+ import { noRawFocusRingWidth } from "./rules/no-raw-focus-ring-width.js";
12
+ import { noInvalidTokenUtility } from "./rules/no-invalid-token-utility.js";
13
+ import { noTokenCategoryBypass } from "./rules/no-token-category-bypass.js";
14
+
15
+ /**
16
+ * The plugin carries no version of its own. Its bytes are published inside
17
+ * `@nadicodeai/ui`, whose version the release gate already forces to move in
18
+ * lockstep, so that manifest is the one home of the number and this reads it.
19
+ * The published copy of this file sits at `<ui>/dist/eslint/index.js` and the
20
+ * source sits at `tools/eslint-plugin-nadicodeai/index.js`, which puts the
21
+ * manifest at one of two places relative to here; the `name` field says which
22
+ * candidate is the right one, so the repository root's own manifest — also two
23
+ * levels up — cannot answer by accident.
24
+ */
25
+ const PUBLISHING_PACKAGE = "@nadicodeai/ui";
26
+ const MANIFEST_CANDIDATES = ["../../package.json", `../../${PUBLISHING_PACKAGE}/package.json`];
27
+
28
+ const version = readPublishedVersion();
29
+
30
+ function readPublishedVersion() {
31
+ for (const candidate of MANIFEST_CANDIDATES) {
32
+ let manifest;
33
+ try {
34
+ manifest = JSON.parse(readFileSync(new URL(candidate, import.meta.url), "utf8"));
35
+ } catch {
36
+ continue;
37
+ }
38
+ if (manifest?.name === PUBLISHING_PACKAGE && typeof manifest.version === "string") {
39
+ return manifest.version;
40
+ }
41
+ }
42
+ throw new Error(
43
+ `@nadicodeai/eslint-plugin: no ${PUBLISHING_PACKAGE} manifest at ${MANIFEST_CANDIDATES.join(" or ")}, so the plugin cannot report the version it ships under.`,
44
+ );
45
+ }
46
+
47
+ export const strictDesignSystemRules = {
48
+ "nadicodeai/no-design-system-src-import": "error",
49
+ "nadicodeai/no-invalid-token-utility": "error",
50
+ "nadicodeai/no-native-visible-control": "error",
51
+ "nadicodeai/no-raw-color-utility": "error",
52
+ "nadicodeai/no-raw-focus-ring-width": "error",
53
+ "nadicodeai/no-raw-logo-import": "error",
54
+ "nadicodeai/no-shadcn-appearance-override": "error",
55
+ "nadicodeai/no-token-category-bypass": "error",
56
+ "nadicodeai/no-ui-src-import": "error",
57
+ };
58
+
59
+ /** @type {import('eslint').ESLint.Plugin} */
60
+ const plugin = {
61
+ meta: {
62
+ name: "@nadicodeai/eslint-plugin",
63
+ version,
64
+ },
65
+ configs: {},
66
+ rules: {
67
+ "no-deprecated-zod-api": noDeprecatedZodApi,
68
+ "no-raw-logo-import": noRawLogoImport,
69
+ "no-raw-color-utility": noRawColorUtility,
70
+ "no-shadcn-appearance-override": noShadcnAppearanceOverride,
71
+ "no-native-visible-control": noNativeVisibleControl,
72
+ "no-raw-focus-ring-width": noRawFocusRingWidth,
73
+ "no-unpinned-vercel-functions-import": noUnpinnedVercelFunctionsImport,
74
+ "no-ui-src-import": noUiSrcImport,
75
+ "no-design-system-src-import": noDesignSystemSrcImport,
76
+ "no-invalid-token-utility": noInvalidTokenUtility,
77
+ "no-token-category-bypass": noTokenCategoryBypass,
78
+ },
79
+ };
80
+
81
+ export const strictDesignSystemConfig = [
82
+ {
83
+ name: "nadicodeai/design-system-strict",
84
+ plugins: { nadicodeai: plugin },
85
+ rules: strictDesignSystemRules,
86
+ },
87
+ ];
88
+
89
+ plugin.configs["flat/strict"] = strictDesignSystemConfig;
90
+
91
+ export default plugin;
@@ -0,0 +1,231 @@
1
+ const PACKAGE_PRIMITIVE_PATH = "@nadicodeai/ui/src/";
2
+
3
+ export function isPackageOwnedPrimitive(filename) {
4
+ return filename.replaceAll("\\", "/").includes(PACKAGE_PRIMITIVE_PATH);
5
+ }
6
+
7
+ function variableInitializer(node, context) {
8
+ let scope = context.sourceCode.getScope(node);
9
+ while (scope) {
10
+ const variable = scope.set.get(node.name);
11
+ const definition = variable?.defs.find(
12
+ (candidate) => candidate.type === "Variable" && candidate.node?.type === "VariableDeclarator",
13
+ );
14
+ if (definition?.node.init) return definition.node.init;
15
+ scope = scope.upper;
16
+ }
17
+ return undefined;
18
+ }
19
+
20
+ function collectStaticClassFragments(
21
+ node,
22
+ fragments,
23
+ context,
24
+ seen = new Set(),
25
+ includeObjectKeys = true,
26
+ ) {
27
+ if (!node) return;
28
+
29
+ if (seen.has(node)) return;
30
+ seen.add(node);
31
+
32
+ if (node.type === "Literal" && typeof node.value === "string") {
33
+ fragments.push(node.value);
34
+ return;
35
+ }
36
+ if (node.type === "JSXExpressionContainer" || node.type === "ChainExpression") {
37
+ collectStaticClassFragments(node.expression, fragments, context, seen, includeObjectKeys);
38
+ return;
39
+ }
40
+ if (node.type === "TemplateLiteral") {
41
+ for (const quasi of node.quasis) fragments.push(quasi.value.cooked ?? quasi.value.raw);
42
+ for (const expression of node.expressions) {
43
+ collectStaticClassFragments(expression, fragments, context, seen, includeObjectKeys);
44
+ }
45
+ return;
46
+ }
47
+ if (node.type === "TaggedTemplateExpression") {
48
+ collectStaticClassFragments(node.quasi, fragments, context, seen, includeObjectKeys);
49
+ return;
50
+ }
51
+ if (node.type === "ConditionalExpression") {
52
+ collectStaticClassFragments(node.consequent, fragments, context, seen, includeObjectKeys);
53
+ collectStaticClassFragments(node.alternate, fragments, context, seen, includeObjectKeys);
54
+ return;
55
+ }
56
+ if (node.type === "LogicalExpression" || node.type === "BinaryExpression") {
57
+ collectStaticClassFragments(node.left, fragments, context, seen, includeObjectKeys);
58
+ collectStaticClassFragments(node.right, fragments, context, seen, includeObjectKeys);
59
+ return;
60
+ }
61
+ if (node.type === "CallExpression" || node.type === "NewExpression") {
62
+ for (const argument of node.arguments) {
63
+ collectStaticClassFragments(
64
+ argument.type === "SpreadElement" ? argument.argument : argument,
65
+ fragments,
66
+ context,
67
+ seen,
68
+ includeObjectKeys,
69
+ );
70
+ }
71
+ return;
72
+ }
73
+ if (node.type === "ArrayExpression" || node.type === "SequenceExpression") {
74
+ for (const element of node.elements ?? node.expressions) {
75
+ collectStaticClassFragments(
76
+ element?.type === "SpreadElement" ? element.argument : element,
77
+ fragments,
78
+ context,
79
+ seen,
80
+ includeObjectKeys,
81
+ );
82
+ }
83
+ return;
84
+ }
85
+ if (node.type === "ObjectExpression") {
86
+ for (const property of node.properties) {
87
+ if (property.type === "SpreadElement") {
88
+ collectStaticClassFragments(property.argument, fragments, context, seen, includeObjectKeys);
89
+ continue;
90
+ }
91
+ if (includeObjectKeys && !property.computed) {
92
+ collectStaticClassFragments(property.key, fragments, context, seen, includeObjectKeys);
93
+ }
94
+ collectStaticClassFragments(property.value, fragments, context, seen, includeObjectKeys);
95
+ }
96
+ return;
97
+ }
98
+ if (node.type === "Identifier") {
99
+ collectStaticClassFragments(
100
+ variableInitializer(node, context),
101
+ fragments,
102
+ context,
103
+ seen,
104
+ includeObjectKeys,
105
+ );
106
+ return;
107
+ }
108
+ if (node.type === "MemberExpression") {
109
+ // A dynamic lookup can select any value in a local class table. Resolve the
110
+ // entire object so no palette entry can hide behind `classes[current]`.
111
+ collectStaticClassFragments(node.object, fragments, context, seen, includeObjectKeys);
112
+ return;
113
+ }
114
+ if (
115
+ node.type === "TSAsExpression" ||
116
+ node.type === "TSSatisfiesExpression" ||
117
+ node.type === "TSNonNullExpression" ||
118
+ node.type === "TypeCastExpression"
119
+ ) {
120
+ collectStaticClassFragments(node.expression, fragments, context, seen, includeObjectKeys);
121
+ }
122
+ }
123
+
124
+ function staticPropertyName(property) {
125
+ if (property.key.type === "Identifier" && !property.computed) return property.key.name;
126
+ if (property.key.type === "Literal" && typeof property.key.value === "string") {
127
+ return property.key.value;
128
+ }
129
+ return undefined;
130
+ }
131
+
132
+ function collectStaticSpreadClassFragments(node, fragments, context, seen = new Set()) {
133
+ if (!node || seen.has(node)) return;
134
+ seen.add(node);
135
+
136
+ if (node.type === "Identifier") {
137
+ collectStaticSpreadClassFragments(variableInitializer(node, context), fragments, context, seen);
138
+ return;
139
+ }
140
+ if (node.type === "ObjectExpression") {
141
+ for (const property of node.properties) {
142
+ if (property.type === "SpreadElement") {
143
+ collectStaticSpreadClassFragments(property.argument, fragments, context, seen);
144
+ continue;
145
+ }
146
+ if (staticPropertyName(property) === "className") {
147
+ collectStaticClassFragments(property.value, fragments, context, seen);
148
+ }
149
+ }
150
+ return;
151
+ }
152
+ if (node.type === "ConditionalExpression") {
153
+ collectStaticSpreadClassFragments(node.consequent, fragments, context, seen);
154
+ collectStaticSpreadClassFragments(node.alternate, fragments, context, seen);
155
+ return;
156
+ }
157
+ if (node.type === "LogicalExpression") {
158
+ collectStaticSpreadClassFragments(node.left, fragments, context, seen);
159
+ collectStaticSpreadClassFragments(node.right, fragments, context, seen);
160
+ return;
161
+ }
162
+ if (
163
+ node.type === "TSAsExpression" ||
164
+ node.type === "TSSatisfiesExpression" ||
165
+ node.type === "TSNonNullExpression" ||
166
+ node.type === "TypeCastExpression"
167
+ ) {
168
+ collectStaticSpreadClassFragments(node.expression, fragments, context, seen);
169
+ }
170
+ }
171
+
172
+ export function classUtilities(attribute, context) {
173
+ if (attribute?.type !== "JSXAttribute" || attribute.name.name !== "className") return [];
174
+ return staticClassUtilities(attribute.value, context);
175
+ }
176
+
177
+ export function staticStringFragments(node, context) {
178
+ const fragments = [];
179
+ collectStaticClassFragments(node, fragments, context);
180
+ return fragments;
181
+ }
182
+
183
+ function staticClassUtilities(node, context) {
184
+ return staticStringFragments(node, context).flatMap((fragment) =>
185
+ fragment.split(/\s+/).filter(Boolean),
186
+ );
187
+ }
188
+
189
+ function staticValueClassUtilities(node, context) {
190
+ const fragments = [];
191
+ collectStaticClassFragments(node, fragments, context, new Set(), false);
192
+ return fragments.flatMap((fragment) => fragment.split(/\s+/).filter(Boolean));
193
+ }
194
+
195
+ export function tokenUtilityVisitors(context, onUtility) {
196
+ const cvaNames = new Set();
197
+
198
+ function visitUtilities(node, utilities) {
199
+ for (const utility of utilities) onUtility(node, utility);
200
+ }
201
+
202
+ return {
203
+ ImportDeclaration(node) {
204
+ if (node.source.value !== "class-variance-authority") return;
205
+ for (const specifier of node.specifiers) {
206
+ if (specifier.type === "ImportSpecifier" && specifier.imported.name === "cva") {
207
+ cvaNames.add(specifier.local.name);
208
+ }
209
+ }
210
+ },
211
+ JSXAttribute(node) {
212
+ visitUtilities(node, classUtilities(node, context));
213
+ },
214
+ CallExpression(node) {
215
+ if (node.callee.type !== "Identifier" || !cvaNames.has(node.callee.name)) return;
216
+ visitUtilities(node, staticValueClassUtilities(node, context));
217
+ },
218
+ };
219
+ }
220
+
221
+ export function openingElementClassUtilities(node, context) {
222
+ const fragments = [];
223
+ for (const attribute of node.attributes) {
224
+ if (attribute.type === "JSXAttribute" && attribute.name.name === "className") {
225
+ fragments.push(...staticStringFragments(attribute.value, context));
226
+ } else if (attribute.type === "JSXSpreadAttribute") {
227
+ collectStaticSpreadClassFragments(attribute.argument, fragments, context);
228
+ }
229
+ }
230
+ return fragments.flatMap((fragment) => fragment.split(/\s+/).filter(Boolean));
231
+ }
@@ -0,0 +1,156 @@
1
+ const LEGACY_FACTORIES = new Map([
2
+ ["nativeEnum", "z.enum()"],
3
+ ["promise", "await the value before parsing it"],
4
+ ]);
5
+
6
+ const LEGACY_METHODS = {
7
+ number: new Map([
8
+ ["finite", "remove it; z.number() already rejects infinite values"],
9
+ ["safe", ".int()"],
10
+ ["step", ".multipleOf()"],
11
+ ]),
12
+ object: new Map([
13
+ ["merge", ".extend(other.shape)"],
14
+ ["passthrough", "z.looseObject()"],
15
+ ["strict", "z.strictObject()"],
16
+ ["strip", "z.object(), which strips unknown keys by default"],
17
+ ]),
18
+ string: new Map(
19
+ [
20
+ "base64",
21
+ "base64url",
22
+ "cuid",
23
+ "cuid2",
24
+ "e164",
25
+ "email",
26
+ "emoji",
27
+ "guid",
28
+ "ipv4",
29
+ "ipv6",
30
+ "jwt",
31
+ "ksuid",
32
+ "nanoid",
33
+ "ulid",
34
+ "url",
35
+ "uuid",
36
+ "uuidv4",
37
+ "uuidv6",
38
+ "uuidv7",
39
+ "xid",
40
+ ].map((name) => [name, `z.${name.startsWith("uuidv") ? "uuid" : name}()`]),
41
+ ),
42
+ };
43
+
44
+ for (const name of ["date", "datetime", "duration", "time"]) {
45
+ LEGACY_METHODS.string.set(name, `z.iso.${name}()`);
46
+ }
47
+ for (const name of ["cidrv4", "cidrv6"]) {
48
+ LEGACY_METHODS.string.set(name, `z.${name}()`);
49
+ }
50
+
51
+ function memberName(node) {
52
+ if (!node.computed && node.property.type === "Identifier") {
53
+ return node.property.name;
54
+ }
55
+ if (node.computed && node.property.type === "Literal") {
56
+ return typeof node.property.value === "string" ? node.property.value : undefined;
57
+ }
58
+ return undefined;
59
+ }
60
+
61
+ export const noDeprecatedZodApi = {
62
+ meta: {
63
+ type: "problem",
64
+ docs: {
65
+ description: "Disallow deprecated and legacy Zod APIs when a Zod 4 replacement exists",
66
+ },
67
+ schema: [],
68
+ messages: {
69
+ legacyFactory: "{{api}} is deprecated in Zod 4; use {{replacement}}.",
70
+ legacyMethod: "{{api}} is deprecated or legacy in Zod 4; use {{replacement}}.",
71
+ },
72
+ },
73
+
74
+ create(context) {
75
+ const sourceCode = context.sourceCode;
76
+ const zodBindings = new Set();
77
+
78
+ function isZodBinding(identifier) {
79
+ for (let scope = sourceCode.getScope(identifier); scope; scope = scope.upper) {
80
+ const variable = scope.set.get(identifier.name);
81
+ if (variable) {
82
+ return zodBindings.has(variable);
83
+ }
84
+ }
85
+ return false;
86
+ }
87
+
88
+ function rootFactory(call) {
89
+ if (call.type !== "CallExpression" || call.callee.type !== "MemberExpression") {
90
+ return undefined;
91
+ }
92
+ const factory = memberName(call.callee);
93
+ if (!factory) {
94
+ return undefined;
95
+ }
96
+ if (call.callee.object.type === "Identifier" && isZodBinding(call.callee.object)) {
97
+ return factory;
98
+ }
99
+ return rootFactory(call.callee.object);
100
+ }
101
+
102
+ return {
103
+ ImportDeclaration(node) {
104
+ if (node.source.value !== "zod") {
105
+ return;
106
+ }
107
+ for (const specifier of node.specifiers) {
108
+ const importsNamespace = specifier.type === "ImportNamespaceSpecifier";
109
+ const importsZ =
110
+ specifier.type === "ImportSpecifier" &&
111
+ ((specifier.imported.type === "Identifier" && specifier.imported.name === "z") ||
112
+ (specifier.imported.type === "Literal" && specifier.imported.value === "z"));
113
+ if (!importsNamespace && !importsZ) {
114
+ continue;
115
+ }
116
+ for (const variable of sourceCode.getDeclaredVariables(specifier)) {
117
+ zodBindings.add(variable);
118
+ }
119
+ }
120
+ },
121
+
122
+ CallExpression(node) {
123
+ if (node.callee.type !== "MemberExpression") {
124
+ return;
125
+ }
126
+ const method = memberName(node.callee);
127
+ if (!method) {
128
+ return;
129
+ }
130
+
131
+ if (node.callee.object.type === "Identifier" && isZodBinding(node.callee.object)) {
132
+ const replacement = LEGACY_FACTORIES.get(method);
133
+ if (replacement) {
134
+ context.report({
135
+ node: node.callee.property,
136
+ messageId: "legacyFactory",
137
+ data: { api: `z.${method}()`, replacement },
138
+ });
139
+ }
140
+ return;
141
+ }
142
+
143
+ const factory = rootFactory(node.callee.object);
144
+ const family = factory === "strictObject" || factory === "looseObject" ? "object" : factory;
145
+ const replacement = LEGACY_METHODS[family]?.get(method);
146
+ if (replacement) {
147
+ context.report({
148
+ node: node.callee.property,
149
+ messageId: "legacyMethod",
150
+ data: { api: `z.${factory}().${method}()`, replacement },
151
+ });
152
+ }
153
+ },
154
+ };
155
+ },
156
+ };
@@ -0,0 +1,11 @@
1
+ import { bannedSourceRootMatcher, createSrcImportRule } from "./src-import-boundary.js";
2
+
3
+ /** @type {import('eslint').Rule.RuleModule} */
4
+ export const noDesignSystemSrcImport = createSrcImportRule({
5
+ description:
6
+ "Disallow deep imports from @nadicodeai/design-system source paths in apps and UI consumers",
7
+ bannedMessage: "Import @nadicodeai/design-system through published exports only, not {{value}}.",
8
+ // The package dir is `design-system/`, so relative paths carry the shorter
9
+ // `design-system/src` marker rather than the scoped specifier.
10
+ isBanned: bannedSourceRootMatcher("design-system/src"),
11
+ });
@@ -0,0 +1,46 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ import { tokenUtilityVisitors } from "./jsx-class-utility.js";
4
+
5
+ const require = createRequire(import.meta.url);
6
+ const generatedTheme = require("@nadicodeai/design-system/tailwind").theme.extend;
7
+ const typographyUtilities = new Set(
8
+ Object.keys(generatedTheme.fontSize).map((name) => `nc-type-${name}`),
9
+ );
10
+ const colorTokens = new Set(Object.keys(generatedTheme.colors));
11
+ const COLOR_UTILITY =
12
+ /^(?:bg|text|border|outline|ring|fill|stroke|decoration|accent|caret|divide|from|via|to|shadow)-nc-([^/]+)(?:\/.*)?$/;
13
+
14
+ function withoutVariants(utility) {
15
+ return utility.slice(utility.lastIndexOf(":") + 1);
16
+ }
17
+
18
+ function isInvalidGeneratedUtility(utility) {
19
+ const unqualified = withoutVariants(utility);
20
+ if (unqualified.startsWith("nc-type-")) {
21
+ return !typographyUtilities.has(unqualified);
22
+ }
23
+
24
+ const color = COLOR_UTILITY.exec(unqualified);
25
+ return color ? !colorTokens.has(color[1]) : false;
26
+ }
27
+
28
+ export const noInvalidTokenUtility = {
29
+ meta: {
30
+ type: "problem",
31
+ docs: {
32
+ description: "Disallow token utilities that are absent from generated design-system output",
33
+ },
34
+ schema: [],
35
+ messages: {
36
+ invalidTokenUtility:
37
+ "{{utility}} is not generated by the installed NadicodeAI design system. Use a utility from @nadicodeai/design-system/tailwind.",
38
+ },
39
+ },
40
+ create(context) {
41
+ return tokenUtilityVisitors(context, (node, utility) => {
42
+ if (!isInvalidGeneratedUtility(utility)) return;
43
+ context.report({ node, messageId: "invalidTokenUtility", data: { utility } });
44
+ });
45
+ },
46
+ };
@@ -0,0 +1,86 @@
1
+ import { isPackageOwnedPrimitive } from "./jsx-class-utility.js";
2
+
3
+ const NATIVE_CONTROLS = new Set(["button", "input", "select", "textarea"]);
4
+
5
+ function staticValue(node) {
6
+ if (node?.type === "Literal") {
7
+ return node.value;
8
+ }
9
+ if (node?.type === "JSXExpressionContainer") {
10
+ return staticValue(node.expression);
11
+ }
12
+ if (node?.type === "TemplateLiteral" && node.expressions.length === 0) {
13
+ return node.quasis[0]?.value.cooked;
14
+ }
15
+ return undefined;
16
+ }
17
+
18
+ function hiddenInput(node) {
19
+ const typeAttribute = node.attributes.find(
20
+ (attribute) => attribute.type === "JSXAttribute" && attribute.name.name === "type",
21
+ );
22
+ return staticValue(typeAttribute?.value) === "hidden";
23
+ }
24
+
25
+ function isPrimitiveRenderElement(node, packagePrimitiveNames) {
26
+ const expression = node.parent;
27
+ const attribute = expression?.parent;
28
+ const openingElement = attribute?.parent;
29
+ return (
30
+ expression?.type === "JSXExpressionContainer" &&
31
+ attribute?.type === "JSXAttribute" &&
32
+ attribute.name.name === "render" &&
33
+ openingElement?.type === "JSXOpeningElement" &&
34
+ openingElement.name.type === "JSXIdentifier" &&
35
+ packagePrimitiveNames.has(openingElement.name.name)
36
+ );
37
+ }
38
+
39
+ export const noNativeVisibleControl = {
40
+ meta: {
41
+ type: "problem",
42
+ docs: {
43
+ description: "Disallow visible native controls in app source; use @nadicodeai/ui primitives",
44
+ },
45
+ schema: [],
46
+ messages: {
47
+ nativeVisibleControl:
48
+ "Use the @nadicodeai/ui primitive instead of native visible <{{element}}>.",
49
+ },
50
+ },
51
+ create(context) {
52
+ if (isPackageOwnedPrimitive(context.filename)) {
53
+ return {};
54
+ }
55
+ const packagePrimitiveNames = new Set();
56
+ return {
57
+ ImportDeclaration(node) {
58
+ if (
59
+ typeof node.source.value !== "string" ||
60
+ !node.source.value.startsWith("@nadicodeai/ui")
61
+ ) {
62
+ return;
63
+ }
64
+ for (const specifier of node.specifiers) {
65
+ packagePrimitiveNames.add(specifier.local.name);
66
+ }
67
+ },
68
+ JSXOpeningElement(node) {
69
+ if (node.name.type !== "JSXIdentifier" || !NATIVE_CONTROLS.has(node.name.name)) {
70
+ return;
71
+ }
72
+ if (node.name.name === "input" && hiddenInput(node)) {
73
+ return;
74
+ }
75
+ if (isPrimitiveRenderElement(node.parent, packagePrimitiveNames)) {
76
+ return;
77
+ }
78
+ context.report({
79
+ node: node.name,
80
+ messageId: "nativeVisibleControl",
81
+ data: { element: node.name.name },
82
+ });
83
+ },
84
+ };
85
+ },
86
+ };