@nordmanai/nif 0.2.2 → 0.2.4

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 (358) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +6 -0
  3. package/dist/index.js +31353 -11545
  4. package/dist/styles.css +1 -1
  5. package/dist/ui/components/nm-ai/nm-ai.d.ts +4 -0
  6. package/dist/ui/components/nm-alert/nm-alert.d.ts +13 -0
  7. package/dist/ui/components/nm-button/nm-button.d.ts +4 -2
  8. package/dist/ui/components/nm-checkbox/nm-checkbox.d.ts +1 -1
  9. package/dist/ui/components/nm-chip/nm-chip.d.ts +5 -2
  10. package/dist/ui/components/nm-collapsible/nm-collapsible.d.ts +6 -0
  11. package/dist/ui/components/nm-combobox/nm-combobox.d.ts +1 -1
  12. package/dist/ui/components/nm-command/nm-command.d.ts +8 -1
  13. package/dist/ui/components/nm-composer/nm-composer.d.ts +47 -4
  14. package/dist/ui/components/nm-context-menu/nm-context-menu.d.ts +1 -1
  15. package/dist/ui/components/nm-dialog/nm-dialog.d.ts +1 -1
  16. package/dist/ui/components/nm-dropdown/nm-dropdown.d.ts +1 -1
  17. package/dist/ui/components/nm-dropdown-menu/nm-dropdown-menu.d.ts +11 -2
  18. package/dist/ui/components/nm-field/nm-field.d.ts +2 -0
  19. package/dist/ui/components/nm-hover-card/nm-hover-card.d.ts +1 -1
  20. package/dist/ui/components/nm-icon/animated/activity.d.ts +72 -0
  21. package/dist/ui/components/nm-icon/animated/archive.d.ts +31 -0
  22. package/dist/ui/components/nm-icon/animated/arrow-down.d.ts +128 -0
  23. package/dist/ui/components/nm-icon/animated/arrow-left.d.ts +128 -0
  24. package/dist/ui/components/nm-icon/animated/arrow-right.d.ts +128 -0
  25. package/dist/ui/components/nm-icon/animated/arrow-up-down.d.ts +119 -0
  26. package/dist/ui/components/nm-icon/animated/arrow-up.d.ts +128 -0
  27. package/dist/ui/components/nm-icon/animated/audio-lines.d.ts +99 -0
  28. package/dist/ui/components/nm-icon/animated/bookmark-plus.d.ts +35 -0
  29. package/dist/ui/components/nm-icon/animated/bookmark.d.ts +52 -0
  30. package/dist/ui/components/nm-icon/animated/bot.d.ts +90 -0
  31. package/dist/ui/components/nm-icon/animated/calendar-days.d.ts +87 -0
  32. package/dist/ui/components/nm-icon/animated/calendar.d.ts +36 -0
  33. package/dist/ui/components/nm-icon/animated/camera.d.ts +50 -0
  34. package/dist/ui/components/nm-icon/animated/chart-column-increasing.d.ts +37 -0
  35. package/dist/ui/components/nm-icon/animated/chart-column.d.ts +86 -0
  36. package/dist/ui/components/nm-icon/animated/chart-line.d.ts +51 -0
  37. package/dist/ui/components/nm-icon/animated/check-check.d.ts +50 -0
  38. package/dist/ui/components/nm-icon/animated/check.d.ts +25 -0
  39. package/dist/ui/components/nm-icon/animated/chevron-down.d.ts +39 -0
  40. package/dist/ui/components/nm-icon/animated/chevron-left.d.ts +39 -0
  41. package/dist/ui/components/nm-icon/animated/chevron-right.d.ts +39 -0
  42. package/dist/ui/components/nm-icon/animated/chevron-up.d.ts +39 -0
  43. package/dist/ui/components/nm-icon/animated/circle-alert.d.ts +23 -0
  44. package/dist/ui/components/nm-icon/animated/circle-check-big.d.ts +26 -0
  45. package/dist/ui/components/nm-icon/animated/circle-check.d.ts +26 -0
  46. package/dist/ui/components/nm-icon/animated/circle-plus.d.ts +44 -0
  47. package/dist/ui/components/nm-icon/animated/circle-question-mark.d.ts +22 -0
  48. package/dist/ui/components/nm-icon/animated/circle-x.d.ts +44 -0
  49. package/dist/ui/components/nm-icon/animated/clock-3.d.ts +44 -0
  50. package/dist/ui/components/nm-icon/animated/clock-4.d.ts +44 -0
  51. package/dist/ui/components/nm-icon/animated/clock.d.ts +44 -0
  52. package/dist/ui/components/nm-icon/animated/cloud-sun.d.ts +9 -0
  53. package/dist/ui/components/nm-icon/animated/cloud-upload.d.ts +45 -0
  54. package/dist/ui/components/nm-icon/animated/copy.d.ts +135 -0
  55. package/dist/ui/components/nm-icon/animated/download.d.ts +45 -0
  56. package/dist/ui/components/nm-icon/animated/ellipsis.d.ts +141 -0
  57. package/dist/ui/components/nm-icon/animated/external-link.d.ts +49 -0
  58. package/dist/ui/components/nm-icon/animated/eye-off.d.ts +23 -0
  59. package/dist/ui/components/nm-icon/animated/eye.d.ts +39 -0
  60. package/dist/ui/components/nm-icon/animated/fast-forward.d.ts +34 -0
  61. package/dist/ui/components/nm-icon/animated/file-clock.d.ts +48 -0
  62. package/dist/ui/components/nm-icon/animated/file-text.d.ts +56 -0
  63. package/dist/ui/components/nm-icon/animated/file.d.ts +67 -0
  64. package/dist/ui/components/nm-icon/animated/folder.d.ts +92 -0
  65. package/dist/ui/components/nm-icon/animated/gauge.d.ts +47 -0
  66. package/dist/ui/components/nm-icon/animated/globe.d.ts +21 -0
  67. package/dist/ui/components/nm-icon/animated/graduation-cap.d.ts +41 -0
  68. package/dist/ui/components/nm-icon/animated/headphones.d.ts +50 -0
  69. package/dist/ui/components/nm-icon/animated/image.d.ts +40 -0
  70. package/dist/ui/components/nm-icon/animated/index.d.ts +2 -0
  71. package/dist/ui/components/nm-icon/animated/info.d.ts +37 -0
  72. package/dist/ui/components/nm-icon/animated/key-round.d.ts +37 -0
  73. package/dist/ui/components/nm-icon/animated/layers.d.ts +61 -0
  74. package/dist/ui/components/nm-icon/animated/layout-dashboard.d.ts +131 -0
  75. package/dist/ui/components/nm-icon/animated/library-big.d.ts +29 -0
  76. package/dist/ui/components/nm-icon/animated/lightbulb.d.ts +51 -0
  77. package/dist/ui/components/nm-icon/animated/link.d.ts +193 -0
  78. package/dist/ui/components/nm-icon/animated/list-filter.d.ts +13 -0
  79. package/dist/ui/components/nm-icon/animated/list.d.ts +111 -0
  80. package/dist/ui/components/nm-icon/animated/loader-circle.d.ts +24 -0
  81. package/dist/ui/components/nm-icon/animated/lock.d.ts +94 -0
  82. package/dist/ui/components/nm-icon/animated/log-out.d.ts +45 -0
  83. package/dist/ui/components/nm-icon/animated/mail.d.ts +100 -0
  84. package/dist/ui/components/nm-icon/animated/map-pin.d.ts +67 -0
  85. package/dist/ui/components/nm-icon/animated/menu.d.ts +57 -0
  86. package/dist/ui/components/nm-icon/animated/message-circle-dashed.d.ts +34 -0
  87. package/dist/ui/components/nm-icon/animated/message-circle.d.ts +23 -0
  88. package/dist/ui/components/nm-icon/animated/message-square-plus.d.ts +49 -0
  89. package/dist/ui/components/nm-icon/animated/message-square-text.d.ts +104 -0
  90. package/dist/ui/components/nm-icon/animated/message-square.d.ts +23 -0
  91. package/dist/ui/components/nm-icon/animated/mic-off.d.ts +23 -0
  92. package/dist/ui/components/nm-icon/animated/mic.d.ts +37 -0
  93. package/dist/ui/components/nm-icon/animated/minimize.d.ts +139 -0
  94. package/dist/ui/components/nm-icon/animated/minus.d.ts +54 -0
  95. package/dist/ui/components/nm-icon/animated/moon.d.ts +62 -0
  96. package/dist/ui/components/nm-icon/animated/music.d.ts +22 -0
  97. package/dist/ui/components/nm-icon/animated/notebook-pen.d.ts +41 -0
  98. package/dist/ui/components/nm-icon/animated/panel-left.d.ts +29 -0
  99. package/dist/ui/components/nm-icon/animated/panel-right.d.ts +29 -0
  100. package/dist/ui/components/nm-icon/animated/paperclip.d.ts +49 -0
  101. package/dist/ui/components/nm-icon/animated/pause.d.ts +59 -0
  102. package/dist/ui/components/nm-icon/animated/pencil.d.ts +25 -0
  103. package/dist/ui/components/nm-icon/animated/pin-off.d.ts +44 -0
  104. package/dist/ui/components/nm-icon/animated/pin.d.ts +85 -0
  105. package/dist/ui/components/nm-icon/animated/plane-takeoff.d.ts +25 -0
  106. package/dist/ui/components/nm-icon/animated/play.d.ts +43 -0
  107. package/dist/ui/components/nm-icon/animated/plug-zap.d.ts +49 -0
  108. package/dist/ui/components/nm-icon/animated/plus.d.ts +95 -0
  109. package/dist/ui/components/nm-icon/animated/radio.d.ts +24 -0
  110. package/dist/ui/components/nm-icon/animated/refresh-cw.d.ts +55 -0
  111. package/dist/ui/components/nm-icon/animated/rocket.d.ts +48 -0
  112. package/dist/ui/components/nm-icon/animated/rotate-ccw.d.ts +51 -0
  113. package/dist/ui/components/nm-icon/animated/rotate-cw.d.ts +71 -0
  114. package/dist/ui/components/nm-icon/animated/save.d.ts +21 -0
  115. package/dist/ui/components/nm-icon/animated/search.d.ts +42 -0
  116. package/dist/ui/components/nm-icon/animated/send.d.ts +39 -0
  117. package/dist/ui/components/nm-icon/animated/settings.d.ts +39 -0
  118. package/dist/ui/components/nm-icon/animated/share-2.d.ts +122 -0
  119. package/dist/ui/components/nm-icon/animated/share.d.ts +40 -0
  120. package/dist/ui/components/nm-icon/animated/shield-check.d.ts +36 -0
  121. package/dist/ui/components/nm-icon/animated/shopping-bag.d.ts +35 -0
  122. package/dist/ui/components/nm-icon/animated/sliders-horizontal.d.ts +239 -0
  123. package/dist/ui/components/nm-icon/animated/sparkles.d.ts +205 -0
  124. package/dist/ui/components/nm-icon/animated/star.d.ts +48 -0
  125. package/dist/ui/components/nm-icon/animated/sun.d.ts +9 -0
  126. package/dist/ui/components/nm-icon/animated/terminal.d.ts +22 -0
  127. package/dist/ui/components/nm-icon/animated/trash-2.d.ts +61 -0
  128. package/dist/ui/components/nm-icon/animated/trash.d.ts +37 -0
  129. package/dist/ui/components/nm-icon/animated/trending-up.d.ts +40 -0
  130. package/dist/ui/components/nm-icon/animated/triangle-alert.d.ts +37 -0
  131. package/dist/ui/components/nm-icon/animated/trophy.d.ts +23 -0
  132. package/dist/ui/components/nm-icon/animated/type.d.ts +57 -0
  133. package/dist/ui/components/nm-icon/animated/upload.d.ts +49 -0
  134. package/dist/ui/components/nm-icon/animated/user-round.d.ts +33 -0
  135. package/dist/ui/components/nm-icon/animated/user.d.ts +33 -0
  136. package/dist/ui/components/nm-icon/animated/users-round.d.ts +93 -0
  137. package/dist/ui/components/nm-icon/animated/users.d.ts +93 -0
  138. package/dist/ui/components/nm-icon/animated/volume-2.d.ts +10 -0
  139. package/dist/ui/components/nm-icon/animated/wand-sparkles.d.ts +71 -0
  140. package/dist/ui/components/nm-icon/animated/x.d.ts +95 -0
  141. package/dist/ui/components/nm-icon/animated/zap.d.ts +65 -0
  142. package/dist/ui/components/nm-icon/animated/zoom-in.d.ts +35 -0
  143. package/dist/ui/components/nm-icon/animated/zoom-out.d.ts +53 -0
  144. package/dist/ui/components/nm-icon/nm-icon.d.ts +6 -3
  145. package/dist/ui/components/nm-icon/nm-lucide-extended.d.ts +3 -0
  146. package/dist/ui/components/nm-icon/nm-lucide.d.ts +7 -3
  147. package/dist/ui/components/nm-menubar/nm-menubar.d.ts +2 -2
  148. package/dist/ui/components/nm-panel/nm-panel.d.ts +5 -1
  149. package/dist/ui/components/nm-popover/nm-popover.d.ts +2 -2
  150. package/dist/ui/components/nm-progress/nm-progress.d.ts +1 -1
  151. package/dist/ui/components/nm-radio-group/nm-radio-group.d.ts +2 -2
  152. package/dist/ui/components/nm-select/nm-select.d.ts +1 -1
  153. package/dist/ui/components/nm-skeleton/nm-skeleton.d.ts +3 -0
  154. package/dist/ui/components/nm-slider/nm-slider.d.ts +1 -1
  155. package/dist/ui/components/nm-small-icon-button/nm-small-icon-button.d.ts +3 -3
  156. package/dist/ui/components/nm-spinner/nm-spinner.d.ts +3 -0
  157. package/dist/ui/components/nm-switch/nm-switch.d.ts +1 -1
  158. package/dist/ui/components/nm-tabs/nm-tabs.d.ts +6 -0
  159. package/dist/ui/components/nm-textarea/nm-textarea.d.ts +12 -2
  160. package/dist/ui/components/nm-toggle/nm-toggle.d.ts +1 -1
  161. package/dist/ui/components/nm-tooltip/nm-tooltip.d.ts +1 -1
  162. package/dist/ui/components/nm-voice-orb/nm-voice-orb.d.ts +18 -0
  163. package/dist/ui/components/nm-voice-orb/use-nm-voice-orb-theme.d.ts +2 -0
  164. package/dist/ui/config/nm-app-panel.d.ts +2 -0
  165. package/dist/ui/config/nm-button.d.ts +6 -0
  166. package/dist/ui/config/nm-composer.d.ts +11 -0
  167. package/dist/ui/config/nm-icons-extended.d.ts +1 -0
  168. package/dist/ui/config/nm-icons.d.ts +4 -1
  169. package/dist/ui/config/nm-voice-orb.d.ts +22 -0
  170. package/dist/ui/lib/nm-motion.d.ts +29 -0
  171. package/package.json +12 -8
  172. package/registry/index.json +5277 -73
  173. package/registry/ui/components/nm-ai/nm-ai.tsx +7 -4
  174. package/registry/ui/components/nm-alert/nm-alert.css +85 -0
  175. package/registry/ui/components/nm-alert/nm-alert.tsx +35 -0
  176. package/registry/ui/components/nm-button/nm-button.css +24 -0
  177. package/registry/ui/components/nm-button/nm-button.tsx +25 -11
  178. package/registry/ui/components/nm-checkbox/nm-checkbox.tsx +1 -1
  179. package/registry/ui/components/nm-chip/nm-chip.css +25 -0
  180. package/registry/ui/components/nm-chip/nm-chip.tsx +9 -3
  181. package/registry/ui/components/nm-collapsible/nm-collapsible.css +3 -0
  182. package/registry/ui/components/nm-collapsible/nm-collapsible.tsx +16 -0
  183. package/registry/ui/components/nm-combobox/nm-combobox.tsx +1 -1
  184. package/registry/ui/components/nm-command/nm-command.css +48 -0
  185. package/registry/ui/components/nm-command/nm-command.tsx +19 -5
  186. package/registry/ui/components/nm-composer/nm-composer.css +87 -3
  187. package/registry/ui/components/nm-composer/nm-composer.tsx +321 -33
  188. package/registry/ui/components/nm-context-menu/nm-context-menu.tsx +1 -1
  189. package/registry/ui/components/nm-dialog/nm-dialog.css +5 -6
  190. package/registry/ui/components/nm-dialog/nm-dialog.tsx +1 -1
  191. package/registry/ui/components/nm-dropdown/nm-dropdown.css +5 -0
  192. package/registry/ui/components/nm-dropdown/nm-dropdown.tsx +28 -249
  193. package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.css +8 -0
  194. package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.tsx +85 -6
  195. package/registry/ui/components/nm-field/nm-field.tsx +6 -1
  196. package/registry/ui/components/nm-hover-card/nm-hover-card.tsx +1 -1
  197. package/registry/ui/components/nm-icon/animated/activity.tsx +109 -0
  198. package/registry/ui/components/nm-icon/animated/archive.tsx +85 -0
  199. package/registry/ui/components/nm-icon/animated/arrow-down.tsx +149 -0
  200. package/registry/ui/components/nm-icon/animated/arrow-left.tsx +149 -0
  201. package/registry/ui/components/nm-icon/animated/arrow-right.tsx +149 -0
  202. package/registry/ui/components/nm-icon/animated/arrow-up-down.tsx +168 -0
  203. package/registry/ui/components/nm-icon/animated/arrow-up.tsx +149 -0
  204. package/registry/ui/components/nm-icon/animated/audio-lines.tsx +190 -0
  205. package/registry/ui/components/nm-icon/animated/bookmark-plus.tsx +65 -0
  206. package/registry/ui/components/nm-icon/animated/bookmark.tsx +77 -0
  207. package/registry/ui/components/nm-icon/animated/bot.tsx +167 -0
  208. package/registry/ui/components/nm-icon/animated/calendar-days.tsx +128 -0
  209. package/registry/ui/components/nm-icon/animated/calendar.tsx +83 -0
  210. package/registry/ui/components/nm-icon/animated/camera.tsx +85 -0
  211. package/registry/ui/components/nm-icon/animated/chart-column-increasing.tsx +150 -0
  212. package/registry/ui/components/nm-icon/animated/chart-column.tsx +179 -0
  213. package/registry/ui/components/nm-icon/animated/chart-line.tsx +88 -0
  214. package/registry/ui/components/nm-icon/animated/check-check.tsx +105 -0
  215. package/registry/ui/components/nm-icon/animated/check.tsx +70 -0
  216. package/registry/ui/components/nm-icon/animated/chevron-down.tsx +73 -0
  217. package/registry/ui/components/nm-icon/animated/chevron-left.tsx +73 -0
  218. package/registry/ui/components/nm-icon/animated/chevron-right.tsx +73 -0
  219. package/registry/ui/components/nm-icon/animated/chevron-up.tsx +73 -0
  220. package/registry/ui/components/nm-icon/animated/circle-alert.tsx +84 -0
  221. package/registry/ui/components/nm-icon/animated/circle-check-big.tsx +75 -0
  222. package/registry/ui/components/nm-icon/animated/circle-check.tsx +77 -0
  223. package/registry/ui/components/nm-icon/animated/circle-plus.tsx +93 -0
  224. package/registry/ui/components/nm-icon/animated/circle-question-mark.tsx +62 -0
  225. package/registry/ui/components/nm-icon/animated/circle-x.tsx +93 -0
  226. package/registry/ui/components/nm-icon/animated/clock-3.tsx +95 -0
  227. package/registry/ui/components/nm-icon/animated/clock-4.tsx +95 -0
  228. package/registry/ui/components/nm-icon/animated/clock.tsx +95 -0
  229. package/registry/ui/components/nm-icon/animated/cloud-sun.tsx +130 -0
  230. package/registry/ui/components/nm-icon/animated/cloud-upload.tsx +93 -0
  231. package/registry/ui/components/nm-icon/animated/copy.tsx +153 -0
  232. package/registry/ui/components/nm-icon/animated/download.tsx +93 -0
  233. package/registry/ui/components/nm-icon/animated/ellipsis.tsx +189 -0
  234. package/registry/ui/components/nm-icon/animated/external-link.tsx +97 -0
  235. package/registry/ui/components/nm-icon/animated/eye-off.tsx +63 -0
  236. package/registry/ui/components/nm-icon/animated/eye.tsx +82 -0
  237. package/registry/ui/components/nm-icon/animated/fast-forward.tsx +72 -0
  238. package/registry/ui/components/nm-icon/animated/file-clock.tsx +105 -0
  239. package/registry/ui/components/nm-icon/animated/file-text.tsx +102 -0
  240. package/registry/ui/components/nm-icon/animated/file.tsx +124 -0
  241. package/registry/ui/components/nm-icon/animated/folder.tsx +132 -0
  242. package/registry/ui/components/nm-icon/animated/gauge.tsx +84 -0
  243. package/registry/ui/components/nm-icon/animated/globe.tsx +61 -0
  244. package/registry/ui/components/nm-icon/animated/graduation-cap.tsx +92 -0
  245. package/registry/ui/components/nm-icon/animated/headphones.tsx +85 -0
  246. package/registry/ui/components/nm-icon/animated/image.tsx +88 -0
  247. package/registry/ui/components/nm-icon/animated/index.ts +251 -0
  248. package/registry/ui/components/nm-icon/animated/info.tsx +75 -0
  249. package/registry/ui/components/nm-icon/animated/key-round.tsx +67 -0
  250. package/registry/ui/components/nm-icon/animated/layers.tsx +116 -0
  251. package/registry/ui/components/nm-icon/animated/layout-dashboard.tsx +176 -0
  252. package/registry/ui/components/nm-icon/animated/library-big.tsx +89 -0
  253. package/registry/ui/components/nm-icon/animated/lightbulb.tsx +106 -0
  254. package/registry/ui/components/nm-icon/animated/link.tsx +210 -0
  255. package/registry/ui/components/nm-icon/animated/list-filter.tsx +78 -0
  256. package/registry/ui/components/nm-icon/animated/list.tsx +184 -0
  257. package/registry/ui/components/nm-icon/animated/loader-circle.tsx +68 -0
  258. package/registry/ui/components/nm-icon/animated/lock.tsx +152 -0
  259. package/registry/ui/components/nm-icon/animated/log-out.tsx +93 -0
  260. package/registry/ui/components/nm-icon/animated/mail.tsx +131 -0
  261. package/registry/ui/components/nm-icon/animated/map-pin.tsx +111 -0
  262. package/registry/ui/components/nm-icon/animated/menu.tsx +121 -0
  263. package/registry/ui/components/nm-icon/animated/message-circle-dashed.tsx +140 -0
  264. package/registry/ui/components/nm-icon/animated/message-circle.tsx +66 -0
  265. package/registry/ui/components/nm-icon/animated/message-square-plus.tsx +106 -0
  266. package/registry/ui/components/nm-icon/animated/message-square-text.tsx +153 -0
  267. package/registry/ui/components/nm-icon/animated/message-square.tsx +66 -0
  268. package/registry/ui/components/nm-icon/animated/mic-off.tsx +65 -0
  269. package/registry/ui/components/nm-icon/animated/mic.tsx +77 -0
  270. package/registry/ui/components/nm-icon/animated/minimize.tsx +164 -0
  271. package/registry/ui/components/nm-icon/animated/minus.tsx +84 -0
  272. package/registry/ui/components/nm-icon/animated/moon.tsx +98 -0
  273. package/registry/ui/components/nm-icon/animated/music.tsx +62 -0
  274. package/registry/ui/components/nm-icon/animated/notebook-pen.tsx +114 -0
  275. package/registry/ui/components/nm-icon/animated/panel-left.tsx +77 -0
  276. package/registry/ui/components/nm-icon/animated/panel-right.tsx +77 -0
  277. package/registry/ui/components/nm-icon/animated/paperclip.tsx +83 -0
  278. package/registry/ui/components/nm-icon/animated/pause.tsx +116 -0
  279. package/registry/ui/components/nm-icon/animated/pencil.tsx +70 -0
  280. package/registry/ui/components/nm-icon/animated/pin-off.tsx +102 -0
  281. package/registry/ui/components/nm-icon/animated/pin.tsx +124 -0
  282. package/registry/ui/components/nm-icon/animated/plane-takeoff.tsx +62 -0
  283. package/registry/ui/components/nm-icon/animated/play.tsx +74 -0
  284. package/registry/ui/components/nm-icon/animated/plug-zap.tsx +117 -0
  285. package/registry/ui/components/nm-icon/animated/plus.tsx +122 -0
  286. package/registry/ui/components/nm-icon/animated/radio.tsx +137 -0
  287. package/registry/ui/components/nm-icon/animated/refresh-cw.tsx +103 -0
  288. package/registry/ui/components/nm-icon/animated/rocket.tsx +93 -0
  289. package/registry/ui/components/nm-icon/animated/rotate-ccw.tsx +87 -0
  290. package/registry/ui/components/nm-icon/animated/rotate-cw.tsx +98 -0
  291. package/registry/ui/components/nm-icon/animated/save.tsx +58 -0
  292. package/registry/ui/components/nm-icon/animated/search.tsx +90 -0
  293. package/registry/ui/components/nm-icon/animated/send.tsx +87 -0
  294. package/registry/ui/components/nm-icon/animated/settings.tsx +92 -0
  295. package/registry/ui/components/nm-icon/animated/share-2.tsx +148 -0
  296. package/registry/ui/components/nm-icon/animated/share.tsx +76 -0
  297. package/registry/ui/components/nm-icon/animated/shield-check.tsx +70 -0
  298. package/registry/ui/components/nm-icon/animated/shopping-bag.tsx +71 -0
  299. package/registry/ui/components/nm-icon/animated/sliders-horizontal.tsx +243 -0
  300. package/registry/ui/components/nm-icon/animated/sparkles.tsx +227 -0
  301. package/registry/ui/components/nm-icon/animated/star.tsx +86 -0
  302. package/registry/ui/components/nm-icon/animated/sun.tsx +148 -0
  303. package/registry/ui/components/nm-icon/animated/terminal.tsx +71 -0
  304. package/registry/ui/components/nm-icon/animated/trash-2.tsx +136 -0
  305. package/registry/ui/components/nm-icon/animated/trash.tsx +94 -0
  306. package/registry/ui/components/nm-icon/animated/trending-up.tsx +75 -0
  307. package/registry/ui/components/nm-icon/animated/triangle-alert.tsx +75 -0
  308. package/registry/ui/components/nm-icon/animated/trophy.tsx +62 -0
  309. package/registry/ui/components/nm-icon/animated/type.tsx +106 -0
  310. package/registry/ui/components/nm-icon/animated/upload.tsx +94 -0
  311. package/registry/ui/components/nm-icon/animated/user-round.tsx +84 -0
  312. package/registry/ui/components/nm-icon/animated/user.tsx +84 -0
  313. package/registry/ui/components/nm-icon/animated/users-round.tsx +156 -0
  314. package/registry/ui/components/nm-icon/animated/users.tsx +156 -0
  315. package/registry/ui/components/nm-icon/animated/volume-2.tsx +119 -0
  316. package/registry/ui/components/nm-icon/animated/wand-sparkles.tsx +111 -0
  317. package/registry/ui/components/nm-icon/animated/x.tsx +122 -0
  318. package/registry/ui/components/nm-icon/animated/zap.tsx +86 -0
  319. package/registry/ui/components/nm-icon/animated/zoom-in.tsx +66 -0
  320. package/registry/ui/components/nm-icon/animated/zoom-out.tsx +85 -0
  321. package/registry/ui/components/nm-icon/nm-icon.css +0 -1
  322. package/registry/ui/components/nm-icon/nm-icon.tsx +20 -5
  323. package/registry/ui/components/nm-icon/nm-lucide-extended.tsx +284 -0
  324. package/registry/ui/components/nm-icon/nm-lucide.tsx +55 -5
  325. package/registry/ui/components/nm-input/nm-input.css +1 -0
  326. package/registry/ui/components/nm-menubar/nm-menubar.tsx +2 -2
  327. package/registry/ui/components/nm-panel/nm-panel.css +7 -0
  328. package/registry/ui/components/nm-panel/nm-panel.tsx +19 -2
  329. package/registry/ui/components/nm-popover/nm-popover.tsx +4 -3
  330. package/registry/ui/components/nm-progress/nm-progress.tsx +1 -1
  331. package/registry/ui/components/nm-radio-group/nm-radio-group.tsx +2 -2
  332. package/registry/ui/components/nm-select/nm-select.tsx +1 -1
  333. package/registry/ui/components/nm-skeleton/nm-skeleton.css +17 -0
  334. package/registry/ui/components/nm-skeleton/nm-skeleton.tsx +7 -0
  335. package/registry/ui/components/nm-slider/nm-slider.tsx +1 -1
  336. package/registry/ui/components/nm-small-icon-button/nm-small-icon-button.tsx +3 -3
  337. package/registry/ui/components/nm-spinner/nm-spinner.css +22 -0
  338. package/registry/ui/components/nm-spinner/nm-spinner.tsx +7 -0
  339. package/registry/ui/components/nm-switch/nm-switch.css +20 -3
  340. package/registry/ui/components/nm-switch/nm-switch.tsx +1 -1
  341. package/registry/ui/components/nm-tabs/nm-tabs.css +4 -0
  342. package/registry/ui/components/nm-tabs/nm-tabs.tsx +19 -0
  343. package/registry/ui/components/nm-textarea/nm-textarea.css +200 -0
  344. package/registry/ui/components/nm-textarea/nm-textarea.tsx +417 -3
  345. package/registry/ui/components/nm-toggle/nm-toggle.tsx +1 -1
  346. package/registry/ui/components/nm-toolbar/nm-toolbar.tsx +4 -1
  347. package/registry/ui/components/nm-tooltip/nm-tooltip.tsx +1 -1
  348. package/registry/ui/components/nm-voice-orb/nm-voice-orb.css +17 -0
  349. package/registry/ui/components/nm-voice-orb/nm-voice-orb.tsx +112 -0
  350. package/registry/ui/components/nm-voice-orb/use-nm-voice-orb-theme.ts +34 -0
  351. package/registry/ui/components/nordman-icon-button/nordman-icon-button.tsx +7 -3
  352. package/registry/ui/config/nm-button.ts +6 -0
  353. package/registry/ui/config/nm-composer.ts +12 -0
  354. package/registry/ui/config/nm-icons-extended.ts +141 -0
  355. package/registry/ui/config/nm-icons.ts +6 -2
  356. package/registry/ui/config/nm-voice-orb.ts +50 -0
  357. package/registry/ui/lib/nm-motion.ts +30 -0
  358. package/registry/ui/styles/tokens.css +7 -0
@@ -1,34 +1,22 @@
1
- import {
2
- useCallback,
3
- useEffect,
4
- useId,
5
- useLayoutEffect,
6
- useRef,
7
- useState,
8
- type MouseEvent as ReactMouseEvent,
9
- type ReactNode,
10
- type Ref,
11
- } from 'react';
12
- import { createPortal } from 'react-dom';
1
+ import { useCallback, useRef, useState, type ReactElement, type ReactNode, type Ref } from 'react';
13
2
  import type { NmIconId } from '../../config/nm-icons.ts';
14
3
  import {
15
4
  NM_DROPDOWN_ALIGN,
16
5
  NM_DROPDOWN_CLASSES,
17
6
  NM_DROPDOWN_REVEAL,
18
- NM_DROPDOWN_SCROLL_IDLE_MS,
19
7
  NM_DROPDOWN_TONE,
20
8
  NM_DROPDOWN_TRIGGER,
21
9
  } from '../../config/nm-dropdown.ts';
22
- import {
23
- dropdownPortalHost,
24
- placeNmDropdownPanel,
25
- placeNmDropdownRowPanel,
26
- } from './nm-dropdown-placement';
27
10
  import { NordmanIconButton } from '../nordman-icon-button/nordman-icon-button.tsx';
28
- import { openDropdownBranch, type NmDropdownItem } from './nm-dropdown-item';
29
- import { findDropdownItem, NmDropdownOptions } from './nm-dropdown-options';
11
+ import type { NmDropdownItem } from './nm-dropdown-item';
12
+ import { findDropdownItem } from './nm-dropdown-options';
13
+ import {
14
+ NmDropdownMenu,
15
+ NmDropdownMenuContent,
16
+ NmDropdownMenuItems,
17
+ NmDropdownMenuTrigger,
18
+ } from '../nm-dropdown-menu/nm-dropdown-menu.tsx';
30
19
  import { NM_ICON_BUTTON_TONES } from '../../config/nm-icon-button.ts';
31
- import { NmDropdownPanel } from './nm-dropdown-panel';
32
20
  import { createLogger } from '../../kit-logger.ts';
33
21
  import { NmIcon } from '../nm-icon/nm-icon.tsx';
34
22
 
@@ -92,14 +80,8 @@ function assignTriggerRef(ref: Ref<HTMLButtonElement> | undefined, node: HTMLBut
92
80
  }
93
81
 
94
82
  export function NmDropdown(props: NmDropdownProps): ReactNode {
95
- const panelId = useId();
96
- const rootRef = useRef<HTMLDivElement>(null);
97
- const panelRef = useRef<HTMLUListElement>(null);
98
83
  const triggerNodeRef = useRef<HTMLButtonElement | null>(null);
99
84
  const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
100
- const [expandedIds, setExpandedIds] = useState<readonly string[]>([]);
101
- const alignName = props.align === NM_DROPDOWN_ALIGN.end ? 'end' : 'start';
102
- const [motionPlacement, setMotionPlacement] = useState(`bottom-${alignName}`);
103
85
  const { open: openProp, onOpenChange } = props;
104
86
  const open = openProp ?? uncontrolledOpen;
105
87
  const setOpen = useCallback(
@@ -119,7 +101,6 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
119
101
  const iconOnlyTrigger = props.iconOnly === true;
120
102
  const iconTrigger = isIconTrigger(props.trigger);
121
103
  const iconButton = props.trigger === NM_DROPDOWN_TRIGGER.iconButton;
122
- const portal = props.portal ?? iconTrigger;
123
104
  const triggerClass = [
124
105
  NM_DROPDOWN_CLASSES.trigger,
125
106
  props.trigger === NM_DROPDOWN_TRIGGER.icon ? NM_DROPDOWN_CLASSES.triggerIcon : '',
@@ -132,201 +113,12 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
132
113
  .filter((value) => value !== '')
133
114
  .join(' ');
134
115
 
135
- useEffect(() => {
136
- const panel = panelRef.current;
137
- if (!open || panel == null) {
138
- return;
139
- }
140
- let idle = 0;
141
- const onScroll = (event: Event) => {
142
- const target = event.target;
143
- if (!(target instanceof HTMLElement)) {
144
- return;
145
- }
146
- const inSubmenu = target.closest(`.${NM_DROPDOWN_CLASSES.subpanel}`) != null;
147
- const inPanel = panel.contains(target);
148
- if (!inSubmenu && !inPanel) {
149
- return;
150
- }
151
- if (inPanel && !inSubmenu) {
152
- setExpandedIds((current) => (current.length === 0 ? current : []));
153
- }
154
- target.dataset.scrolling = 'true';
155
- window.clearTimeout(idle);
156
- idle = window.setTimeout(() => {
157
- delete target.dataset.scrolling;
158
- }, NM_DROPDOWN_SCROLL_IDLE_MS);
159
- };
160
- document.addEventListener('scroll', onScroll, true);
161
- return () => {
162
- document.removeEventListener('scroll', onScroll, true);
163
- window.clearTimeout(idle);
164
- delete panel.dataset.scrolling;
165
- };
166
- }, [open]);
167
-
168
- useEffect(() => {
169
- if (!open) {
170
- return;
171
- }
172
- function onPointer(event: MouseEvent): void {
173
- const target = event.target;
174
- if (!(target instanceof Node)) {
175
- return;
176
- }
177
- const inSubmenu =
178
- target instanceof Element && target.closest(`.${NM_DROPDOWN_CLASSES.subpanel}`) != null;
179
- if (rootRef.current?.contains(target) || panelRef.current?.contains(target) || inSubmenu) {
180
- return;
181
- }
182
- setOpen(false);
183
- setExpandedIds([]);
184
- }
185
- function onKey(event: KeyboardEvent): void {
186
- if (event.key === 'Escape') {
187
- setOpen(false);
188
- setExpandedIds([]);
189
- }
190
- }
191
- document.addEventListener('mousedown', onPointer);
192
- document.addEventListener('keydown', onKey);
193
- return () => {
194
- document.removeEventListener('mousedown', onPointer);
195
- document.removeEventListener('keydown', onKey);
196
- };
197
- }, [open, setOpen]);
198
-
199
- useLayoutEffect(() => {
200
- if (!open || !portal) {
201
- return;
202
- }
203
- function applyPlacement(): void {
204
- const trigger = triggerNodeRef.current;
205
- const panel = panelRef.current;
206
- if (trigger == null || panel == null) {
207
- return;
208
- }
209
- const rect = trigger.getBoundingClientRect();
210
- const viewport = { width: window.innerWidth, height: window.innerHeight };
211
- const rowEl = props.align === NM_DROPDOWN_ALIGN.row ? trigger.closest('.nm-rail__row') : null;
212
- if (rowEl instanceof HTMLElement) {
213
- const rowRect = rowEl.getBoundingClientRect();
214
- const placement = placeNmDropdownRowPanel({
215
- row: {
216
- top: rowRect.top,
217
- left: rowRect.left,
218
- right: rowRect.right,
219
- bottom: rowRect.bottom,
220
- width: rowRect.width,
221
- height: rowRect.height,
222
- },
223
- panel: { height: panel.offsetHeight },
224
- viewport,
225
- });
226
- panel.style.setProperty('--nm-dropdown-top', `${placement.top}px`);
227
- panel.style.setProperty('--nm-dropdown-left', `${placement.left}px`);
228
- panel.style.setProperty('--nm-dropdown-right', 'auto');
229
- panel.style.setProperty('--nm-dropdown-width', `${placement.width}px`);
230
- panel.style.width = `${placement.width}px`;
231
- logger.debug('place-row', triggerLabel, placement);
232
- return;
233
- }
234
-
235
- const placement = placeNmDropdownPanel({
236
- trigger: {
237
- top: rect.top,
238
- left: rect.left,
239
- right: rect.right,
240
- bottom: rect.bottom,
241
- width: rect.width,
242
- height: rect.height,
243
- },
244
- panel: { width: panel.offsetWidth, height: panel.offsetHeight },
245
- viewport,
246
- align: props.align ?? NM_DROPDOWN_ALIGN.start,
247
- });
248
- panel.style.removeProperty('--nm-dropdown-width');
249
- panel.style.removeProperty('width');
250
- panel.style.setProperty('--nm-dropdown-top', `${placement.top}px`);
251
- panel.style.setProperty('--nm-dropdown-left', `${placement.left}px`);
252
- panel.style.setProperty('--nm-dropdown-right', 'auto');
253
- logger.debug('place', triggerLabel, placement);
254
- }
255
- applyPlacement();
256
- window.addEventListener('resize', applyPlacement);
257
- window.addEventListener('scroll', applyPlacement, true);
258
- return () => {
259
- window.removeEventListener('resize', applyPlacement);
260
- window.removeEventListener('scroll', applyPlacement, true);
261
- };
262
- }, [open, portal, props.align, alignName, items.length, expandedIds, triggerLabel]);
263
-
264
116
  logger.debug('render', triggerLabel, { open, items: items.length });
265
117
 
266
- const panelClass = [
267
- NM_DROPDOWN_CLASSES.panel,
268
- props.align === NM_DROPDOWN_ALIGN.end ? NM_DROPDOWN_CLASSES.panelEnd : '',
269
- props.align === NM_DROPDOWN_ALIGN.row ? NM_DROPDOWN_CLASSES.panelRow : '',
270
- portal ? NM_DROPDOWN_CLASSES.panelPortal : '',
271
- ]
272
- .filter((value) => value !== '')
273
- .join(' ');
274
-
275
- const panel = (
276
- <NmDropdownPanel
277
- open={open}
278
- placement={motionPlacement}
279
- className={panelClass}
280
- id={panelId}
281
- label={props.label}
282
- panelRef={panelRef}
283
- >
284
- <NmDropdownOptions
285
- items={items}
286
- selected={props.selected}
287
- expandedIds={expandedIds}
288
- onOpenBranch={(id) => {
289
- setExpandedIds((current) => {
290
- const next = openDropdownBranch(items, id);
291
- const same =
292
- next.length === current.length &&
293
- next.every((value, index) => value === current[index]);
294
- if (same) {
295
- return current;
296
- }
297
- logger.debug('hover', id);
298
- props.onBranchExpand?.(id);
299
- return next;
300
- });
301
- }}
302
- onCloseBranches={() => {
303
- setExpandedIds((current) => (current.length === 0 ? current : []));
304
- }}
305
- onSelect={(id) => {
306
- logger.debug('select', id);
307
- props.onSelect?.(id);
308
- setOpen(false);
309
- setExpandedIds([]);
310
- }}
311
- />
312
- </NmDropdownPanel>
313
- );
314
-
315
118
  const bindTrigger = (node: HTMLButtonElement | null) => {
316
119
  triggerNodeRef.current = node;
317
120
  assignTriggerRef(props.triggerRef, node);
318
121
  };
319
- const toggle = (event: ReactMouseEvent<HTMLButtonElement>) => {
320
- event.stopPropagation();
321
- if (!open) {
322
- const rect = triggerNodeRef.current?.getBoundingClientRect();
323
- if (rect != null) {
324
- const side = rect.bottom + 120 > window.innerHeight ? 'top' : 'bottom';
325
- setMotionPlacement(`${side}-${alignName}`);
326
- }
327
- }
328
- setOpen(!open);
329
- };
330
122
 
331
123
  const rootClass = [
332
124
  NM_DROPDOWN_CLASSES.root,
@@ -335,7 +127,7 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
335
127
  .filter((value) => value !== '')
336
128
  .join(' ');
337
129
 
338
- let triggerElement: JSX.Element;
130
+ let triggerElement: ReactElement;
339
131
  if (props.trigger === NM_DROPDOWN_TRIGGER.icon) {
340
132
  triggerElement = (
341
133
  <NordmanIconButton
@@ -344,11 +136,7 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
344
136
  imageSrc={props.imageSrc}
345
137
  tone={NM_ICON_BUTTON_TONES.quiet}
346
138
  disabled={props.disabled}
347
- expanded={open}
348
- popup="listbox"
349
- controls={panelId}
350
139
  ref={bindTrigger}
351
- onClick={toggle}
352
140
  />
353
141
  );
354
142
  } else if (iconButton) {
@@ -357,40 +145,22 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
357
145
  glyph={props.icon ?? 'ellipsis'}
358
146
  label={props.label}
359
147
  className={props.triggerClassName}
360
- aria-haspopup="listbox"
361
- aria-expanded={open}
362
- aria-controls={panelId}
148
+ disabled={props.disabled}
363
149
  ref={bindTrigger}
364
- onClick={toggle}
365
150
  />
366
151
  );
367
152
  } else {
368
153
  triggerElement = (
369
- <button
370
- className={triggerClass}
371
- type="button"
372
- aria-haspopup="listbox"
373
- aria-expanded={open}
374
- aria-controls={panelId}
375
- aria-label={props.label}
376
- ref={bindTrigger}
377
- onClick={toggle}
378
- >
154
+ <button className={triggerClass} type="button" aria-label={props.label} disabled={props.disabled} ref={bindTrigger}>
379
155
  {iconOnlyTrigger ? (
380
- dropdownGlyph(
381
- props.imageSrc,
382
- iconOnlyTrigger ? (leadIcon ?? props.icon ?? 'ellipsis') : (props.icon ?? 'ellipsis'),
383
- iconOnlyTrigger ? NM_DROPDOWN_CLASSES.lead : undefined,
384
- )
156
+ dropdownGlyph(props.imageSrc, leadIcon ?? props.icon ?? 'ellipsis', NM_DROPDOWN_CLASSES.lead)
385
157
  ) : (
386
158
  <>
387
159
  {dropdownGlyph(props.imageSrc, leadIcon, NM_DROPDOWN_CLASSES.lead)}
388
160
  <span className={NM_DROPDOWN_CLASSES.label}>{triggerLabel}</span>
389
161
  </>
390
162
  )}
391
- {chip || iconTrigger ? null : (
392
- <NmIcon id="chevron" className={NM_DROPDOWN_CLASSES.chevron} />
393
- )}
163
+ {chip || iconTrigger ? null : <NmIcon id="chevron" className={NM_DROPDOWN_CLASSES.chevron} />}
394
164
  </button>
395
165
  );
396
166
  }
@@ -398,15 +168,24 @@ export function NmDropdown(props: NmDropdownProps): ReactNode {
398
168
  return (
399
169
  <div
400
170
  className={rootClass}
401
- ref={rootRef}
402
171
  data-testid={props.testId}
403
172
  data-open={open ? 'true' : undefined}
404
173
  data-reveal={props.reveal}
405
174
  >
406
- {triggerElement}
407
- {portal && typeof document !== 'undefined'
408
- ? createPortal(panel, dropdownPortalHost(props.portalRoot, triggerNodeRef.current))
409
- : panel}
175
+ <NmDropdownMenu open={open} onOpenChange={setOpen}>
176
+ <NmDropdownMenuTrigger render={triggerElement} />
177
+ <NmDropdownMenuContent align={props.align === NM_DROPDOWN_ALIGN.end ? 'end' : 'start'}>
178
+ <NmDropdownMenuItems
179
+ items={items}
180
+ selected={props.selected}
181
+ onBranchExpand={props.onBranchExpand}
182
+ onSelect={(id) => {
183
+ logger.debug('select', id);
184
+ props.onSelect?.(id);
185
+ }}
186
+ />
187
+ </NmDropdownMenuContent>
188
+ </NmDropdownMenu>
410
189
  </div>
411
190
  );
412
191
  }
@@ -10,6 +10,7 @@
10
10
  flex-direction: column;
11
11
  gap: var(--nm-space-2);
12
12
  min-width: var(--nm-width-menu);
13
+ max-width: min(var(--nm-width-menu-max), calc(100vw - var(--nm-space-16) * 2));
13
14
  max-height: var(--available-height);
14
15
  padding: var(--nm-list-pad);
15
16
  overflow-x: hidden;
@@ -29,6 +30,13 @@
29
30
  opacity: 0;
30
31
  }
31
32
 
33
+ .nm-menu__item-text {
34
+ min-width: 0;
35
+ flex: 1 1 auto;
36
+ overflow: hidden;
37
+ text-overflow: ellipsis;
38
+ }
39
+
32
40
  .nm-menu__label {
33
41
  padding: var(--nm-space-6) var(--nm-icon-pad);
34
42
  color: var(--nm-fg-subtle);
@@ -1,7 +1,11 @@
1
- import type { ComponentProps } from 'react';
2
- import { Menu as MenuPrimitive } from '@base-ui/react/menu';
1
+ import { createContext, useContext, type ComponentProps } from 'react';
2
+ import { AnimateIcon, Menu as MenuPrimitive } from '../../lib/nm-motion.ts';
3
3
  import { nmClass } from '../../lib/nm-class.ts';
4
4
  import { NmIcon } from '../nm-icon/nm-icon.tsx';
5
+ import type { NmDropdownItem } from '../nm-dropdown/nm-dropdown-item.ts';
6
+
7
+ /** Set inside a group, where Base UI lets a label name that group. */
8
+ const InGroup = createContext(false);
5
9
 
6
10
  /** Base UI Menu, in the shadcn dropdown-menu composition, styled by NIF tokens. */
7
11
  export function NmDropdownMenu(props: MenuPrimitive.Root.Props) {
@@ -32,11 +36,21 @@ export function NmDropdownMenuContent({
32
36
  }
33
37
 
34
38
  export function NmDropdownMenuGroup(props: MenuPrimitive.Group.Props) {
35
- return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
39
+ return (
40
+ <InGroup.Provider value>
41
+ <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
42
+ </InGroup.Provider>
43
+ );
36
44
  }
37
45
 
46
+ /** A heading in the menu. Inside a group it names the group. On its own it is a plain heading, and never breaks the menu. */
38
47
  export function NmDropdownMenuLabel({ className, ...props }: MenuPrimitive.GroupLabel.Props) {
39
- return <MenuPrimitive.GroupLabel data-slot="dropdown-menu-label" className={nmClass('nm-menu__label', className as string)} {...props} />;
48
+ const classes = nmClass('nm-menu__label', className as string);
49
+ return useContext(InGroup) ? (
50
+ <MenuPrimitive.GroupLabel data-slot="dropdown-menu-label" className={classes} {...props} />
51
+ ) : (
52
+ <div role="presentation" data-slot="dropdown-menu-label" className={classes} {...(props as ComponentProps<'div'>)} />
53
+ );
40
54
  }
41
55
 
42
56
  export function NmDropdownMenuItem({
@@ -44,7 +58,11 @@ export function NmDropdownMenuItem({
44
58
  variant = 'default',
45
59
  ...props
46
60
  }: MenuPrimitive.Item.Props & { variant?: 'default' | 'destructive' }) {
47
- return <MenuPrimitive.Item data-slot="dropdown-menu-item" data-variant={variant} className={nmClass('nm-menu__item', className as string)} {...props} />;
61
+ return (
62
+ <AnimateIcon animateOnHover asChild>
63
+ <MenuPrimitive.Item data-slot="dropdown-menu-item" data-variant={variant} className={nmClass('nm-menu__item', className as string)} {...props} />
64
+ </AnimateIcon>
65
+ );
48
66
  }
49
67
 
50
68
  export function NmDropdownMenuSub(props: MenuPrimitive.SubmenuRoot.Props) {
@@ -78,7 +96,11 @@ export function NmDropdownMenuCheckboxItem({ className, children, ...props }: Me
78
96
  }
79
97
 
80
98
  export function NmDropdownMenuRadioGroup(props: MenuPrimitive.RadioGroup.Props) {
81
- return <MenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
99
+ return (
100
+ <InGroup.Provider value>
101
+ <MenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />
102
+ </InGroup.Provider>
103
+ );
82
104
  }
83
105
 
84
106
  export function NmDropdownMenuRadioItem({ className, children, ...props }: MenuPrimitive.RadioItem.Props) {
@@ -116,3 +138,60 @@ export function NmDropdownMenuText({ title, description }: { title: string; desc
116
138
  export function NmDropdownMenuDot({ status }: { status?: 'ok' | 'error' }) {
117
139
  return <span className="nm-menu__dot" data-status={status} aria-hidden="true" />;
118
140
  }
141
+
142
+ function itemBody(item: NmDropdownItem) {
143
+ return (
144
+ <>
145
+ {item.icon ? <NmIcon id={item.icon} /> : null}
146
+ <span className="nm-menu__item-text">{item.label}</span>
147
+ {item.detail ? <span className="nm-menu__description">{item.detail}</span> : null}
148
+ {item.shortcut ? <NmDropdownMenuShortcut>{item.shortcut}</NmDropdownMenuShortcut> : null}
149
+ </>
150
+ );
151
+ }
152
+
153
+ /** A list of NmDropdownItem as animated menu rows: branches become submenus, `checked` rows keep a mark. */
154
+ export function NmDropdownMenuItems({
155
+ items,
156
+ selected,
157
+ onSelect,
158
+ onBranchExpand,
159
+ }: {
160
+ items: readonly NmDropdownItem[];
161
+ selected?: string | null;
162
+ onSelect?: (id: string) => void;
163
+ onBranchExpand?: (id: string) => void;
164
+ }) {
165
+ return (
166
+ <>
167
+ {items.map((item, index) => {
168
+ if (item.separator === true) {
169
+ return <NmDropdownMenuSeparator key={`${item.id}-${index}`} />;
170
+ }
171
+ if (item.children != null && item.children.length > 0) {
172
+ return (
173
+ <NmDropdownMenuSub key={item.id}>
174
+ <NmDropdownMenuSubTrigger disabled={item.disabled} onMouseEnter={() => onBranchExpand?.(item.id)} onFocus={() => onBranchExpand?.(item.id)}>{itemBody(item)}</NmDropdownMenuSubTrigger>
175
+ <NmDropdownMenuSubContent>
176
+ <NmDropdownMenuItems items={item.children} selected={selected} onSelect={onSelect} onBranchExpand={onBranchExpand} />
177
+ </NmDropdownMenuSubContent>
178
+ </NmDropdownMenuSub>
179
+ );
180
+ }
181
+ const checked = item.checked ?? (selected != null ? item.id === selected : undefined);
182
+ if (checked !== undefined) {
183
+ return (
184
+ <NmDropdownMenuCheckboxItem key={item.id} checked={checked} disabled={item.disabled} onClick={() => onSelect?.(item.id)}>
185
+ {itemBody(item)}
186
+ </NmDropdownMenuCheckboxItem>
187
+ );
188
+ }
189
+ return (
190
+ <NmDropdownMenuItem key={item.id} variant={item.danger ? 'destructive' : 'default'} disabled={item.disabled} onClick={() => onSelect?.(item.id)}>
191
+ {itemBody(item)}
192
+ </NmDropdownMenuItem>
193
+ );
194
+ })}
195
+ </>
196
+ );
197
+ }
@@ -28,6 +28,7 @@ import { NmCombobox, NmComboboxContent, NmComboboxEmpty, NmComboboxInput, NmComb
28
28
  import { NmSelect, NmSelectContent, NmSelectItem, NmSelectTrigger, NmSelectValue } from '../nm-select/nm-select.tsx';
29
29
  import { NmColorSwatch } from '../nm-color-picker/nm-color-picker.tsx';
30
30
  import { NmIcon } from '../nm-icon/nm-icon.tsx';
31
+ import { NmTextarea } from '../nm-textarea/nm-textarea.tsx';
31
32
 
32
33
  const logger = createLogger('interface-nm-field');
33
34
 
@@ -76,6 +77,8 @@ export type NmFieldProps = {
76
77
  onKeyUp?: KeyboardEventHandler<HTMLInputElement>;
77
78
  onFocus?: () => void;
78
79
  onBlur?: () => void;
80
+ openInPanel?: boolean;
81
+ panelTitle?: string;
79
82
  };
80
83
 
81
84
  function OptionSwatches(props: { colors?: readonly string[] }): ReactNode {
@@ -290,7 +293,9 @@ function StackControl(
290
293
  );
291
294
  } else if (props.kind === NM_FIELD_KINDS.area) {
292
295
  editor = (
293
- <textarea
296
+ <NmTextarea
297
+ variant={props.openInPanel ? 'panel' : 'default'}
298
+ panelTitle={props.panelTitle ?? props.caption ?? props.label}
294
299
  className={NM_FIELD_CLASSES.control}
295
300
  id={props.controlId}
296
301
  name={props.name}
@@ -1,4 +1,4 @@
1
- import { PreviewCard as PreviewCardPrimitive } from '@base-ui/react/preview-card';
1
+ import { PreviewCard as PreviewCardPrimitive } from '../../lib/nm-motion.ts';
2
2
  import { nmClass } from '../../lib/nm-class.ts';
3
3
 
4
4
  /** Base UI Preview Card, in the shadcn hover-card composition, styled by NIF tokens. */
@@ -0,0 +1,109 @@
1
+ /* From Animate UI's registry (icons-lucide-activity), with its import pointed at NIF's motion adapter. */
2
+ 'use client';
3
+
4
+ import * as React from 'react';
5
+ import { motion, type Variants } from 'motion/react';
6
+
7
+ import {
8
+ getVariants,
9
+ useAnimateIconContext,
10
+ IconWrapper,
11
+ type IconProps,
12
+ } from '@animate-ui/react/icons';
13
+
14
+ type ActivityProps = IconProps<keyof typeof animations>;
15
+
16
+ const animations = {
17
+ default: {
18
+ path: {
19
+ initial: {
20
+ opacity: 1,
21
+ pathLength: 1,
22
+ pathOffset: 0,
23
+ },
24
+ animate: {
25
+ opacity: [0, 1],
26
+ pathLength: [0, 1],
27
+ pathOffset: [1, 0],
28
+ transition: {
29
+ duration: 0.8,
30
+ ease: 'easeInOut',
31
+ opacity: { duration: 0.01 },
32
+ },
33
+ },
34
+ },
35
+ } satisfies Record<string, Variants>,
36
+ 'default-return': {
37
+ path: {
38
+ initial: {
39
+ opacity: 1,
40
+ pathLength: 1,
41
+ pathOffset: 0,
42
+ },
43
+ animate: {
44
+ opacity: [0, 1, 1, 1],
45
+ pathLength: [0, 1, 0, 1],
46
+ pathOffset: [1, 0, 0.01, 0],
47
+ transition: {
48
+ duration: 2.5,
49
+ ease: 'easeInOut',
50
+ opacity: { duration: 0.01 },
51
+ },
52
+ },
53
+ },
54
+ } satisfies Record<string, Variants>,
55
+ 'default-loop': {
56
+ path: {
57
+ initial: {
58
+ opacity: 1,
59
+ pathLength: 1,
60
+ pathOffset: 0,
61
+ },
62
+ animate: {
63
+ opacity: [0, 1, 1, 1, 1],
64
+ pathLength: [0, 1, 0, 1, 0],
65
+ pathOffset: [1, 0, 0.01, 0, 0.999],
66
+ transition: {
67
+ duration: 3,
68
+ ease: 'easeInOut',
69
+ repeat: Infinity,
70
+ repeatType: 'loop',
71
+ opacity: { duration: 0.01 },
72
+ },
73
+ },
74
+ },
75
+ } satisfies Record<string, Variants>,
76
+ } as const;
77
+
78
+ function IconComponent({ size, ...props }: ActivityProps) {
79
+ const { controls } = useAnimateIconContext();
80
+ const variants = getVariants(animations);
81
+
82
+ return (
83
+ <motion.svg
84
+ xmlns="http://www.w3.org/2000/svg"
85
+ width={size}
86
+ height={size}
87
+ viewBox="0 0 24 24"
88
+ fill="none"
89
+ stroke="currentColor"
90
+ strokeWidth={2}
91
+ strokeLinecap="round"
92
+ strokeLinejoin="round"
93
+ {...props}
94
+ >
95
+ <motion.path
96
+ d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"
97
+ variants={variants.path}
98
+ initial="initial"
99
+ animate={controls}
100
+ />
101
+ </motion.svg>
102
+ );
103
+ }
104
+
105
+ function Activity(props: ActivityProps) {
106
+ return <IconWrapper icon={IconComponent} {...props} />;
107
+ }
108
+
109
+ export { animations, Activity as ActivityAnimated };