@nadicodeai/ui 12.1.165 → 12.1.166

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 (363) 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 +11 -3
  69. package/dist/components/data-table.d.ts.map +1 -1
  70. package/dist/components/data-table.js +12 -4
  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.map +1 -1
  154. package/dist/components/record-list.js +4 -3
  155. package/dist/components/record-sheet.js +1 -1
  156. package/dist/components/record-time.d.ts.map +1 -1
  157. package/dist/components/record-time.js +2 -1
  158. package/dist/components/resizable.d.ts.map +1 -1
  159. package/dist/components/resizable.js +1 -1
  160. package/dist/components/row-edit-form.d.ts +2 -1
  161. package/dist/components/row-edit-form.d.ts.map +1 -1
  162. package/dist/components/row-edit-form.js +2 -1
  163. package/dist/components/run-timeline.js +1 -1
  164. package/dist/components/scope-switcher.js +1 -1
  165. package/dist/components/segmented-control.js +1 -1
  166. package/dist/components/select.js +1 -1
  167. package/dist/components/settings-facts.js +1 -1
  168. package/dist/components/settings-section.js +1 -1
  169. package/dist/components/sheet.d.ts +1 -1
  170. package/dist/components/sheet.d.ts.map +1 -1
  171. package/dist/components/sheet.js +1 -1
  172. package/dist/components/sidebar.d.ts +2 -2
  173. package/dist/components/sidebar.d.ts.map +1 -1
  174. package/dist/components/sidebar.js +16 -18
  175. package/dist/components/site-menu.d.ts +28 -0
  176. package/dist/components/site-menu.d.ts.map +1 -0
  177. package/dist/components/site-menu.js +23 -0
  178. package/dist/components/slider.d.ts.map +1 -1
  179. package/dist/components/slider.js +2 -1
  180. package/dist/components/snippet.d.ts +2 -0
  181. package/dist/components/snippet.d.ts.map +1 -1
  182. package/dist/components/snippet.js +13 -6
  183. package/dist/components/sonner.d.ts.map +1 -1
  184. package/dist/components/sonner.js +3 -4
  185. package/dist/components/status-badge.d.ts +1 -1
  186. package/dist/components/status-badge.d.ts.map +1 -1
  187. package/dist/components/switch.js +1 -1
  188. package/dist/components/table-card.js +1 -1
  189. package/dist/components/table.js +4 -4
  190. package/dist/components/tabs-nav.d.ts +52 -0
  191. package/dist/components/tabs-nav.d.ts.map +1 -0
  192. package/dist/components/tabs-nav.js +95 -0
  193. package/dist/components/tabs.d.ts +2 -56
  194. package/dist/components/tabs.d.ts.map +1 -1
  195. package/dist/components/tabs.js +2 -91
  196. package/dist/components/text-link.d.ts +1 -2
  197. package/dist/components/text-link.d.ts.map +1 -1
  198. package/dist/components/text-link.js +1 -2
  199. package/dist/components/textarea.d.ts +5 -2
  200. package/dist/components/textarea.d.ts.map +1 -1
  201. package/dist/components/textarea.js +12 -4
  202. package/dist/components/toast.d.ts +2 -0
  203. package/dist/components/toast.d.ts.map +1 -1
  204. package/dist/components/toast.js +4 -0
  205. package/dist/components/toggle-group.d.ts +3 -1
  206. package/dist/components/toggle-group.d.ts.map +1 -1
  207. package/dist/components/toggle-group.js +3 -6
  208. package/dist/components/toggle.js +1 -1
  209. package/dist/components/tooltip.d.ts +12 -12
  210. package/dist/components/tooltip.d.ts.map +1 -1
  211. package/dist/components/tooltip.js +9 -9
  212. package/dist/components/trend-badge.js +2 -2
  213. package/dist/components/update-card.js +1 -1
  214. package/dist/components/usage-meter.d.ts +1 -1
  215. package/dist/components/usage-meter.d.ts.map +1 -1
  216. package/dist/components/usage-meter.js +9 -7
  217. package/dist/components/waiting-line.js +1 -1
  218. package/dist/index.d.ts +3 -7
  219. package/dist/index.d.ts.map +1 -1
  220. package/dist/index.js +3 -7
  221. package/dist/internal/agent-orb-motion.d.ts +4 -1
  222. package/dist/internal/agent-orb-motion.d.ts.map +1 -1
  223. package/dist/internal/agent-orb-motion.js +9 -7
  224. package/dist/internal/agent-orb.d.ts +4 -1
  225. package/dist/internal/agent-orb.d.ts.map +1 -1
  226. package/dist/internal/agent-orb.js +7 -1
  227. package/dist/internal/assistant-ui/attachment.d.ts.map +1 -1
  228. package/dist/internal/assistant-ui/attachment.js +15 -15
  229. package/dist/internal/assistant-ui/follow-up-suggestions.js +1 -1
  230. package/dist/internal/assistant-ui/markdown-text.js +26 -25
  231. package/dist/internal/assistant-ui/reasoning.d.ts.map +1 -1
  232. package/dist/internal/assistant-ui/reasoning.js +13 -16
  233. package/dist/internal/assistant-ui/thread.d.ts.map +1 -1
  234. package/dist/internal/assistant-ui/thread.js +22 -16
  235. package/dist/internal/assistant-ui/tool-fallback.d.ts.map +1 -1
  236. package/dist/internal/assistant-ui/tool-fallback.js +29 -21
  237. package/dist/internal/assistant-ui/tool-group.d.ts.map +1 -1
  238. package/dist/internal/assistant-ui/tool-group.js +6 -7
  239. package/dist/internal/assistant-ui/tooltip-icon-button.js +1 -1
  240. package/dist/internal/badge-frame.d.ts +15 -0
  241. package/dist/internal/badge-frame.d.ts.map +1 -0
  242. package/dist/internal/badge-frame.js +44 -0
  243. package/dist/internal/button-classes.d.ts +20 -0
  244. package/dist/internal/button-classes.d.ts.map +1 -0
  245. package/dist/internal/button-classes.js +74 -0
  246. package/dist/internal/catalog-list.d.ts.map +1 -1
  247. package/dist/internal/catalog-list.js +8 -4
  248. package/dist/internal/collection-rail.js +3 -3
  249. package/dist/internal/form-drawer-frame.d.ts +10 -0
  250. package/dist/internal/form-drawer-frame.d.ts.map +1 -0
  251. package/dist/internal/form-drawer-frame.js +9 -0
  252. package/dist/internal/form-submit.d.ts +2 -1
  253. package/dist/internal/form-submit.d.ts.map +1 -1
  254. package/dist/internal/settings-save.d.ts.map +1 -1
  255. package/dist/internal/settings-save.js +4 -2
  256. package/dist/internal/status-mark.d.ts.map +1 -1
  257. package/dist/internal/status-mark.js +4 -1
  258. package/dist/internal/tab-row.d.ts +10 -0
  259. package/dist/internal/tab-row.d.ts.map +1 -0
  260. package/dist/internal/tab-row.js +2 -0
  261. package/dist/internal/table-compact-line.d.ts +1 -1
  262. package/dist/internal/table-compact-line.d.ts.map +1 -1
  263. package/dist/internal/table-compact-line.js +1 -1
  264. package/dist/internal/tooltip-content-frame.d.ts +14 -0
  265. package/dist/internal/tooltip-content-frame.d.ts.map +1 -0
  266. package/dist/internal/tooltip-content-frame.js +11 -0
  267. package/dist/lib/css-variables.d.ts +8 -0
  268. package/dist/lib/css-variables.d.ts.map +1 -0
  269. package/dist/lib/css-variables.js +4 -0
  270. package/dist/lib/merge-tokens.generated.js +1 -1
  271. package/dist/lib/use-copy-to-clipboard.d.ts.map +1 -1
  272. package/dist/lib/use-copy-to-clipboard.js +1 -2
  273. package/dist/showcase/samples.js +1 -1
  274. package/dist/showcase/specimens/choices.d.ts.map +1 -1
  275. package/dist/showcase/specimens/choices.js +3 -2
  276. package/dist/showcase/specimens/compositions.d.ts.map +1 -1
  277. package/dist/showcase/specimens/compositions.js +7 -5
  278. package/dist/showcase/specimens/data.d.ts.map +1 -1
  279. package/dist/showcase/specimens/data.js +1 -1
  280. package/dist/showcase/specimens/feedback.d.ts.map +1 -1
  281. package/dist/showcase/specimens/feedback.js +1 -2
  282. package/dist/showcase/specimens/index.d.ts +2 -0
  283. package/dist/showcase/specimens/index.d.ts.map +1 -1
  284. package/dist/showcase/specimens/inputs.d.ts +1 -0
  285. package/dist/showcase/specimens/inputs.d.ts.map +1 -1
  286. package/dist/showcase/specimens/inputs.js +5 -2
  287. package/dist/showcase/specimens/menus.d.ts +1 -0
  288. package/dist/showcase/specimens/menus.d.ts.map +1 -1
  289. package/dist/showcase/specimens/menus.js +7 -2
  290. package/dist/showcase/specimens/navigation.d.ts.map +1 -1
  291. package/dist/showcase/specimens/navigation.js +6 -5
  292. package/dist/showcase/specimens/status.d.ts.map +1 -1
  293. package/dist/showcase/specimens/status.js +4 -4
  294. package/dist/showcase/usage.generated.d.ts +1 -1
  295. package/dist/showcase/usage.generated.d.ts.map +1 -1
  296. package/dist/showcase/usage.generated.js +38 -16
  297. package/dist/standalone/index.js +1 -1
  298. package/dist/standalone/orb-page.js +10 -8
  299. package/dist/styles/components.css +1 -1
  300. package/package.json +32 -33
  301. package/dist/eslint/index.js +0 -224
  302. package/dist/eslint/rules/badge-is-static-label.js +0 -93
  303. package/dist/eslint/rules/button-icon-slot.js +0 -102
  304. package/dist/eslint/rules/button-link-for-navigation.js +0 -146
  305. package/dist/eslint/rules/button-no-aria-label-with-text.js +0 -75
  306. package/dist/eslint/rules/button-type-roles-only-in-buttons.js +0 -83
  307. package/dist/eslint/rules/choice-control-has-a-name.js +0 -98
  308. package/dist/eslint/rules/choice-group-in-fieldset.js +0 -86
  309. package/dist/eslint/rules/command-shortcut-single-owner.js +0 -118
  310. package/dist/eslint/rules/confirm-dialog-words.js +0 -63
  311. package/dist/eslint/rules/data-table-one-unsized-column.js +0 -96
  312. package/dist/eslint/rules/destructive-action-placement.js +0 -69
  313. package/dist/eslint/rules/disabled-choice-says-why.js +0 -71
  314. package/dist/eslint/rules/disabled-control-appearance.js +0 -75
  315. package/dist/eslint/rules/ellipsis-opens-a-dialog.js +0 -110
  316. package/dist/eslint/rules/empty-state-owner.js +0 -145
  317. package/dist/eslint/rules/input-group-owners.js +0 -155
  318. package/dist/eslint/rules/jsx-class-utility.js +0 -200
  319. package/dist/eslint/rules/kbd-children-no-modifier-text.js +0 -128
  320. package/dist/eslint/rules/literal-text.js +0 -41
  321. package/dist/eslint/rules/menu-owner.js +0 -75
  322. package/dist/eslint/rules/middle-truncate-placement.js +0 -69
  323. package/dist/eslint/rules/no-app-feature-component.js +0 -100
  324. package/dist/eslint/rules/no-bare-button-label.js +0 -55
  325. package/dist/eslint/rules/no-choice-control-wrapper.js +0 -97
  326. package/dist/eslint/rules/no-comment.js +0 -77
  327. package/dist/eslint/rules/no-control-in-read-only-surface.js +0 -106
  328. package/dist/eslint/rules/no-decorative-icon.js +0 -164
  329. package/dist/eslint/rules/no-deprecated-zod-api.js +0 -215
  330. package/dist/eslint/rules/no-global-patch.js +0 -115
  331. package/dist/eslint/rules/no-hand-built-busy.js +0 -104
  332. package/dist/eslint/rules/no-hand-built-theme-picker.js +0 -144
  333. package/dist/eslint/rules/no-hand-built-tile.js +0 -41
  334. package/dist/eslint/rules/no-hand-formatted-date.js +0 -87
  335. package/dist/eslint/rules/no-hand-stacked-avatars.js +0 -67
  336. package/dist/eslint/rules/no-nested-collapse.js +0 -60
  337. package/dist/eslint/rules/no-package-component-redefinition.js +0 -175
  338. package/dist/eslint/rules/no-search-in-form.js +0 -47
  339. package/dist/eslint/rules/no-shadcn-appearance-override.js +0 -305
  340. package/dist/eslint/rules/no-shell-prompt-in-snippet.js +0 -74
  341. package/dist/eslint/rules/no-stock-error-words.js +0 -56
  342. package/dist/eslint/rules/no-subject-derived-expectation.js +0 -183
  343. package/dist/eslint/rules/no-tooltip-around-labelled-field.js +0 -72
  344. package/dist/eslint/rules/no-weight-class-on-strong-in-type-role.js +0 -57
  345. package/dist/eslint/rules/no-write-in-subscription.js +0 -140
  346. package/dist/eslint/rules/one-submenu-level.js +0 -43
  347. package/dist/eslint/rules/one-toast-per-flow.js +0 -91
  348. package/dist/eslint/rules/option-count.js +0 -167
  349. package/dist/eslint/rules/page-command-link-not-render.js +0 -43
  350. package/dist/eslint/rules/page-composition.js +0 -232
  351. package/dist/eslint/rules/progress-needs-name.js +0 -57
  352. package/dist/eslint/rules/rendered-import.js +0 -121
  353. package/dist/eslint/rules/server-action-discipline.js +0 -233
  354. package/dist/eslint/rules/settings-limit-in-footer.js +0 -94
  355. package/dist/eslint/rules/skeleton-in-region.js +0 -80
  356. package/dist/eslint/rules/sortable-heading-uses-sort.js +0 -79
  357. package/dist/eslint/rules/table-cell-inset-owner.js +0 -107
  358. package/dist/eslint/rules/tabs-selection-is-controlled.js +0 -47
  359. package/dist/eslint/rules/test-files-from-one-definition.js +0 -67
  360. package/dist/eslint/rules/tooltip-only-arrow.js +0 -38
  361. package/dist/eslint/rules/tooltip-trigger-accessible-name.js +0 -114
  362. package/dist/eslint/rules/workspace-declares-imports.js +0 -163
  363. package/dist/eslint/strict-design-system.js +0 -250
@@ -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
- };
@@ -1,104 +0,0 @@
1
- /*
2
- * Standard tool checked first: `no-restricted-imports` refuses an import by
3
- * module, but not the same export by module and file area (PendingLabel is
4
- * allowed inside packages/ui), and `no-restricted-syntax` cannot join a
5
- * PendingLabel element to the Button it sits under through a renamed import.
6
- */
7
- import { openingElementClassUtilities } from "./jsx-class-utility.js";
8
- import { PACKAGE_BARREL, renderedImports } from "./rendered-import.js";
9
-
10
- const PENDING_LABEL = "PendingLabel";
11
- const PENDING_LABEL_MODULES = new Set([
12
- PACKAGE_BARREL,
13
- `${PACKAGE_BARREL}/components/pending-label`,
14
- ]);
15
- const BUTTONS = new Set(["Button", "ButtonLink"]);
16
- const SPINNER_ICONS = new Set([
17
- "Loader",
18
- "LoaderIcon",
19
- "Loader2",
20
- "Loader2Icon",
21
- "LoaderCircle",
22
- "LoaderCircleIcon",
23
- "LoaderPinwheel",
24
- ]);
25
- const ICON_MODULE = "lucide-react";
26
- const SPIN = "animate-spin";
27
- const FUNCTIONS = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
28
-
29
- const PACKAGE_PATH = "/packages/ui/";
30
- const PORTAL_PATH = "/apps/portal/";
31
-
32
- const PENDING_LABEL_ONLY = new Set([PENDING_LABEL]);
33
-
34
- const SOURCE_SIDE = { ImportSpecifier: "imported", ExportSpecifier: "local" };
35
-
36
- const sourceName = (specifier) => {
37
- const named = specifier[SOURCE_SIDE[specifier.type]];
38
- return named?.name ?? named?.value;
39
- };
40
-
41
- const isSpinToken = (utility) => utility.split(":").pop().replace(/^!/, "") === SPIN;
42
-
43
- function insideAButton(element, importOf) {
44
- for (let current = element.parent; current; current = current.parent) {
45
- if (FUNCTIONS.has(current.type)) return false;
46
- if (current.type === "JSXElement" && BUTTONS.has(importOf(current.openingElement.name)?.name)) {
47
- return true;
48
- }
49
- }
50
- return false;
51
- }
52
-
53
- export const noHandBuiltBusy = {
54
- meta: {
55
- type: "problem",
56
- docs: {
57
- description:
58
- "A working button takes loading and loadingLabel; no product hand-builds a busy label or a spinner.",
59
- },
60
- schema: [],
61
- messages: {
62
- "hand-built-busy":
63
- "A working button takes loading and loadingLabel: it keeps its place and focus, says its loadingLabel and shows no spinner. A wait past a second is WaitingLine.",
64
- },
65
- },
66
- create(context) {
67
- const filename = context.filename.replaceAll("\\", "/");
68
- const inPackage = filename.includes(PACKAGE_PATH);
69
- const inPortal = filename.includes(PORTAL_PATH);
70
- const importOf = renderedImports(context);
71
-
72
- const report = (node) => context.report({ node, messageId: "hand-built-busy" });
73
-
74
- function bannedFrom(source) {
75
- if (source === ICON_MODULE) return SPINNER_ICONS;
76
- if (!inPackage && PENDING_LABEL_MODULES.has(source)) return PENDING_LABEL_ONLY;
77
- return null;
78
- }
79
-
80
- function checkImport(node) {
81
- if (node.importKind === "type" || node.exportKind === "type") return;
82
- const source = node.source?.value;
83
- const bannedNames = bannedFrom(source);
84
- if (!bannedNames) return;
85
- for (const specifier of node.specifiers) {
86
- if (specifier.importKind === "type" || specifier.exportKind === "type") continue;
87
- if (bannedNames.has(sourceName(specifier))) report(specifier);
88
- }
89
- }
90
-
91
- return {
92
- ImportDeclaration: checkImport,
93
- ExportNamedDeclaration: checkImport,
94
- JSXElement(node) {
95
- if (importOf(node.openingElement.name)?.name !== PENDING_LABEL) return;
96
- if (insideAButton(node, importOf)) report(node.openingElement);
97
- },
98
- JSXOpeningElement(node) {
99
- if (inPortal) return;
100
- if (openingElementClassUtilities(node, context).some(isSpinToken)) report(node);
101
- },
102
- };
103
- },
104
- };