@nadicodeai/ui 12.1.165 → 12.1.167

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 (367) hide show
  1. package/AGENTS.md +8 -9
  2. package/README.md +2 -17
  3. package/dist/components/accordion.d.ts.map +1 -1
  4. package/dist/components/accordion.js +2 -1
  5. package/dist/components/account-menu.d.ts.map +1 -1
  6. package/dist/components/account-menu.js +5 -3
  7. package/dist/components/activity-calendar.d.ts.map +1 -1
  8. package/dist/components/activity-calendar.js +3 -2
  9. package/dist/components/agent-card.js +1 -1
  10. package/dist/components/agent-orb.d.ts.map +1 -1
  11. package/dist/components/agent-orb.js +1 -0
  12. package/dist/components/agent-profile.d.ts.map +1 -1
  13. package/dist/components/agent-profile.js +7 -4
  14. package/dist/components/alert-dialog.d.ts +1 -1
  15. package/dist/components/alert-dialog.d.ts.map +1 -1
  16. package/dist/components/alert-dialog.js +3 -3
  17. package/dist/components/app-mark.js +1 -1
  18. package/dist/components/avatar.js +8 -8
  19. package/dist/components/badge.d.ts +11 -16
  20. package/dist/components/badge.d.ts.map +1 -1
  21. package/dist/components/badge.js +7 -43
  22. package/dist/components/breadcrumb.d.ts.map +1 -1
  23. package/dist/components/breadcrumb.js +3 -2
  24. package/dist/components/button.d.ts +5 -21
  25. package/dist/components/button.d.ts.map +1 -1
  26. package/dist/components/button.js +6 -76
  27. package/dist/components/calendar.d.ts +1 -1
  28. package/dist/components/calendar.d.ts.map +1 -1
  29. package/dist/components/calendar.js +3 -3
  30. package/dist/components/card-row.js +1 -1
  31. package/dist/components/card.d.ts +4 -1
  32. package/dist/components/card.d.ts.map +1 -1
  33. package/dist/components/card.js +3 -2
  34. package/dist/components/catalog-drawer.d.ts.map +1 -1
  35. package/dist/components/catalog-drawer.js +3 -2
  36. package/dist/components/chart-axis.d.ts.map +1 -1
  37. package/dist/components/chart-axis.js +0 -2
  38. package/dist/components/chart-bar-horizontal.d.ts.map +1 -1
  39. package/dist/components/chart-bar-horizontal.js +16 -14
  40. package/dist/components/chart-card.d.ts.map +1 -1
  41. package/dist/components/chart-card.js +0 -1
  42. package/dist/components/chart.d.ts.map +1 -1
  43. package/dist/components/chart.js +18 -32
  44. package/dist/components/checkbox.d.ts +3 -2
  45. package/dist/components/checkbox.d.ts.map +1 -1
  46. package/dist/components/checkbox.js +4 -3
  47. package/dist/components/choicebox.d.ts +5 -5
  48. package/dist/components/choicebox.d.ts.map +1 -1
  49. package/dist/components/choicebox.js +6 -5
  50. package/dist/components/clearable-input.d.ts.map +1 -1
  51. package/dist/components/clearable-input.js +2 -2
  52. package/dist/components/code-block.d.ts.map +1 -1
  53. package/dist/components/code-block.js +4 -2
  54. package/dist/components/collapsible.js +1 -1
  55. package/dist/components/collection-filters.d.ts.map +1 -1
  56. package/dist/components/collection-filters.js +1 -0
  57. package/dist/components/collection-page.js +1 -1
  58. package/dist/components/collection-sort.d.ts.map +1 -1
  59. package/dist/components/collection-sort.js +1 -4
  60. package/dist/components/collection-toolbar.js +1 -1
  61. package/dist/components/combobox.js +4 -4
  62. package/dist/components/command.d.ts.map +1 -1
  63. package/dist/components/command.js +1 -1
  64. package/dist/components/confirm-dialog.js +2 -2
  65. package/dist/components/context-menu.d.ts +1 -1
  66. package/dist/components/context-menu.d.ts.map +1 -1
  67. package/dist/components/copy-button.js +1 -1
  68. package/dist/components/data-table.d.ts +14 -7
  69. package/dist/components/data-table.d.ts.map +1 -1
  70. package/dist/components/data-table.js +24 -15
  71. package/dist/components/dialog.d.ts +1 -1
  72. package/dist/components/dialog.d.ts.map +1 -1
  73. package/dist/components/dialog.js +2 -2
  74. package/dist/components/drawer.d.ts +4 -4
  75. package/dist/components/drawer.d.ts.map +1 -1
  76. package/dist/components/drawer.js +14 -15
  77. package/dist/components/dropdown-menu.d.ts +1 -1
  78. package/dist/components/dropdown-menu.d.ts.map +1 -1
  79. package/dist/components/dropdown-menu.js +9 -5
  80. package/dist/components/empty-art.js +1 -1
  81. package/dist/components/empty-state.js +2 -2
  82. package/dist/components/entry-scene.d.ts.map +1 -1
  83. package/dist/components/entry-scene.js +2 -3
  84. package/dist/components/field.js +3 -3
  85. package/dist/components/file-diff.d.ts.map +1 -1
  86. package/dist/components/file-diff.js +5 -2
  87. package/dist/components/footer.d.ts +1 -1
  88. package/dist/components/footer.d.ts.map +1 -1
  89. package/dist/components/footer.js +3 -3
  90. package/dist/components/form-dialog.d.ts.map +1 -1
  91. package/dist/components/form-dialog.js +2 -1
  92. package/dist/components/form-drawer.d.ts +7 -9
  93. package/dist/components/form-drawer.d.ts.map +1 -1
  94. package/dist/components/form-drawer.js +5 -5
  95. package/dist/components/form.d.ts +26 -0
  96. package/dist/components/form.d.ts.map +1 -0
  97. package/dist/components/form.js +29 -0
  98. package/dist/components/gauge.js +2 -2
  99. package/dist/components/heatmap/calendar-heatmap.d.ts.map +1 -1
  100. package/dist/components/heatmap/calendar-heatmap.js +15 -13
  101. package/dist/components/hive-scene.d.ts.map +1 -1
  102. package/dist/components/hive-scene.js +3 -1
  103. package/dist/components/hover-card.d.ts +1 -1
  104. package/dist/components/hover-card.d.ts.map +1 -1
  105. package/dist/components/hover-card.js +1 -1
  106. package/dist/components/input-group.d.ts +5 -6
  107. package/dist/components/input-group.d.ts.map +1 -1
  108. package/dist/components/input-group.js +8 -11
  109. package/dist/components/input-otp.d.ts.map +1 -1
  110. package/dist/components/input-otp.js +2 -2
  111. package/dist/components/item.d.ts +1 -1
  112. package/dist/components/item.js +2 -2
  113. package/dist/components/kbd.d.ts +6 -9
  114. package/dist/components/kbd.d.ts.map +1 -1
  115. package/dist/components/kbd.js +7 -3
  116. package/dist/components/message-notice.js +1 -1
  117. package/dist/components/middle-truncate.d.ts.map +1 -1
  118. package/dist/components/middle-truncate.js +1 -0
  119. package/dist/components/model-identity.d.ts +4 -4
  120. package/dist/components/model-identity.d.ts.map +1 -1
  121. package/dist/components/model-identity.js +2 -2
  122. package/dist/components/model-mark.d.ts.map +1 -1
  123. package/dist/components/model-mark.js +4 -2
  124. package/dist/components/multi-select.js +2 -2
  125. package/dist/components/native-select.d.ts.map +1 -1
  126. package/dist/components/native-select.js +2 -6
  127. package/dist/components/notice-banner.js +1 -1
  128. package/dist/components/object-page.js +2 -2
  129. package/dist/components/object-workspace.d.ts.map +1 -1
  130. package/dist/components/object-workspace.js +1 -3
  131. package/dist/components/overview-page.d.ts +1 -1
  132. package/dist/components/overview-page.d.ts.map +1 -1
  133. package/dist/components/overview-page.js +2 -1
  134. package/dist/components/page-actions.d.ts.map +1 -1
  135. package/dist/components/page-actions.js +9 -4
  136. package/dist/components/pairing-code.js +1 -1
  137. package/dist/components/pending-label.d.ts.map +1 -1
  138. package/dist/components/pending-label.js +0 -1
  139. package/dist/components/popover.d.ts +1 -1
  140. package/dist/components/popover.d.ts.map +1 -1
  141. package/dist/components/portal-sidebar-frame.d.ts.map +1 -1
  142. package/dist/components/portal-sidebar-frame.js +1 -1
  143. package/dist/components/product-message.d.ts.map +1 -1
  144. package/dist/components/product-message.js +1 -0
  145. package/dist/components/progress-checklist.d.ts.map +1 -1
  146. package/dist/components/progress-checklist.js +2 -2
  147. package/dist/components/progress.d.ts.map +1 -1
  148. package/dist/components/progress.js +5 -4
  149. package/dist/components/radio-group.js +2 -2
  150. package/dist/components/reading-column.js +1 -1
  151. package/dist/components/record-identity.d.ts.map +1 -1
  152. package/dist/components/record-identity.js +2 -5
  153. package/dist/components/record-list.d.ts +5 -4
  154. package/dist/components/record-list.d.ts.map +1 -1
  155. package/dist/components/record-list.js +31 -17
  156. package/dist/components/record-sheet.js +1 -1
  157. package/dist/components/record-time.d.ts.map +1 -1
  158. package/dist/components/record-time.js +2 -1
  159. package/dist/components/resizable.d.ts.map +1 -1
  160. package/dist/components/resizable.js +1 -1
  161. package/dist/components/row-edit-form.d.ts +2 -1
  162. package/dist/components/row-edit-form.d.ts.map +1 -1
  163. package/dist/components/row-edit-form.js +2 -1
  164. package/dist/components/run-timeline.js +1 -1
  165. package/dist/components/scope-switcher.js +1 -1
  166. package/dist/components/segmented-control.js +1 -1
  167. package/dist/components/select.js +1 -1
  168. package/dist/components/settings-facts.js +1 -1
  169. package/dist/components/settings-section.js +1 -1
  170. package/dist/components/sheet.d.ts +1 -1
  171. package/dist/components/sheet.d.ts.map +1 -1
  172. package/dist/components/sheet.js +1 -1
  173. package/dist/components/sidebar.d.ts +2 -2
  174. package/dist/components/sidebar.d.ts.map +1 -1
  175. package/dist/components/sidebar.js +16 -18
  176. package/dist/components/site-menu.d.ts +28 -0
  177. package/dist/components/site-menu.d.ts.map +1 -0
  178. package/dist/components/site-menu.js +23 -0
  179. package/dist/components/slider.d.ts.map +1 -1
  180. package/dist/components/slider.js +2 -1
  181. package/dist/components/snippet.d.ts +2 -0
  182. package/dist/components/snippet.d.ts.map +1 -1
  183. package/dist/components/snippet.js +13 -6
  184. package/dist/components/sonner.d.ts.map +1 -1
  185. package/dist/components/sonner.js +3 -4
  186. package/dist/components/status-badge.d.ts +1 -1
  187. package/dist/components/status-badge.d.ts.map +1 -1
  188. package/dist/components/switch.js +1 -1
  189. package/dist/components/table-card.js +1 -1
  190. package/dist/components/table-layouts.d.ts +24 -9
  191. package/dist/components/table-layouts.d.ts.map +1 -1
  192. package/dist/components/table-layouts.js +27 -10
  193. package/dist/components/table.js +4 -4
  194. package/dist/components/tabs-nav.d.ts +52 -0
  195. package/dist/components/tabs-nav.d.ts.map +1 -0
  196. package/dist/components/tabs-nav.js +95 -0
  197. package/dist/components/tabs.d.ts +2 -56
  198. package/dist/components/tabs.d.ts.map +1 -1
  199. package/dist/components/tabs.js +2 -91
  200. package/dist/components/text-link.d.ts +1 -2
  201. package/dist/components/text-link.d.ts.map +1 -1
  202. package/dist/components/text-link.js +1 -2
  203. package/dist/components/textarea.d.ts +5 -2
  204. package/dist/components/textarea.d.ts.map +1 -1
  205. package/dist/components/textarea.js +12 -4
  206. package/dist/components/toast.d.ts +2 -0
  207. package/dist/components/toast.d.ts.map +1 -1
  208. package/dist/components/toast.js +4 -0
  209. package/dist/components/toggle-group.d.ts +3 -1
  210. package/dist/components/toggle-group.d.ts.map +1 -1
  211. package/dist/components/toggle-group.js +3 -6
  212. package/dist/components/toggle.js +1 -1
  213. package/dist/components/tooltip.d.ts +12 -12
  214. package/dist/components/tooltip.d.ts.map +1 -1
  215. package/dist/components/tooltip.js +9 -9
  216. package/dist/components/trend-badge.js +2 -2
  217. package/dist/components/update-card.js +1 -1
  218. package/dist/components/usage-meter.d.ts +1 -1
  219. package/dist/components/usage-meter.d.ts.map +1 -1
  220. package/dist/components/usage-meter.js +9 -7
  221. package/dist/components/waiting-line.js +1 -1
  222. package/dist/index.d.ts +3 -7
  223. package/dist/index.d.ts.map +1 -1
  224. package/dist/index.js +3 -7
  225. package/dist/internal/agent-orb-motion.d.ts +4 -1
  226. package/dist/internal/agent-orb-motion.d.ts.map +1 -1
  227. package/dist/internal/agent-orb-motion.js +9 -7
  228. package/dist/internal/agent-orb.d.ts +4 -1
  229. package/dist/internal/agent-orb.d.ts.map +1 -1
  230. package/dist/internal/agent-orb.js +7 -1
  231. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  232. package/dist/internal/assistant-ui/attachment.js +15 -15
  233. package/dist/internal/assistant-ui/follow-up-suggestions.js +1 -1
  234. package/dist/internal/assistant-ui/markdown-text.js +26 -25
  235. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  236. package/dist/internal/assistant-ui/reasoning.js +13 -16
  237. package/dist/internal/assistant-ui/thread.d.ts.map +1 -1
  238. package/dist/internal/assistant-ui/thread.js +22 -16
  239. package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -1
  240. package/dist/internal/assistant-ui/tool-fallback.js +29 -21
  241. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  242. package/dist/internal/assistant-ui/tool-group.js +6 -7
  243. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  244. package/dist/internal/badge-frame.d.ts +15 -0
  245. package/dist/internal/badge-frame.d.ts.map +1 -0
  246. package/dist/internal/badge-frame.js +44 -0
  247. package/dist/internal/button-classes.d.ts +20 -0
  248. package/dist/internal/button-classes.d.ts.map +1 -0
  249. package/dist/internal/button-classes.js +74 -0
  250. package/dist/internal/catalog-list.d.ts.map +1 -1
  251. package/dist/internal/catalog-list.js +8 -4
  252. package/dist/internal/collection-rail.js +3 -3
  253. package/dist/internal/form-drawer-frame.d.ts +10 -0
  254. package/dist/internal/form-drawer-frame.d.ts.map +1 -0
  255. package/dist/internal/form-drawer-frame.js +9 -0
  256. package/dist/internal/form-submit.d.ts +2 -1
  257. package/dist/internal/form-submit.d.ts.map +1 -1
  258. package/dist/internal/settings-save.d.ts.map +1 -1
  259. package/dist/internal/settings-save.js +4 -2
  260. package/dist/internal/status-mark.d.ts.map +1 -1
  261. package/dist/internal/status-mark.js +4 -1
  262. package/dist/internal/tab-row.d.ts +10 -0
  263. package/dist/internal/tab-row.d.ts.map +1 -0
  264. package/dist/internal/tab-row.js +2 -0
  265. package/dist/internal/table-compact-line.d.ts +1 -1
  266. package/dist/internal/table-compact-line.d.ts.map +1 -1
  267. package/dist/internal/table-compact-line.js +1 -1
  268. package/dist/internal/tooltip-content-frame.d.ts +14 -0
  269. package/dist/internal/tooltip-content-frame.d.ts.map +1 -0
  270. package/dist/internal/tooltip-content-frame.js +11 -0
  271. package/dist/lib/css-variables.d.ts +8 -0
  272. package/dist/lib/css-variables.d.ts.map +1 -0
  273. package/dist/lib/css-variables.js +4 -0
  274. package/dist/lib/merge-tokens.generated.js +1 -1
  275. package/dist/lib/use-copy-to-clipboard.d.ts.map +1 -1
  276. package/dist/lib/use-copy-to-clipboard.js +1 -2
  277. package/dist/showcase/samples.js +1 -1
  278. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  279. package/dist/showcase/specimens/choices.js +3 -2
  280. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  281. package/dist/showcase/specimens/compositions.js +7 -5
  282. package/dist/showcase/specimens/data.d.ts.map +1 -1
  283. package/dist/showcase/specimens/data.js +1 -1
  284. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  285. package/dist/showcase/specimens/feedback.js +1 -2
  286. package/dist/showcase/specimens/index.d.ts +2 -0
  287. package/dist/showcase/specimens/index.d.ts.map +1 -1
  288. package/dist/showcase/specimens/inputs.d.ts +1 -0
  289. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  290. package/dist/showcase/specimens/inputs.js +5 -2
  291. package/dist/showcase/specimens/menus.d.ts +1 -0
  292. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  293. package/dist/showcase/specimens/menus.js +7 -2
  294. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  295. package/dist/showcase/specimens/navigation.js +6 -5
  296. package/dist/showcase/specimens/status.d.ts.map +1 -1
  297. package/dist/showcase/specimens/status.js +4 -4
  298. package/dist/showcase/usage.generated.d.ts +1 -1
  299. package/dist/showcase/usage.generated.d.ts.map +1 -1
  300. package/dist/showcase/usage.generated.js +40 -18
  301. package/dist/standalone/index.js +2 -2
  302. package/dist/standalone/orb-page.js +10 -8
  303. package/dist/styles/components.css +14 -1
  304. package/package.json +32 -33
  305. package/dist/eslint/index.js +0 -224
  306. package/dist/eslint/rules/badge-is-static-label.js +0 -93
  307. package/dist/eslint/rules/button-icon-slot.js +0 -102
  308. package/dist/eslint/rules/button-link-for-navigation.js +0 -146
  309. package/dist/eslint/rules/button-no-aria-label-with-text.js +0 -75
  310. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +0 -83
  311. package/dist/eslint/rules/choice-control-has-a-name.js +0 -98
  312. package/dist/eslint/rules/choice-group-in-fieldset.js +0 -86
  313. package/dist/eslint/rules/command-shortcut-single-owner.js +0 -118
  314. package/dist/eslint/rules/confirm-dialog-words.js +0 -63
  315. package/dist/eslint/rules/data-table-one-unsized-column.js +0 -96
  316. package/dist/eslint/rules/destructive-action-placement.js +0 -69
  317. package/dist/eslint/rules/disabled-choice-says-why.js +0 -71
  318. package/dist/eslint/rules/disabled-control-appearance.js +0 -75
  319. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +0 -110
  320. package/dist/eslint/rules/empty-state-owner.js +0 -145
  321. package/dist/eslint/rules/input-group-owners.js +0 -155
  322. package/dist/eslint/rules/jsx-class-utility.js +0 -200
  323. package/dist/eslint/rules/kbd-children-no-modifier-text.js +0 -128
  324. package/dist/eslint/rules/literal-text.js +0 -41
  325. package/dist/eslint/rules/menu-owner.js +0 -75
  326. package/dist/eslint/rules/middle-truncate-placement.js +0 -69
  327. package/dist/eslint/rules/no-app-feature-component.js +0 -100
  328. package/dist/eslint/rules/no-bare-button-label.js +0 -55
  329. package/dist/eslint/rules/no-choice-control-wrapper.js +0 -97
  330. package/dist/eslint/rules/no-comment.js +0 -77
  331. package/dist/eslint/rules/no-control-in-read-only-surface.js +0 -106
  332. package/dist/eslint/rules/no-decorative-icon.js +0 -164
  333. package/dist/eslint/rules/no-deprecated-zod-api.js +0 -215
  334. package/dist/eslint/rules/no-global-patch.js +0 -115
  335. package/dist/eslint/rules/no-hand-built-busy.js +0 -104
  336. package/dist/eslint/rules/no-hand-built-theme-picker.js +0 -144
  337. package/dist/eslint/rules/no-hand-built-tile.js +0 -41
  338. package/dist/eslint/rules/no-hand-formatted-date.js +0 -87
  339. package/dist/eslint/rules/no-hand-stacked-avatars.js +0 -67
  340. package/dist/eslint/rules/no-nested-collapse.js +0 -60
  341. package/dist/eslint/rules/no-package-component-redefinition.js +0 -175
  342. package/dist/eslint/rules/no-search-in-form.js +0 -47
  343. package/dist/eslint/rules/no-shadcn-appearance-override.js +0 -305
  344. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +0 -74
  345. package/dist/eslint/rules/no-stock-error-words.js +0 -56
  346. package/dist/eslint/rules/no-subject-derived-expectation.js +0 -183
  347. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +0 -72
  348. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +0 -57
  349. package/dist/eslint/rules/no-write-in-subscription.js +0 -140
  350. package/dist/eslint/rules/one-submenu-level.js +0 -43
  351. package/dist/eslint/rules/one-toast-per-flow.js +0 -91
  352. package/dist/eslint/rules/option-count.js +0 -167
  353. package/dist/eslint/rules/page-command-link-not-render.js +0 -43
  354. package/dist/eslint/rules/page-composition.js +0 -232
  355. package/dist/eslint/rules/progress-needs-name.js +0 -57
  356. package/dist/eslint/rules/rendered-import.js +0 -121
  357. package/dist/eslint/rules/server-action-discipline.js +0 -233
  358. package/dist/eslint/rules/settings-limit-in-footer.js +0 -94
  359. package/dist/eslint/rules/skeleton-in-region.js +0 -80
  360. package/dist/eslint/rules/sortable-heading-uses-sort.js +0 -79
  361. package/dist/eslint/rules/table-cell-inset-owner.js +0 -107
  362. package/dist/eslint/rules/tabs-selection-is-controlled.js +0 -47
  363. package/dist/eslint/rules/test-files-from-one-definition.js +0 -67
  364. package/dist/eslint/rules/tooltip-only-arrow.js +0 -38
  365. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +0 -114
  366. package/dist/eslint/rules/workspace-declares-imports.js +0 -163
  367. package/dist/eslint/strict-design-system.js +0 -250
@@ -1,106 +0,0 @@
1
- /*
2
- * Standard tool checked first: a `no-restricted-syntax` selector can match a
3
- * `Button` below `TooltipContent`, but not follow a renamed import to the part,
4
- * count the links across a HoverCardContent's children and its summary's
5
- * `action`.
6
- */
7
- import { renderedImports, walk } from "./rendered-import.js";
8
-
9
- const OVERLAYS = new Set(["Tooltip", "HoverCard"]);
10
- const CONTROLS = new Set(["Button", "ButtonLink", "TextLink", "Link", "a"]);
11
- const NATIVE_CONTROLS = new Set(["input", "select", "textarea"]);
12
- const HOVER_CARD_SUMMARY = "HoverCardSummary";
13
-
14
- const hasAttribute = (openingElement, attributeName) =>
15
- openingElement.attributes.some(
16
- (attribute) => attribute.type === "JSXAttribute" && attribute.name.name === attributeName,
17
- );
18
-
19
- export const noControlInReadOnlySurface = {
20
- meta: {
21
- type: "problem",
22
- docs: {
23
- description:
24
- "Tooltip text and a Choicebox tile are for reading; a HoverCard holds at most one link.",
25
- },
26
- schema: [],
27
- messages: {
28
- "read-only-surface":
29
- "Tooltip text and a Choicebox tile are for reading: move the control outside. A HoverCard holds at most one link, through HoverCardSummary's `action`, and never a second Tooltip or HoverCard; for more, open a Popover, a menu or the record's page.",
30
- },
31
- },
32
- create(context) {
33
- const importOf = renderedImports(context);
34
- const { visitorKeys } = context.sourceCode;
35
-
36
- const nameOf = (element) => {
37
- const { name } = element.openingElement;
38
- if (name.type !== "JSXIdentifier" && name.type !== "JSXMemberExpression") return null;
39
- if (name.type === "JSXIdentifier" && /^[a-z]/.test(name.name)) return name.name;
40
- const imported = importOf(name);
41
- if (!imported) return null;
42
- return imported.name === "default" ? name.name : imported.name;
43
- };
44
-
45
- const isInteractive = (element, name) =>
46
- CONTROLS.has(name) ||
47
- NATIVE_CONTROLS.has(name) ||
48
- hasAttribute(element.openingElement, "onClick") ||
49
- hasAttribute(element.openingElement, "tabIndex");
50
-
51
- function visitChildren(container, visit) {
52
- for (const child of container.children) {
53
- if (visit(child) === false) continue;
54
- walk(child, visitorKeys, visit);
55
- }
56
- }
57
-
58
- function checkTooltipContent(container) {
59
- visitChildren(container, (child) => {
60
- if (child.type !== "JSXElement") return true;
61
- const name = nameOf(child);
62
- if (!OVERLAYS.has(name) && !isInteractive(child, name)) return true;
63
- context.report({ node: child.openingElement, messageId: "read-only-surface" });
64
- return false;
65
- });
66
- }
67
-
68
- function checkChoiceboxItem(container) {
69
- visitChildren(container, (child) => {
70
- if (child.type !== "JSXElement" || !isInteractive(child, nameOf(child))) return true;
71
- context.report({ node: child.openingElement, messageId: "read-only-surface" });
72
- return false;
73
- });
74
- }
75
-
76
- function checkHoverCardContent(container) {
77
- let links = 0;
78
- visitChildren(container, (child) => {
79
- if (child.type !== "JSXElement") return true;
80
- const name = nameOf(child);
81
- const { openingElement } = child;
82
- if (OVERLAYS.has(name)) {
83
- context.report({ node: openingElement, messageId: "read-only-surface" });
84
- return false;
85
- }
86
- const isLink =
87
- CONTROLS.has(name) ||
88
- hasAttribute(openingElement, "onClick") ||
89
- (name === HOVER_CARD_SUMMARY && hasAttribute(openingElement, "action"));
90
- if (!isLink) return true;
91
- links += 1;
92
- if (links > 1) context.report({ node: openingElement, messageId: "read-only-surface" });
93
- return true;
94
- });
95
- }
96
-
97
- return {
98
- JSXElement(node) {
99
- const name = nameOf(node);
100
- if (name === "TooltipContent") checkTooltipContent(node);
101
- else if (name === "ChoiceboxGroupItem") checkChoiceboxItem(node);
102
- else if (name === "HoverCardContent") checkHoverCardContent(node);
103
- },
104
- };
105
- },
106
- };
@@ -1,164 +0,0 @@
1
- /*
2
- * Standard tool checked first: a `no-restricted-syntax` selector such as
3
- * `CardTitle JSXOpeningElement` matches any element under a title, not the
4
- * ones bound to an icon module, and cannot stop at a control between the two
5
- * (`<CardHeader><Button><Plus/></Button></CardHeader>` is allowed). This rule
6
- * joins the element to its import and reads the nearest container above it.
7
- */
8
- import { renderedImports, sourceMatches, writtenName } from "./rendered-import.js";
9
-
10
- export const noDecorativeIcon = {
11
- meta: {
12
- type: "problem",
13
- docs: {
14
- description:
15
- "A title or a label carries no icon; an icon belongs to a control or a menu row.",
16
- },
17
- schema: [
18
- {
19
- type: "object",
20
- properties: {
21
- iconModules: { type: "array", items: { type: "string" }, uniqueItems: true },
22
- headings: { type: "array", items: { type: "string" }, uniqueItems: true },
23
- controls: { type: "array", items: { type: "string" }, uniqueItems: true },
24
- },
25
- additionalProperties: false,
26
- },
27
- ],
28
- defaultOptions: [
29
- {
30
- iconModules: ["lucide-react", "@nadicodeai/ui/components/house-icons"],
31
- headings: [
32
- "h1",
33
- "h2",
34
- "h3",
35
- "h4",
36
- "h5",
37
- "h6",
38
- "legend",
39
- "dt",
40
- "th",
41
- "caption",
42
- "CardTitle",
43
- "CardDescription",
44
- "CardHeader",
45
- "DialogTitle",
46
- "SheetTitle",
47
- "AlertDialogTitle",
48
- "DrawerTitle",
49
- "FieldLabel",
50
- "FieldLegend",
51
- "Label",
52
- "ItemTitle",
53
- "TableHead",
54
- ],
55
- controls: [
56
- "button",
57
- "a",
58
- "Button",
59
- "Link",
60
- "CardAction",
61
- "TabsTrigger",
62
- "TabsLink",
63
- "ToggleGroupItem",
64
- "Toggle",
65
- "SidebarMenuButton",
66
- "InputGroupAddon",
67
- "InputGroupButton",
68
- ],
69
- },
70
- ],
71
- messages: {
72
- "beside-heading":
73
- "A title or a label carries no icon: an identity mark starts a row or a card (IdentityMark), and an icon belongs to a control or a menu row.",
74
- },
75
- },
76
- create(context) {
77
- const [{ iconModules, headings, controls }] = context.options;
78
- const headingNames = new Set(headings);
79
- const controlNames = new Set(controls);
80
- const importOf = renderedImports(context);
81
- const isIconImport = (name) => {
82
- const imported = importOf({ type: "JSXIdentifier", name });
83
- return (
84
- imported !== null &&
85
- iconModules.some((module) => sourceMatches(imported.source, module, context.filename))
86
- );
87
- };
88
-
89
- function constantOf(name, scope) {
90
- for (let current = scope; current; current = current.upper) {
91
- const variable = current.set.get(name);
92
- if (!variable) continue;
93
- const [definition] = variable.defs;
94
- const declared =
95
- definition?.type === "Variable" && definition.parent.kind === "const"
96
- ? definition.node.init
97
- : null;
98
- return declared ?? null;
99
- }
100
- return null;
101
- }
102
-
103
- function holdsAnIcon(value, scope, seen = new Set()) {
104
- if (!value || seen.has(value)) return false;
105
- seen.add(value);
106
- switch (value.type) {
107
- case "Identifier":
108
- return (
109
- isIconImport(value.name) || holdsAnIcon(constantOf(value.name, scope), scope, seen)
110
- );
111
- case "MemberExpression":
112
- return holdsAnIcon(value.object, scope, seen);
113
- case "ConditionalExpression":
114
- return [value.consequent, value.alternate].some((branch) =>
115
- holdsAnIcon(branch, scope, seen),
116
- );
117
- case "LogicalExpression":
118
- return [value.left, value.right].some((side) => holdsAnIcon(side, scope, seen));
119
- case "ObjectExpression":
120
- return value.properties.some(
121
- (property) => property.type === "Property" && holdsAnIcon(property.value, scope, seen),
122
- );
123
- case "ArrayExpression":
124
- return value.elements.some((element) => holdsAnIcon(element, scope, seen));
125
- default:
126
- return false;
127
- }
128
- }
129
-
130
- function isIcon(openingElement) {
131
- const imported = importOf(openingElement.name);
132
- if (imported) {
133
- return iconModules.some((module) =>
134
- sourceMatches(imported.source, module, context.filename),
135
- );
136
- }
137
- const { name } = openingElement;
138
- if (name.type !== "JSXIdentifier" || !/^[A-Z]/.test(name.name)) return false;
139
- const scope = context.sourceCode.getScope(openingElement);
140
- return holdsAnIcon(constantOf(name.name, scope), scope);
141
- }
142
-
143
- return {
144
- JSXOpeningElement(node) {
145
- if (!isIcon(node)) return;
146
- for (let current = node.parent.parent; current; current = current.parent) {
147
- if (current.type === "JSXAttribute") {
148
- if (headingNames.has(writtenName(current.parent.name))) {
149
- context.report({ node, messageId: "beside-heading" });
150
- }
151
- return;
152
- }
153
- if (current.type !== "JSXElement") continue;
154
- const name = writtenName(current.openingElement.name);
155
- if (controlNames.has(name)) return;
156
- if (headingNames.has(name)) {
157
- context.report({ node, messageId: "beside-heading" });
158
- return;
159
- }
160
- }
161
- },
162
- };
163
- },
164
- };
@@ -1,215 +0,0 @@
1
- /*
2
- * Legacy Zod 3 APIs, in two sets that are enforced from two different places.
3
- *
4
- * UNANNOTATED — the three the installed zod 4.6.5 leaves without a
5
- * `@deprecated` tag: `promise` carries only prose, `.strict()` and `.strip()`
6
- * carry only a "consider…" hint. No tag means no type-aware rule can fire on
7
- * them, so they are this rule's own policy and are reported in every
8
- * workspace.
9
- *
10
- * ANNOTATED — the rest, which Zod does tag `@deprecated`, `nativeEnum`
11
- * included. `@typescript-eslint/no-deprecated` reports those with the
12
- * library's own replacement text, but only where it is turned on, and it needs
13
- * type information. In this repository that is `@nadicodeai/ui` alone:
14
- * switching the Portal on measured 10.4s → 25.8s per lint run and surfaced 15
15
- * unrelated findings (React's `FormEvent`, vitest's `toThrowError`), so it
16
- * stays ui-only (#821). The Portal and the website are where this repository
17
- * writes most of its Zod, so the names stay listed here for them — a second
18
- * copy of an upstream annotation, kept deliberately because the alternative is
19
- * no coverage at all in two of three workspaces (#822).
20
- *
21
- * The split is a rule option: `upstreamAnnotated: "report"` (default) names
22
- * them, `"defer"` leaves them to the type-aware rule. `@nadicodeai/ui` selects
23
- * `"defer"` in the root config, so no tagged API is reported twice there.
24
- */
25
- const LEGACY_FACTORIES = new Map([["promise", "await the value before parsing it"]]);
26
-
27
- const UPSTREAM_ANNOTATED_FACTORIES = new Map([["nativeEnum", "z.enum()"]]);
28
-
29
- const LEGACY_METHODS = {
30
- object: new Map([
31
- ["strict", "z.strictObject()"],
32
- ["strip", "z.object(), which strips unknown keys by default"],
33
- ]),
34
- };
35
-
36
- const UPSTREAM_ANNOTATED_METHODS = {
37
- number: new Map([
38
- ["finite", "remove it; z.number() already rejects infinite values"],
39
- ["safe", ".int()"],
40
- ["step", ".multipleOf()"],
41
- ]),
42
- object: new Map([
43
- ["merge", ".extend(other.shape)"],
44
- ["passthrough", "z.looseObject()"],
45
- ]),
46
- string: new Map([
47
- ...[
48
- "base64",
49
- "base64url",
50
- "cidrv4",
51
- "cidrv6",
52
- "cuid",
53
- "cuid2",
54
- "e164",
55
- "email",
56
- "emoji",
57
- "guid",
58
- "ipv4",
59
- "ipv6",
60
- "jwt",
61
- "ksuid",
62
- "nanoid",
63
- "ulid",
64
- "url",
65
- "uuid",
66
- "uuidv4",
67
- "uuidv6",
68
- "uuidv7",
69
- "xid",
70
- ].map((name) => [name, `z.${name.startsWith("uuidv") ? "uuid" : name}()`]),
71
- ...["date", "datetime", "duration", "time"].map((name) => [name, `z.iso.${name}()`]),
72
- ]),
73
- };
74
-
75
- function defersAnnotated(context) {
76
- return context.options?.[0]?.upstreamAnnotated === "defer";
77
- }
78
-
79
- /** The factory table a run consults: the unannotated always, the annotated unless deferred. */
80
- function legacyFactories(context) {
81
- if (defersAnnotated(context)) return LEGACY_FACTORIES;
82
- return new Map([...UPSTREAM_ANNOTATED_FACTORIES, ...LEGACY_FACTORIES]);
83
- }
84
-
85
- /** The method table a run consults: the unannotated always, the annotated unless deferred. */
86
- function legacyMethods(context) {
87
- if (defersAnnotated(context)) return LEGACY_METHODS;
88
- const merged = {};
89
- for (const family of new Set([
90
- ...Object.keys(LEGACY_METHODS),
91
- ...Object.keys(UPSTREAM_ANNOTATED_METHODS),
92
- ])) {
93
- merged[family] = new Map([
94
- ...(UPSTREAM_ANNOTATED_METHODS[family] ?? []),
95
- ...(LEGACY_METHODS[family] ?? []),
96
- ]);
97
- }
98
- return merged;
99
- }
100
-
101
- function memberName(node) {
102
- if (!node.computed && node.property.type === "Identifier") {
103
- return node.property.name;
104
- }
105
- if (node.computed && node.property.type === "Literal") {
106
- // oxlint-disable-next-line anti-slop/no-runtime-typeof -- ESTree types Literal.value as string | number | boolean | RegExp | bigint | null; only typeof picks the string.
107
- return typeof node.property.value === "string" ? node.property.value : undefined;
108
- }
109
- return undefined;
110
- }
111
-
112
- export const noDeprecatedZodApi = {
113
- meta: {
114
- type: "problem",
115
- docs: {
116
- description: "Disallow the Zod 3 APIs that Zod 4 replaced without marking them @deprecated",
117
- },
118
- schema: [
119
- {
120
- type: "object",
121
- properties: { upstreamAnnotated: { enum: ["report", "defer"] } },
122
- additionalProperties: false,
123
- },
124
- ],
125
- messages: {
126
- legacyFactory: "{{api}} is legacy in Zod 4; use {{replacement}}.",
127
- legacyMethod: "{{api}} is legacy in Zod 4; use {{replacement}}.",
128
- },
129
- },
130
-
131
- create(context) {
132
- const sourceCode = context.sourceCode;
133
- const factories = legacyFactories(context);
134
- const methods = legacyMethods(context);
135
- const zodBindings = new Set();
136
-
137
- function isZodBinding(identifier) {
138
- for (let scope = sourceCode.getScope(identifier); scope; scope = scope.upper) {
139
- const variable = scope.set.get(identifier.name);
140
- if (variable) {
141
- return zodBindings.has(variable);
142
- }
143
- }
144
- return false;
145
- }
146
-
147
- function rootFactory(call) {
148
- if (call.type !== "CallExpression" || call.callee.type !== "MemberExpression") {
149
- return undefined;
150
- }
151
- const factory = memberName(call.callee);
152
- if (!factory) {
153
- return undefined;
154
- }
155
- if (call.callee.object.type === "Identifier" && isZodBinding(call.callee.object)) {
156
- return factory;
157
- }
158
- return rootFactory(call.callee.object);
159
- }
160
-
161
- return {
162
- ImportDeclaration(node) {
163
- if (node.source.value !== "zod") {
164
- return;
165
- }
166
- for (const specifier of node.specifiers) {
167
- const importsNamespace = specifier.type === "ImportNamespaceSpecifier";
168
- const importsZ =
169
- specifier.type === "ImportSpecifier" &&
170
- ((specifier.imported.type === "Identifier" && specifier.imported.name === "z") ||
171
- (specifier.imported.type === "Literal" && specifier.imported.value === "z"));
172
- if (!importsNamespace && !importsZ) {
173
- continue;
174
- }
175
- for (const variable of sourceCode.getDeclaredVariables(specifier)) {
176
- zodBindings.add(variable);
177
- }
178
- }
179
- },
180
-
181
- CallExpression(node) {
182
- if (node.callee.type !== "MemberExpression") {
183
- return;
184
- }
185
- const method = memberName(node.callee);
186
- if (!method) {
187
- return;
188
- }
189
-
190
- if (node.callee.object.type === "Identifier" && isZodBinding(node.callee.object)) {
191
- const replacement = factories.get(method);
192
- if (replacement) {
193
- context.report({
194
- node: node.callee.property,
195
- messageId: "legacyFactory",
196
- data: { api: `z.${method}()`, replacement },
197
- });
198
- }
199
- return;
200
- }
201
-
202
- const factory = rootFactory(node.callee.object);
203
- const family = factory === "strictObject" || factory === "looseObject" ? "object" : factory;
204
- const replacement = methods[family]?.get(method);
205
- if (replacement) {
206
- context.report({
207
- node: node.callee.property,
208
- messageId: "legacyMethod",
209
- data: { api: `z.${factory}().${method}()`, replacement },
210
- });
211
- }
212
- },
213
- };
214
- },
215
- };
@@ -1,115 +0,0 @@
1
- /*
2
- * A product built on another system's runtime must not replace what that
3
- * runtime calls: assigning `history.pushState`, a property of `window`, or a
4
- * member of a built-in prototype changes the code the other system runs, behind
5
- * its back. Nadia's desktop once replaced `history.pushState` and
6
- * `replaceState` to rewrite Hermes's routes; the product declares its intent to
7
- * the owning system instead.
8
- *
9
- * Standard tool checked first: core `no-restricted-syntax` can match an
10
- * assignment to `history.pushState` by name, but the route lock wrote it as
11
- * `const { history } = target; history.pushState = guarded`, and a member
12
- * reached through a local alias (`const h = window.history`) carries no global
13
- * name a selector can see. This rule resolves a local constant to what it was
14
- * initialised from before matching.
15
- *
16
- * Which objects count as globals is configuration: the workspace names them
17
- * where the rule is turned on, and this file holds only the matching.
18
- */
19
-
20
- const PATCHERS = new Set([
21
- "Object.assign",
22
- "Object.defineProperty",
23
- "Object.defineProperties",
24
- "Reflect.set",
25
- "Reflect.defineProperty",
26
- ]);
27
-
28
- function variableOf(scope, name) {
29
- for (let current = scope; current; current = current.upper) {
30
- const found = current.set.get(name);
31
- if (found) return found;
32
- }
33
- return null;
34
- }
35
-
36
- function aliasOf(context, identifier) {
37
- const variable = variableOf(context.sourceCode.getScope(identifier), identifier.name);
38
- const definition = variable?.defs.length === 1 ? variable.defs[0] : null;
39
- if (definition?.type !== "Variable" || definition.parent?.kind !== "const") return null;
40
- const { id, init } = definition.node;
41
- return id.type === "Identifier" && init ? init : null;
42
- }
43
-
44
- function pathOf(context, node, seen = new Set()) {
45
- if (node.type === "Identifier") {
46
- if (seen.has(node.name)) return node.name;
47
- const alias = aliasOf(context, node);
48
- if (alias) return pathOf(context, alias, new Set([...seen, node.name])) ?? node.name;
49
- return node.name;
50
- }
51
- if (node.type === "ChainExpression") return pathOf(context, node.expression, seen);
52
- if (node.type === "MemberExpression" && !node.computed && node.property.type === "Identifier") {
53
- const object = pathOf(context, node.object, seen);
54
- return object === null ? null : `${object}.${node.property.name}`;
55
- }
56
- return null;
57
- }
58
-
59
- export const noGlobalPatch = {
60
- meta: {
61
- type: "problem",
62
- docs: {
63
- description: "Disallow replacing a member of a global object or a built-in prototype",
64
- },
65
- schema: [
66
- {
67
- type: "object",
68
- properties: {
69
- globals: { type: "string" },
70
- reason: { type: "string" },
71
- },
72
- required: ["globals"],
73
- additionalProperties: false,
74
- },
75
- ],
76
- messages: {
77
- patch:
78
- "`{{target}}` is a global another system's code runs; replacing it changes that code behind its back. Declare the intent to its owner instead.{{reason}}",
79
- },
80
- },
81
- create(context) {
82
- const options = context.options?.[0];
83
- if (!options) return {};
84
- const globals = new RegExp(options.globals);
85
- const reason = options.reason ? ` ${options.reason}` : "";
86
-
87
- const isGlobal = (path) => {
88
- const owner = path.split(".").at(-1);
89
- return owner === "prototype" || globals.test(owner);
90
- };
91
-
92
- const check = (node, target) => {
93
- if (target.type !== "MemberExpression") return;
94
- const owner = pathOf(context, target.object);
95
- if (owner === null || !isGlobal(owner)) return;
96
- const member = target.computed ? "[…]" : `.${target.property.name}`;
97
- context.report({ node, messageId: "patch", data: { reason, target: `${owner}${member}` } });
98
- };
99
-
100
- return {
101
- AssignmentExpression(node) {
102
- check(node, node.left);
103
- },
104
- CallExpression(node) {
105
- const callee = pathOf(context, node.callee);
106
- const [target] = node.arguments;
107
- if (!callee || !PATCHERS.has(callee) || !target) return;
108
- const owner = pathOf(context, target);
109
- if (owner !== null && isGlobal(owner)) {
110
- context.report({ node, messageId: "patch", data: { reason, target: owner } });
111
- }
112
- },
113
- };
114
- },
115
- };