@nordmanai/nif 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (398) hide show
  1. package/README.md +79 -2
  2. package/bin/nif.mjs +196 -0
  3. package/dist/index.d.ts +124 -0
  4. package/dist/index.js +12961 -0
  5. package/dist/styles.css +2 -0
  6. package/dist/tokens.css +72 -0
  7. package/dist/ui/components/nm-ai/nm-ai.d.ts +222 -0
  8. package/dist/ui/components/nm-avatar/nm-avatar.d.ts +12 -0
  9. package/dist/ui/components/nm-bar-overflow/nm-bar-overflow.d.ts +15 -0
  10. package/dist/ui/components/nm-bar-overflow/use-bar-overflow.d.ts +7 -0
  11. package/dist/ui/components/nm-brand-logo/nm-brand-logo.d.ts +10 -0
  12. package/dist/ui/components/nm-breadcrumb/nm-breadcrumb.d.ts +11 -0
  13. package/dist/ui/components/nm-button/nm-button.d.ts +19 -0
  14. package/dist/ui/components/nm-button-group/nm-button-group.d.ts +17 -0
  15. package/dist/ui/components/nm-calendar/nm-calendar.d.ts +3 -0
  16. package/dist/ui/components/nm-card/nm-card.d.ts +34 -0
  17. package/dist/ui/components/nm-chatbox/nm-chatbox-icon.d.ts +7 -0
  18. package/dist/ui/components/nm-chatbox/nm-chatbox.d.ts +19 -0
  19. package/dist/ui/components/nm-checkbox/nm-checkbox.d.ts +2 -0
  20. package/dist/ui/components/nm-chip/nm-chip.d.ts +38 -0
  21. package/dist/ui/components/nm-code-block/nm-code-block.d.ts +55 -0
  22. package/dist/ui/components/nm-collection/nm-collection-bar.d.ts +16 -0
  23. package/dist/ui/components/nm-collection/nm-collection-grid.d.ts +9 -0
  24. package/dist/ui/components/nm-collection/nm-collection-query.d.ts +18 -0
  25. package/dist/ui/components/nm-collection/nm-collection-row-menu.d.ts +7 -0
  26. package/dist/ui/components/nm-collection/nm-collection-table.d.ts +13 -0
  27. package/dist/ui/components/nm-collection/nm-collection-tile-actions.d.ts +7 -0
  28. package/dist/ui/components/nm-collection/nm-collection-title.d.ts +10 -0
  29. package/dist/ui/components/nm-collection/use-collection-scroll-reveal.d.ts +3 -0
  30. package/dist/ui/components/nm-color-picker/nm-color-picker.d.ts +15 -0
  31. package/dist/ui/components/nm-combobox/nm-combobox.d.ts +26 -0
  32. package/dist/ui/components/nm-command/nm-command.d.ts +37 -0
  33. package/dist/ui/components/nm-composer/nm-composer.d.ts +33 -0
  34. package/dist/ui/components/nm-context-menu/nm-context-menu.d.ts +9 -0
  35. package/dist/ui/components/nm-date-picker/nm-date-picker.d.ts +35 -0
  36. package/dist/ui/components/nm-dialog/nm-dialog.d.ts +13 -0
  37. package/dist/ui/components/nm-dropdown/nm-dropdown-item.d.ts +26 -0
  38. package/dist/ui/components/nm-dropdown/nm-dropdown-options.d.ts +12 -0
  39. package/dist/ui/components/nm-dropdown/nm-dropdown-panel.d.ts +16 -0
  40. package/dist/ui/components/nm-dropdown/nm-dropdown-placement.d.ts +55 -0
  41. package/dist/ui/components/nm-dropdown/nm-dropdown.d.ts +31 -0
  42. package/dist/ui/components/nm-dropdown-menu/nm-dropdown-menu.d.ts +30 -0
  43. package/dist/ui/components/nm-field/nm-field.d.ts +52 -0
  44. package/dist/ui/components/nm-form-field/nm-form-field.d.ts +18 -0
  45. package/dist/ui/components/nm-gallery/nm-gallery.d.ts +8 -0
  46. package/dist/ui/components/nm-hover-card/nm-hover-card.d.ts +5 -0
  47. package/dist/ui/components/nm-icon/nm-icon.d.ts +7 -0
  48. package/dist/ui/components/nm-icon/nm-lucide.d.ts +7 -0
  49. package/dist/ui/components/nm-icon-border/nm-icon-border.d.ts +21 -0
  50. package/dist/ui/components/nm-input/nm-input.d.ts +5 -0
  51. package/dist/ui/components/nm-input-group/nm-input-group.d.ts +9 -0
  52. package/dist/ui/components/nm-label/nm-label.d.ts +2 -0
  53. package/dist/ui/components/nm-list-item/nm-list-item.d.ts +23 -0
  54. package/dist/ui/components/nm-menubar/nm-menubar.d.ts +9 -0
  55. package/dist/ui/components/nm-message/nm-message-actions.d.ts +7 -0
  56. package/dist/ui/components/nm-message/nm-message-meta.d.ts +10 -0
  57. package/dist/ui/components/nm-message/nm-text-shimmer.d.ts +4 -0
  58. package/dist/ui/components/nm-message/nm-trace.d.ts +58 -0
  59. package/dist/ui/components/nm-modal/nm-modal.d.ts +35 -0
  60. package/dist/ui/components/nm-native-select/nm-native-select.d.ts +5 -0
  61. package/dist/ui/components/nm-panel/nm-panel.d.ts +14 -0
  62. package/dist/ui/components/nm-panel-bar/nm-panel-bar.d.ts +17 -0
  63. package/dist/ui/components/nm-popover/nm-popover.d.ts +8 -0
  64. package/dist/ui/components/nm-progress/nm-progress.d.ts +3 -0
  65. package/dist/ui/components/nm-prose/nm-prose.d.ts +6 -0
  66. package/dist/ui/components/nm-questionnaire/nm-questionnaire.d.ts +17 -0
  67. package/dist/ui/components/nm-radio-group/nm-radio-group.d.ts +4 -0
  68. package/dist/ui/components/nm-rail-icon/nm-rail-icon.d.ts +6 -0
  69. package/dist/ui/components/nm-resize-handle/nm-resize-handle.d.ts +18 -0
  70. package/dist/ui/components/nm-segmented/nm-segmented.d.ts +20 -0
  71. package/dist/ui/components/nm-select/nm-select.d.ts +22 -0
  72. package/dist/ui/components/nm-separator/nm-separator.d.ts +2 -0
  73. package/dist/ui/components/nm-side-panel/nm-side-panel.d.ts +33 -0
  74. package/dist/ui/components/nm-slider/nm-slider.d.ts +6 -0
  75. package/dist/ui/components/nm-small-icon-button/nm-small-icon-button.d.ts +21 -0
  76. package/dist/ui/components/nm-status-bar/nm-status-bar.d.ts +8 -0
  77. package/dist/ui/components/nm-switch/nm-switch.d.ts +2 -0
  78. package/dist/ui/components/nm-table/nm-table.d.ts +38 -0
  79. package/dist/ui/components/nm-tabs/nm-tabs.d.ts +9 -0
  80. package/dist/ui/components/nm-textarea/nm-textarea.d.ts +2 -0
  81. package/dist/ui/components/nm-toggle/nm-toggle.d.ts +9 -0
  82. package/dist/ui/components/nm-toolbar/nm-toolbar.d.ts +21 -0
  83. package/dist/ui/components/nm-tooltip/nm-tooltip.d.ts +5 -0
  84. package/dist/ui/components/nm-top-bar/nm-top-bar.d.ts +12 -0
  85. package/dist/ui/components/nordman-icon-button/nordman-icon-button.d.ts +29 -0
  86. package/dist/ui/components/nordman-login/nordman-login.d.ts +36 -0
  87. package/dist/ui/components/nordman-login-field/nordman-login-field.d.ts +13 -0
  88. package/dist/ui/components/nordman-login-forgot/nordman-login-forgot.d.ts +9 -0
  89. package/dist/ui/components/nordman-login-google/nordman-login-google.d.ts +6 -0
  90. package/dist/ui/components/nordman-login-hero/nordman-login-hero.d.ts +6 -0
  91. package/dist/ui/components/nordman-login-register/nordman-login-register.d.ts +11 -0
  92. package/dist/ui/components/nordman-login-reset/nordman-login-reset.d.ts +9 -0
  93. package/dist/ui/components/nordman-login-reveal/nordman-login-reveal.d.ts +6 -0
  94. package/dist/ui/components/nordman-login-sign-in/nordman-login-sign-in.d.ts +11 -0
  95. package/dist/ui/components/nordman-toggle/nordman-toggle.d.ts +12 -0
  96. package/dist/ui/config/nm-ai.d.ts +44 -0
  97. package/dist/ui/config/nm-app-panel.d.ts +36 -0
  98. package/dist/ui/config/nm-appearance.d.ts +100 -0
  99. package/dist/ui/config/nm-bar-overflow.d.ts +9 -0
  100. package/dist/ui/config/nm-button.d.ts +31 -0
  101. package/dist/ui/config/nm-chatbox-icons.d.ts +42 -0
  102. package/dist/ui/config/nm-chatbox.d.ts +40 -0
  103. package/dist/ui/config/nm-collection.d.ts +88 -0
  104. package/dist/ui/config/nm-composer.d.ts +42 -0
  105. package/dist/ui/config/nm-dropdown.d.ts +56 -0
  106. package/dist/ui/config/nm-fade.d.ts +6 -0
  107. package/dist/ui/config/nm-field.d.ts +38 -0
  108. package/dist/ui/config/nm-header-icons.d.ts +15 -0
  109. package/dist/ui/config/nm-icon-border.d.ts +3 -0
  110. package/dist/ui/config/nm-icon-button.d.ts +26 -0
  111. package/dist/ui/config/nm-icons.d.ts +371 -0
  112. package/dist/ui/config/nm-list-item.d.ts +14 -0
  113. package/dist/ui/config/nm-message.d.ts +87 -0
  114. package/dist/ui/config/nm-modal.d.ts +67 -0
  115. package/dist/ui/config/nm-panel-bar.d.ts +9 -0
  116. package/dist/ui/config/nm-questionnaire.d.ts +57 -0
  117. package/dist/ui/config/nm-radius.d.ts +49 -0
  118. package/dist/ui/config/nm-rail-icons.d.ts +14 -0
  119. package/dist/ui/config/nm-rail.d.ts +5 -0
  120. package/dist/ui/config/nm-segmented.d.ts +17 -0
  121. package/dist/ui/config/nm-side-panel.d.ts +33 -0
  122. package/dist/ui/config/nm-site-palette.d.ts +30 -0
  123. package/dist/ui/config/nm-small-icon-button.d.ts +12 -0
  124. package/dist/ui/config/nm-tabs.d.ts +8 -0
  125. package/dist/ui/config/nm-top-bar.d.ts +4 -0
  126. package/dist/ui/config/nordman-chrome.d.ts +12 -0
  127. package/dist/ui/config/nordman-login.d.ts +23 -0
  128. package/dist/ui/content/nm-modal.d.ts +1 -0
  129. package/dist/ui/content/nordman-login.d.ts +38 -0
  130. package/dist/ui/kit-logger.d.ts +1 -0
  131. package/dist/ui/lib/appearance/appearanceState.d.ts +28 -0
  132. package/dist/ui/lib/appearance/applyAppearance.d.ts +5 -0
  133. package/dist/ui/lib/appearance/cloudOrbAppearance.d.ts +4 -0
  134. package/dist/ui/lib/appearance/color.d.ts +13 -0
  135. package/dist/ui/lib/appearance/deriveTokens.d.ts +6 -0
  136. package/dist/ui/lib/appearance/index.d.ts +6 -0
  137. package/dist/ui/lib/appearance/markTokens.d.ts +2 -0
  138. package/dist/ui/lib/appearance/readLayoutMetrics.d.ts +4 -0
  139. package/dist/ui/lib/bar-overflow.d.ts +13 -0
  140. package/dist/ui/lib/logger.d.ts +8 -0
  141. package/dist/ui/lib/menu-motion.d.ts +72 -0
  142. package/dist/ui/lib/nm-class.d.ts +2 -0
  143. package/dist/ui/lib/nordman-ui-locale.d.ts +9 -0
  144. package/interface/app-panel/code.svg +5 -0
  145. package/interface/app-panel/console.svg +5 -0
  146. package/interface/app-panel/copy.svg +5 -0
  147. package/interface/app-panel/ellipsis.svg +7 -0
  148. package/interface/app-panel/message.svg +5 -0
  149. package/interface/app-panel/network.svg +10 -0
  150. package/interface/app-panel/play.svg +5 -0
  151. package/interface/app-panel/plus.svg +5 -0
  152. package/interface/chatbox/app.svg +5 -0
  153. package/interface/chatbox/audio-lines.svg +5 -0
  154. package/interface/chatbox/check.svg +5 -0
  155. package/interface/chatbox/globe.svg +5 -0
  156. package/interface/chatbox/integration.svg +5 -0
  157. package/interface/chatbox/mic.svg +5 -0
  158. package/interface/chatbox/paperclip.svg +5 -0
  159. package/interface/chatbox/pointer.svg +5 -0
  160. package/interface/chatbox/send.svg +5 -0
  161. package/interface/chatbox/settings.svg +5 -0
  162. package/interface/chatbox/spreadsheet.svg +5 -0
  163. package/interface/chatbox/x.svg +5 -0
  164. package/interface/collection/audio.svg +5 -0
  165. package/interface/collection/download.svg +5 -0
  166. package/interface/collection/expand.svg +5 -0
  167. package/interface/collection/grid.svg +10 -0
  168. package/interface/collection/image.svg +5 -0
  169. package/interface/collection/spreadsheet.svg +5 -0
  170. package/interface/collection/video.svg +5 -0
  171. package/interface/header/app.svg +5 -0
  172. package/interface/header/bot.svg +5 -0
  173. package/interface/header/chat.svg +10 -0
  174. package/interface/header/folder.svg +5 -0
  175. package/interface/header/layers.svg +10 -0
  176. package/interface/header/panel.svg +5 -0
  177. package/interface/header/play.svg +3 -0
  178. package/interface/header/schedule.svg +8 -0
  179. package/interface/header/search.svg +5 -0
  180. package/interface/header/settings.svg +5 -0
  181. package/interface/header/users.svg +5 -0
  182. package/interface/message/chevron.svg +5 -0
  183. package/interface/message/copy.svg +5 -0
  184. package/interface/message/fork.svg +5 -0
  185. package/interface/message/refresh.svg +5 -0
  186. package/interface/message/volume.svg +5 -0
  187. package/interface/rail/app.svg +5 -0
  188. package/interface/rail/bot.svg +5 -0
  189. package/interface/rail/chats.svg +5 -0
  190. package/interface/rail/folder.svg +5 -0
  191. package/interface/rail/library.svg +5 -0
  192. package/interface/rail/plus-sm.svg +5 -0
  193. package/interface/rail/plus.svg +5 -0
  194. package/interface/rail/search.svg +5 -0
  195. package/interface/rail/settings.svg +8 -0
  196. package/interface/rail/spreadsheet.svg +5 -0
  197. package/package.json +79 -4
  198. package/registry/index.json +1634 -0
  199. package/registry/tokens.css +72 -0
  200. package/registry/ui/components/nm-ai/nm-ai.css +358 -0
  201. package/registry/ui/components/nm-ai/nm-ai.tsx +632 -0
  202. package/registry/ui/components/nm-app-panel/nm-app-panel.css +169 -0
  203. package/registry/ui/components/nm-ask/nm-ask.css +277 -0
  204. package/registry/ui/components/nm-avatar/nm-avatar.css +85 -0
  205. package/registry/ui/components/nm-avatar/nm-avatar.tsx +30 -0
  206. package/registry/ui/components/nm-bar-overflow/nm-bar-overflow.css +43 -0
  207. package/registry/ui/components/nm-bar-overflow/nm-bar-overflow.tsx +61 -0
  208. package/registry/ui/components/nm-bar-overflow/use-bar-overflow.ts +92 -0
  209. package/registry/ui/components/nm-brand-logo/nm-brand-logo.css +20 -0
  210. package/registry/ui/components/nm-brand-logo/nm-brand-logo.tsx +21 -0
  211. package/registry/ui/components/nm-breadcrumb/nm-breadcrumb.css +57 -0
  212. package/registry/ui/components/nm-breadcrumb/nm-breadcrumb.tsx +42 -0
  213. package/registry/ui/components/nm-button/nm-button.css +110 -0
  214. package/registry/ui/components/nm-button/nm-button.tsx +58 -0
  215. package/registry/ui/components/nm-button-group/nm-button-group.css +87 -0
  216. package/registry/ui/components/nm-button-group/nm-button-group.tsx +32 -0
  217. package/registry/ui/components/nm-calendar/nm-calendar.css +178 -0
  218. package/registry/ui/components/nm-calendar/nm-calendar.tsx +43 -0
  219. package/registry/ui/components/nm-card/nm-card.css +130 -0
  220. package/registry/ui/components/nm-card/nm-card.tsx +83 -0
  221. package/registry/ui/components/nm-chatbox/nm-chatbox-icon.tsx +39 -0
  222. package/registry/ui/components/nm-chatbox/nm-chatbox.css +682 -0
  223. package/registry/ui/components/nm-chatbox/nm-chatbox.tsx +101 -0
  224. package/registry/ui/components/nm-checkbox/nm-checkbox.css +61 -0
  225. package/registry/ui/components/nm-checkbox/nm-checkbox.tsx +14 -0
  226. package/registry/ui/components/nm-chip/nm-chip.css +112 -0
  227. package/registry/ui/components/nm-chip/nm-chip.tsx +86 -0
  228. package/registry/ui/components/nm-code-block/nm-code-block.css +240 -0
  229. package/registry/ui/components/nm-code-block/nm-code-block.tsx +196 -0
  230. package/registry/ui/components/nm-collection/nm-collection-bar.tsx +65 -0
  231. package/registry/ui/components/nm-collection/nm-collection-grid.tsx +69 -0
  232. package/registry/ui/components/nm-collection/nm-collection-query.tsx +99 -0
  233. package/registry/ui/components/nm-collection/nm-collection-row-menu.tsx +55 -0
  234. package/registry/ui/components/nm-collection/nm-collection-table.tsx +99 -0
  235. package/registry/ui/components/nm-collection/nm-collection-tile-actions.tsx +50 -0
  236. package/registry/ui/components/nm-collection/nm-collection-title.tsx +25 -0
  237. package/registry/ui/components/nm-collection/nm-collection.css +353 -0
  238. package/registry/ui/components/nm-collection/use-collection-scroll-reveal.ts +38 -0
  239. package/registry/ui/components/nm-color-picker/nm-color-picker.css +67 -0
  240. package/registry/ui/components/nm-color-picker/nm-color-picker.tsx +79 -0
  241. package/registry/ui/components/nm-combobox/nm-combobox.css +72 -0
  242. package/registry/ui/components/nm-combobox/nm-combobox.tsx +80 -0
  243. package/registry/ui/components/nm-command/nm-command.css +190 -0
  244. package/registry/ui/components/nm-command/nm-command.tsx +125 -0
  245. package/registry/ui/components/nm-composer/nm-composer.css +178 -0
  246. package/registry/ui/components/nm-composer/nm-composer.tsx +151 -0
  247. package/registry/ui/components/nm-context-menu/nm-context-menu.tsx +25 -0
  248. package/registry/ui/components/nm-date-picker/nm-date-picker.css +140 -0
  249. package/registry/ui/components/nm-date-picker/nm-date-picker.tsx +153 -0
  250. package/registry/ui/components/nm-dialog/nm-dialog.css +84 -0
  251. package/registry/ui/components/nm-dialog/nm-dialog.tsx +40 -0
  252. package/registry/ui/components/nm-dropdown/nm-dropdown-item.ts +68 -0
  253. package/registry/ui/components/nm-dropdown/nm-dropdown-options.tsx +242 -0
  254. package/registry/ui/components/nm-dropdown/nm-dropdown-panel.tsx +171 -0
  255. package/registry/ui/components/nm-dropdown/nm-dropdown-placement.ts +157 -0
  256. package/registry/ui/components/nm-dropdown/nm-dropdown.css +312 -0
  257. package/registry/ui/components/nm-dropdown/nm-dropdown.tsx +412 -0
  258. package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.css +145 -0
  259. package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.tsx +118 -0
  260. package/registry/ui/components/nm-field/nm-field.css +356 -0
  261. package/registry/ui/components/nm-field/nm-field.tsx +355 -0
  262. package/registry/ui/components/nm-form-field/nm-form-field.css +103 -0
  263. package/registry/ui/components/nm-form-field/nm-form-field.tsx +71 -0
  264. package/registry/ui/components/nm-gallery/nm-gallery.css +66 -0
  265. package/registry/ui/components/nm-gallery/nm-gallery.tsx +31 -0
  266. package/registry/ui/components/nm-hover-card/nm-hover-card.css +26 -0
  267. package/registry/ui/components/nm-hover-card/nm-hover-card.tsx +28 -0
  268. package/registry/ui/components/nm-icon/nm-icon.css +6 -0
  269. package/registry/ui/components/nm-icon/nm-icon.tsx +69 -0
  270. package/registry/ui/components/nm-icon/nm-lucide.tsx +180 -0
  271. package/registry/ui/components/nm-icon-border/nm-icon-border.tsx +56 -0
  272. package/registry/ui/components/nm-input/nm-input.css +75 -0
  273. package/registry/ui/components/nm-input/nm-input.tsx +7 -0
  274. package/registry/ui/components/nm-input-group/nm-input-group.css +66 -0
  275. package/registry/ui/components/nm-input-group/nm-input-group.tsx +20 -0
  276. package/registry/ui/components/nm-label/nm-label.css +11 -0
  277. package/registry/ui/components/nm-label/nm-label.tsx +6 -0
  278. package/registry/ui/components/nm-list-item/nm-list-item.css +177 -0
  279. package/registry/ui/components/nm-list-item/nm-list-item.tsx +112 -0
  280. package/registry/ui/components/nm-menubar/nm-menubar.css +32 -0
  281. package/registry/ui/components/nm-menubar/nm-menubar.tsx +19 -0
  282. package/registry/ui/components/nm-message/nm-message-actions.tsx +24 -0
  283. package/registry/ui/components/nm-message/nm-message-meta.tsx +49 -0
  284. package/registry/ui/components/nm-message/nm-message.css +686 -0
  285. package/registry/ui/components/nm-message/nm-text-shimmer.tsx +6 -0
  286. package/registry/ui/components/nm-message/nm-trace.tsx +219 -0
  287. package/registry/ui/components/nm-modal/nm-modal.css +763 -0
  288. package/registry/ui/components/nm-modal/nm-modal.tsx +497 -0
  289. package/registry/ui/components/nm-native-select/nm-native-select.css +47 -0
  290. package/registry/ui/components/nm-native-select/nm-native-select.tsx +23 -0
  291. package/registry/ui/components/nm-panel/nm-panel.css +73 -0
  292. package/registry/ui/components/nm-panel/nm-panel.tsx +35 -0
  293. package/registry/ui/components/nm-panel-bar/nm-panel-bar.css +20 -0
  294. package/registry/ui/components/nm-panel-bar/nm-panel-bar.tsx +48 -0
  295. package/registry/ui/components/nm-popover/nm-popover.css +43 -0
  296. package/registry/ui/components/nm-popover/nm-popover.tsx +40 -0
  297. package/registry/ui/components/nm-progress/nm-progress.css +21 -0
  298. package/registry/ui/components/nm-progress/nm-progress.tsx +14 -0
  299. package/registry/ui/components/nm-prose/nm-prose.css +81 -0
  300. package/registry/ui/components/nm-prose/nm-prose.tsx +10 -0
  301. package/registry/ui/components/nm-questionnaire/nm-questionnaire.css +182 -0
  302. package/registry/ui/components/nm-questionnaire/nm-questionnaire.tsx +221 -0
  303. package/registry/ui/components/nm-radio-group/nm-radio-group.css +48 -0
  304. package/registry/ui/components/nm-radio-group/nm-radio-group.tsx +15 -0
  305. package/registry/ui/components/nm-rail-icon/nm-rail-icon.css +6 -0
  306. package/registry/ui/components/nm-rail-icon/nm-rail-icon.tsx +28 -0
  307. package/registry/ui/components/nm-resize-handle/nm-resize-handle.css +45 -0
  308. package/registry/ui/components/nm-resize-handle/nm-resize-handle.tsx +102 -0
  309. package/registry/ui/components/nm-segmented/nm-segmented.css +104 -0
  310. package/registry/ui/components/nm-segmented/nm-segmented.tsx +77 -0
  311. package/registry/ui/components/nm-select/nm-select.css +78 -0
  312. package/registry/ui/components/nm-select/nm-select.tsx +64 -0
  313. package/registry/ui/components/nm-separator/nm-separator.css +14 -0
  314. package/registry/ui/components/nm-separator/nm-separator.tsx +6 -0
  315. package/registry/ui/components/nm-side-panel/nm-side-panel.css +93 -0
  316. package/registry/ui/components/nm-side-panel/nm-side-panel.tsx +86 -0
  317. package/registry/ui/components/nm-slider/nm-slider.css +53 -0
  318. package/registry/ui/components/nm-slider/nm-slider.tsx +40 -0
  319. package/registry/ui/components/nm-small-icon-button/nm-small-icon-button.tsx +66 -0
  320. package/registry/ui/components/nm-status-bar/nm-status-bar.css +50 -0
  321. package/registry/ui/components/nm-status-bar/nm-status-bar.tsx +28 -0
  322. package/registry/ui/components/nm-switch/nm-switch.css +45 -0
  323. package/registry/ui/components/nm-switch/nm-switch.tsx +10 -0
  324. package/registry/ui/components/nm-table/nm-table.css +155 -0
  325. package/registry/ui/components/nm-table/nm-table.tsx +95 -0
  326. package/registry/ui/components/nm-tabs/nm-tabs.css +28 -0
  327. package/registry/ui/components/nm-tabs/nm-tabs.tsx +32 -0
  328. package/registry/ui/components/nm-textarea/nm-textarea.css +41 -0
  329. package/registry/ui/components/nm-textarea/nm-textarea.tsx +6 -0
  330. package/registry/ui/components/nm-toggle/nm-toggle.css +55 -0
  331. package/registry/ui/components/nm-toggle/nm-toggle.tsx +16 -0
  332. package/registry/ui/components/nm-toolbar/nm-toolbar.css +42 -0
  333. package/registry/ui/components/nm-toolbar/nm-toolbar.tsx +54 -0
  334. package/registry/ui/components/nm-tooltip/nm-tooltip.css +37 -0
  335. package/registry/ui/components/nm-tooltip/nm-tooltip.tsx +35 -0
  336. package/registry/ui/components/nm-top-bar/nm-top-bar.css +29 -0
  337. package/registry/ui/components/nm-top-bar/nm-top-bar.tsx +34 -0
  338. package/registry/ui/components/nordman-icon-button/nordman-icon-button.css +119 -0
  339. package/registry/ui/components/nordman-icon-button/nordman-icon-button.tsx +185 -0
  340. package/registry/ui/components/nordman-login/nordman-login.css +195 -0
  341. package/registry/ui/components/nordman-login/nordman-login.tsx +136 -0
  342. package/registry/ui/components/nordman-login-field/nordman-login-field.tsx +55 -0
  343. package/registry/ui/components/nordman-login-forgot/nordman-login-forgot.tsx +56 -0
  344. package/registry/ui/components/nordman-login-google/nordman-login-google.tsx +28 -0
  345. package/registry/ui/components/nordman-login-hero/nordman-login-hero.tsx +38 -0
  346. package/registry/ui/components/nordman-login-register/nordman-login-register.tsx +70 -0
  347. package/registry/ui/components/nordman-login-reset/nordman-login-reset.tsx +71 -0
  348. package/registry/ui/components/nordman-login-reveal/nordman-login-reveal.tsx +41 -0
  349. package/registry/ui/components/nordman-login-sign-in/nordman-login-sign-in.tsx +69 -0
  350. package/registry/ui/components/nordman-toggle/nordman-toggle.css +28 -0
  351. package/registry/ui/components/nordman-toggle/nordman-toggle.tsx +35 -0
  352. package/registry/ui/config/nm-ai.ts +59 -0
  353. package/registry/ui/config/nm-appearance.ts +275 -0
  354. package/registry/ui/config/nm-bar-overflow.ts +10 -0
  355. package/registry/ui/config/nm-button.ts +38 -0
  356. package/registry/ui/config/nm-chatbox-icons.ts +67 -0
  357. package/registry/ui/config/nm-chatbox.ts +42 -0
  358. package/registry/ui/config/nm-collection.ts +101 -0
  359. package/registry/ui/config/nm-composer.ts +39 -0
  360. package/registry/ui/config/nm-dropdown.ts +62 -0
  361. package/registry/ui/config/nm-field.ts +43 -0
  362. package/registry/ui/config/nm-icon-button.ts +35 -0
  363. package/registry/ui/config/nm-icons.ts +417 -0
  364. package/registry/ui/config/nm-list-item.ts +14 -0
  365. package/registry/ui/config/nm-message.ts +106 -0
  366. package/registry/ui/config/nm-modal.ts +76 -0
  367. package/registry/ui/config/nm-panel-bar.ts +11 -0
  368. package/registry/ui/config/nm-questionnaire.ts +53 -0
  369. package/registry/ui/config/nm-radius.ts +56 -0
  370. package/registry/ui/config/nm-rail-icons.ts +27 -0
  371. package/registry/ui/config/nm-segmented.ts +19 -0
  372. package/registry/ui/config/nm-side-panel.ts +16 -0
  373. package/registry/ui/config/nm-site-palette.ts +30 -0
  374. package/registry/ui/config/nm-small-icon-button.ts +17 -0
  375. package/registry/ui/config/nm-tabs.ts +9 -0
  376. package/registry/ui/config/nm-top-bar.ts +4 -0
  377. package/registry/ui/config/nordman-chrome.ts +14 -0
  378. package/registry/ui/config/nordman-login.ts +28 -0
  379. package/registry/ui/content/nm-modal.ts +5 -0
  380. package/registry/ui/content/nordman-login.ts +85 -0
  381. package/registry/ui/kit-logger.ts +1 -0
  382. package/registry/ui/lib/appearance/appearanceState.ts +240 -0
  383. package/registry/ui/lib/appearance/applyAppearance.ts +36 -0
  384. package/registry/ui/lib/appearance/cloudOrbAppearance.ts +36 -0
  385. package/registry/ui/lib/appearance/color.ts +96 -0
  386. package/registry/ui/lib/appearance/deriveTokens.ts +218 -0
  387. package/registry/ui/lib/appearance/index.ts +6 -0
  388. package/registry/ui/lib/appearance/markTokens.ts +49 -0
  389. package/registry/ui/lib/appearance/readLayoutMetrics.ts +28 -0
  390. package/registry/ui/lib/bar-overflow.ts +41 -0
  391. package/registry/ui/lib/logger.ts +53 -0
  392. package/registry/ui/lib/menu-motion.ts +187 -0
  393. package/registry/ui/lib/nm-class.ts +4 -0
  394. package/registry/ui/lib/nordman-ui-locale.ts +43 -0
  395. package/registry/ui/styles/interface-theme.css +196 -0
  396. package/registry/ui/styles/light-appearance.css +72 -0
  397. package/registry/ui/styles/tokens.css +424 -0
  398. package/registry/ui/styles/utilities.css +12 -0
@@ -0,0 +1,195 @@
1
+ .nm-login {
2
+ position: relative;
3
+ display: grid;
4
+ grid-template-columns: 1fr 1fr;
5
+ min-height: 100dvh;
6
+ overflow: clip;
7
+ background: var(--nm-canvas);
8
+ color: var(--nm-fg);
9
+ font-family: var(--nm-font);
10
+ }
11
+
12
+ .nm-login__visual {
13
+ display: grid;
14
+ place-items: center;
15
+ height: 100dvh;
16
+ min-height: 100dvh;
17
+ }
18
+
19
+ .nm-login .glow i,
20
+ .nm-login .glow.gl i {
21
+ background: var(--nm-canvas);
22
+ }
23
+
24
+ .nm-login__panel {
25
+ position: relative;
26
+ z-index: 1;
27
+ display: grid;
28
+ place-items: center;
29
+ padding: var(--nm-gap-block) var(--nm-page-x);
30
+ }
31
+
32
+ .nm-login__stack {
33
+ display: flex;
34
+ flex-direction: column;
35
+ gap: var(--nm-gap-block);
36
+ width: min(100%, var(--nm-login-form));
37
+ }
38
+
39
+ .nm-login__title {
40
+ margin: 0;
41
+ text-align: center;
42
+ font-size: var(--nm-type-section);
43
+ font-weight: var(--nm-weight-medium);
44
+ line-height: var(--nm-leading-tight);
45
+ }
46
+
47
+ .nm-login__error {
48
+ margin: 0;
49
+ color: var(--nm-fg);
50
+ border: var(--nm-rule) solid var(--nm-line-strong);
51
+ border-radius: var(--nm-control-r);
52
+ padding: var(--control-px);
53
+ font-size: var(--control-fs);
54
+ }
55
+
56
+ .nm-login__form {
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: var(--nm-gap-copy);
60
+ }
61
+
62
+ .nm-login__field {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: var(--field-label-gap);
66
+ }
67
+
68
+ .nm-login__label-row {
69
+ display: flex;
70
+ align-items: baseline;
71
+ justify-content: space-between;
72
+ gap: var(--nm-gap-copy);
73
+ }
74
+
75
+ .nm-login__label,
76
+ .nm-login__forgot,
77
+ .nm-login__switch {
78
+ margin: 0;
79
+ font-size: var(--field-label-fs);
80
+ color: var(--nm-fg-subtle);
81
+ }
82
+
83
+ .nm-login__control-wrap {
84
+ position: relative;
85
+ }
86
+
87
+ .nm-login__control {
88
+ box-sizing: border-box;
89
+ width: 100%;
90
+ height: var(--nm-field-h);
91
+ padding: 0 var(--control-px);
92
+ border: var(--nm-rule) solid var(--nm-line-strong);
93
+ border-radius: var(--nm-control-r);
94
+ background: var(--nm-raised);
95
+ color: var(--nm-fg);
96
+ font: inherit;
97
+ font-size: var(--control-fs);
98
+ }
99
+
100
+ .nm-login__control:focus {
101
+ border-color: var(--nm-stroke);
102
+ outline: none;
103
+ }
104
+
105
+ .nm-login__control--secret {
106
+ padding-inline-end: var(--nm-login-reveal);
107
+ }
108
+
109
+ .nm-login__reveal {
110
+ position: absolute;
111
+ inset-block: 0;
112
+ inset-inline-end: 0;
113
+ display: grid;
114
+ place-items: center;
115
+ width: var(--nm-login-reveal);
116
+ padding: 0;
117
+ border: 0;
118
+ background: none;
119
+ color: var(--nm-fg-muted);
120
+ cursor: pointer;
121
+ }
122
+
123
+ .nm-login__reveal-icon {
124
+ width: var(--nm-icon-button);
125
+ height: var(--nm-icon-button);
126
+ }
127
+
128
+ .nm-login__notice {
129
+ margin: 0;
130
+ color: var(--nm-fg-muted);
131
+ font-size: var(--nm-type-spec);
132
+ text-align: center;
133
+ }
134
+
135
+ .nm-login__control::placeholder {
136
+ color: var(--nm-stroke);
137
+ }
138
+
139
+ .nm-login__submit {
140
+ margin-top: var(--nm-gap-copy);
141
+ }
142
+
143
+ .nm-login__switch {
144
+ text-align: center;
145
+ }
146
+
147
+ .nm-login__forgot,
148
+ .nm-login__switch-action {
149
+ padding: 0;
150
+ border: 0;
151
+ background: none;
152
+ color: var(--nm-fg);
153
+ font: inherit;
154
+ text-decoration: underline;
155
+ cursor: pointer;
156
+ }
157
+
158
+ .nm-login__skip {
159
+ position: absolute;
160
+ left: var(--nm-page-x);
161
+ top: -4rem;
162
+ z-index: 20;
163
+ padding: var(--nm-pad-cta-y) var(--nm-pad-cta-x);
164
+ background: var(--nm-fg);
165
+ color: var(--nm-canvas);
166
+ }
167
+
168
+ .nm-login__skip:focus {
169
+ top: var(--nm-rail);
170
+ }
171
+
172
+ @media (max-width: 48rem) {
173
+ .nm-login {
174
+ grid-template-columns: 1fr;
175
+ }
176
+
177
+ .nm-login__visual {
178
+ height: 40dvh;
179
+ min-height: var(--nm-login-visual-mobile);
180
+ }
181
+ }
182
+
183
+ .nm-login--google-only .nm-login__stack {
184
+ gap: 5rem;
185
+ }
186
+
187
+ .nm-login--google-only .nm-login__title {
188
+ font-size: 2rem;
189
+ font-weight: var(--nm-weight-medium);
190
+ color: var(--nm-fg);
191
+ }
192
+
193
+ .nm-login__google-wrap {
194
+ width: 100%;
195
+ }
@@ -0,0 +1,136 @@
1
+ import { useEffect, type ReactNode } from 'react';
2
+ import {
3
+ NORDMAN_LOGIN_FORM_ID,
4
+ NORDMAN_LOGIN_INTERFACE,
5
+ NORDMAN_LOGIN_VIEWS,
6
+ type NordmanLoginView,
7
+ } from '../../config/nordman-login.ts';
8
+ import { NordmanLoginRegister } from '../nordman-login-register/nordman-login-register.tsx';
9
+ import { NordmanLoginSignIn } from '../nordman-login-sign-in/nordman-login-sign-in.tsx';
10
+ import { NordmanLoginForgot } from '../nordman-login-forgot/nordman-login-forgot.tsx';
11
+ import { NordmanLoginGoogle } from '../nordman-login-google/nordman-login-google.tsx';
12
+ import { NordmanLoginReset } from '../nordman-login-reset/nordman-login-reset.tsx';
13
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
14
+ import { NordmanLoginHero, type NordmanLoginShape } from '../nordman-login-hero/nordman-login-hero.tsx';
15
+
16
+ export type NordmanLoginProps = {
17
+ title: string;
18
+ view: NordmanLoginView;
19
+ error: string | null;
20
+ notice: string | null;
21
+ pending: boolean;
22
+ sent: boolean;
23
+ passwordMin: number;
24
+ onView: (view: NordmanLoginView) => void;
25
+ onSignIn: (input: { username: string; password: string }) => void;
26
+ onRegister: (input: { username: string; displayName: string; password: string }) => void;
27
+ onRequestReset: (input: { identifier: string }) => void;
28
+ onResetPassword: (input: { password: string }) => void;
29
+ children?: ReactNode;
30
+ hideSwitch?: boolean;
31
+ after?: ReactNode;
32
+ shape: NordmanLoginShape;
33
+ /** Google-only sign-in via Supabase Auth (hides email/password UI). */
34
+ googleOnly?: boolean;
35
+ onContinueWithGoogle?: () => void;
36
+ };
37
+
38
+ function loginBody(props: NordmanLoginProps): ReactNode {
39
+ if (props.view === NORDMAN_LOGIN_VIEWS.register) {
40
+ return (
41
+ <NordmanLoginRegister
42
+ pending={props.pending}
43
+ passwordMin={props.passwordMin}
44
+ onRegister={props.onRegister}
45
+ />
46
+ );
47
+ }
48
+ if (props.view === NORDMAN_LOGIN_VIEWS.forgot) {
49
+ return (
50
+ <NordmanLoginForgot
51
+ pending={props.pending}
52
+ sent={props.sent}
53
+ onRequestReset={props.onRequestReset}
54
+ />
55
+ );
56
+ }
57
+ if (props.view === NORDMAN_LOGIN_VIEWS.reset) {
58
+ return (
59
+ <NordmanLoginReset
60
+ pending={props.pending}
61
+ passwordMin={props.passwordMin}
62
+ onResetPassword={props.onResetPassword}
63
+ />
64
+ );
65
+ }
66
+ if (props.googleOnly) {
67
+ return (
68
+ <NordmanLoginGoogle
69
+ pending={props.pending}
70
+ onContinueWithGoogle={() => props.onContinueWithGoogle?.()}
71
+ />
72
+ );
73
+ }
74
+ return (
75
+ <NordmanLoginSignIn
76
+ pending={props.pending}
77
+ passwordMin={props.passwordMin}
78
+ onForgot={() => props.onView(NORDMAN_LOGIN_VIEWS.forgot)}
79
+ onSignIn={props.onSignIn}
80
+ />
81
+ );
82
+ }
83
+
84
+ export function NordmanLogin(props: NordmanLoginProps): ReactNode {
85
+ const register = props.view === NORDMAN_LOGIN_VIEWS.register;
86
+ const signIn = props.view === NORDMAN_LOGIN_VIEWS.signIn;
87
+
88
+ useEffect(() => {
89
+ document.documentElement.dataset.interface = NORDMAN_LOGIN_INTERFACE;
90
+ }, []);
91
+
92
+ return (
93
+ <div
94
+ className={props.googleOnly ? 'nm-login nm-login--google-only' : 'nm-login'}
95
+ data-testid="nordman-login"
96
+ >
97
+ <a className="nm-login__skip" href={`#${NORDMAN_LOGIN_FORM_ID}`}>
98
+ {nordmanLoginCopy.skip}
99
+ </a>
100
+ <div className="nm-login__visual">
101
+ <NordmanLoginHero shape={props.shape} />
102
+ </div>
103
+ <section className="nm-login__panel">
104
+ <div className="nm-login__stack">
105
+ <h1 className="nm-login__title">{props.title}</h1>
106
+ {props.error ? (
107
+ <p className="nm-login__error" role="alert">
108
+ {props.error}
109
+ </p>
110
+ ) : null}
111
+ {props.notice && props.view !== NORDMAN_LOGIN_VIEWS.forgot ? (
112
+ <p className="nm-login__notice">{props.notice}</p>
113
+ ) : null}
114
+ {props.children ?? loginBody(props)}
115
+ {props.after}
116
+ {props.children == null && props.hideSwitch !== true && !props.googleOnly ? (
117
+ <p className="nm-login__switch">
118
+ {signIn ? nordmanLoginCopy.registerPrompt : nordmanLoginCopy.signInPrompt}{' '}
119
+ <button
120
+ className="nm-login__switch-action"
121
+ type="button"
122
+ onClick={() =>
123
+ props.onView(
124
+ register || !signIn ? NORDMAN_LOGIN_VIEWS.signIn : NORDMAN_LOGIN_VIEWS.register,
125
+ )
126
+ }
127
+ >
128
+ {signIn ? nordmanLoginCopy.registerAction : nordmanLoginCopy.signInAction}
129
+ </button>
130
+ </p>
131
+ ) : null}
132
+ </div>
133
+ </section>
134
+ </div>
135
+ );
136
+ }
@@ -0,0 +1,55 @@
1
+ import { useState, type ReactNode } from 'react';
2
+ import { NordmanLoginReveal } from '../nordman-login-reveal/nordman-login-reveal.tsx';
3
+
4
+ export type NordmanLoginFieldProps = {
5
+ id: string;
6
+ name: string;
7
+ label: string;
8
+ type: 'text' | 'email' | 'password';
9
+ autoComplete: string;
10
+ placeholder?: string;
11
+ minLength?: number;
12
+ required?: boolean;
13
+ accessory?: ReactNode;
14
+ };
15
+
16
+ export function NordmanLoginField(props: NordmanLoginFieldProps): ReactNode {
17
+ const secret = props.type === 'password';
18
+ const [revealed, setRevealed] = useState(false);
19
+ const inputType = secret && revealed ? 'text' : props.type;
20
+
21
+ const control = (
22
+ <input
23
+ className={secret ? 'nm-login__control nm-login__control--secret' : 'nm-login__control'}
24
+ id={props.id}
25
+ name={props.name}
26
+ type={inputType}
27
+ autoComplete={props.autoComplete}
28
+ placeholder={props.placeholder}
29
+ minLength={props.minLength}
30
+ required={props.required}
31
+ />
32
+ );
33
+
34
+ return (
35
+ <div className="nm-login__field">
36
+ <div className="nm-login__label-row">
37
+ <label className="nm-login__label" htmlFor={props.id}>
38
+ {props.label}
39
+ </label>
40
+ {props.accessory}
41
+ </div>
42
+ {secret ? (
43
+ <div className="nm-login__control-wrap">
44
+ {control}
45
+ <NordmanLoginReveal
46
+ revealed={revealed}
47
+ onToggle={() => setRevealed((current) => !current)}
48
+ />
49
+ </div>
50
+ ) : (
51
+ control
52
+ )}
53
+ </div>
54
+ );
55
+ }
@@ -0,0 +1,56 @@
1
+ import { type FormEvent, type ReactNode } from 'react';
2
+ import { NORDMAN_LOGIN_FIELDS, NORDMAN_LOGIN_FORM_ID } from '../../config/nordman-login.ts';
3
+ import { NordmanLoginField } from '../nordman-login-field/nordman-login-field.tsx';
4
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
5
+ import { createLogger } from '../../kit-logger.ts';
6
+ import { NmButton } from '../nm-button/nm-button.tsx';
7
+
8
+ const logger = createLogger('interface-nordman-login-forgot');
9
+
10
+ export type NordmanLoginForgotProps = {
11
+ pending: boolean;
12
+ sent: boolean;
13
+ onRequestReset: (input: { identifier: string }) => void;
14
+ };
15
+
16
+ export function NordmanLoginForgot(props: NordmanLoginForgotProps): ReactNode {
17
+ function onSubmit(event: FormEvent<HTMLFormElement>): void {
18
+ event.preventDefault();
19
+ const data = new FormData(event.currentTarget);
20
+ const identifier = String(data.get(NORDMAN_LOGIN_FIELDS.username) ?? '');
21
+ logger.debug('submit', 'start');
22
+ props.onRequestReset({ identifier });
23
+ }
24
+
25
+ if (props.sent) {
26
+ return (
27
+ <p className="nm-login__notice" data-testid="forgot-sent">
28
+ {nordmanLoginCopy.forgotSent}
29
+ </p>
30
+ );
31
+ }
32
+
33
+ return (
34
+ <form className="nm-login__form" id={NORDMAN_LOGIN_FORM_ID} onSubmit={onSubmit}>
35
+ <NordmanLoginField
36
+ id={NORDMAN_LOGIN_FIELDS.username}
37
+ name={NORDMAN_LOGIN_FIELDS.username}
38
+ label={nordmanLoginCopy.identifier}
39
+ type="text"
40
+ autoComplete="username"
41
+ placeholder={nordmanLoginCopy.identifierPlaceholder}
42
+ />
43
+ <div className="nm-login__submit">
44
+ <NmButton
45
+ label={props.pending ? nordmanLoginCopy.forgotPending : nordmanLoginCopy.forgotSubmit}
46
+ tone="filled"
47
+ size="large"
48
+ block
49
+ type="submit"
50
+ disabled={props.pending}
51
+ testId="cta-forgot-submit"
52
+ />
53
+ </div>
54
+ </form>
55
+ );
56
+ }
@@ -0,0 +1,28 @@
1
+ import { type ReactNode } from 'react';
2
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
3
+ import { useNordmanUiLocale } from '../../lib/nordman-ui-locale.ts';
4
+ import { NmButton } from '../nm-button/nm-button.tsx';
5
+
6
+ export type NordmanLoginGoogleProps = {
7
+ pending: boolean;
8
+ onContinueWithGoogle: () => void;
9
+ };
10
+
11
+ export function NordmanLoginGoogle(props: NordmanLoginGoogleProps): ReactNode {
12
+ useNordmanUiLocale();
13
+
14
+ return (
15
+ <div className="nm-login__google-wrap">
16
+ <NmButton
17
+ label={props.pending ? nordmanLoginCopy.googlePending : nordmanLoginCopy.continueWithGoogle}
18
+ tone="filled"
19
+ size="large"
20
+ block
21
+ icon="google"
22
+ disabled={props.pending}
23
+ testId="cta-continue-google"
24
+ onClick={props.onContinueWithGoogle}
25
+ />
26
+ </div>
27
+ );
28
+ }
@@ -0,0 +1,38 @@
1
+ import { useEffect, useRef, type ReactNode } from 'react';
2
+
3
+ export type NordmanLoginShape = 'square' | 'triangle' | 'circle';
4
+
5
+ const GLOW_CLASS: Record<NordmanLoginShape, string> = {
6
+ square: 'glow',
7
+ triangle: 'glow tri',
8
+ circle: 'glow circle',
9
+ };
10
+
11
+ type NordmanUiHero = {
12
+ mountHero: (glow: HTMLElement, options: { shape: NordmanLoginShape; signal: AbortSignal }) => void;
13
+ };
14
+
15
+ /** The website hero. The app loads `nordman-ui.js` and `hero.css`, which live beside `site.css`. */
16
+ export function NordmanLoginHero(props: { shape: NordmanLoginShape }): ReactNode {
17
+ const glowRef = useRef<HTMLDivElement>(null);
18
+
19
+ useEffect(() => {
20
+ const ui = (window as unknown as { NordmanUI?: NordmanUiHero }).NordmanUI;
21
+ if (glowRef.current == null || ui == null) {
22
+ return;
23
+ }
24
+ const controller = new AbortController();
25
+ ui.mountHero(glowRef.current, { shape: props.shape, signal: controller.signal });
26
+ return () => controller.abort();
27
+ }, [props.shape]);
28
+
29
+ return (
30
+ <div
31
+ ref={glowRef}
32
+ className={GLOW_CLASS[props.shape]}
33
+ aria-hidden="true"
34
+ >
35
+ <i></i>
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1,70 @@
1
+ import { type FormEvent, type ReactNode } from 'react';
2
+ import { NORDMAN_LOGIN_FIELDS, NORDMAN_LOGIN_FORM_ID } from '../../config/nordman-login.ts';
3
+ import { NordmanLoginField } from '../nordman-login-field/nordman-login-field.tsx';
4
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
5
+ import { createLogger } from '../../kit-logger.ts';
6
+ import { NmButton } from '../nm-button/nm-button.tsx';
7
+
8
+ const logger = createLogger('interface-nordman-login-register');
9
+
10
+ export type NordmanLoginRegisterProps = {
11
+ pending: boolean;
12
+ passwordMin: number;
13
+ onRegister: (input: { username: string; displayName: string; password: string }) => void;
14
+ };
15
+
16
+ export function NordmanLoginRegister(props: NordmanLoginRegisterProps): ReactNode {
17
+ function onSubmit(event: FormEvent<HTMLFormElement>): void {
18
+ event.preventDefault();
19
+ const data = new FormData(event.currentTarget);
20
+ logger.debug('submit', 'start');
21
+ props.onRegister({
22
+ username: String(data.get(NORDMAN_LOGIN_FIELDS.registerUsername) ?? ''),
23
+ displayName: String(data.get(NORDMAN_LOGIN_FIELDS.displayName) ?? ''),
24
+ password: String(data.get(NORDMAN_LOGIN_FIELDS.registerPassword) ?? ''),
25
+ });
26
+ }
27
+
28
+ return (
29
+ <form className="nm-login__form" id={NORDMAN_LOGIN_FORM_ID} onSubmit={onSubmit}>
30
+ <NordmanLoginField
31
+ id={NORDMAN_LOGIN_FIELDS.registerUsername}
32
+ name={NORDMAN_LOGIN_FIELDS.registerUsername}
33
+ label={nordmanLoginCopy.identifier}
34
+ type="email"
35
+ autoComplete="email"
36
+ placeholder={nordmanLoginCopy.identifierPlaceholder}
37
+ required
38
+ />
39
+ <NordmanLoginField
40
+ id={NORDMAN_LOGIN_FIELDS.displayName}
41
+ name={NORDMAN_LOGIN_FIELDS.displayName}
42
+ label={nordmanLoginCopy.displayName}
43
+ type="text"
44
+ autoComplete="name"
45
+ minLength={3}
46
+ required
47
+ />
48
+ <NordmanLoginField
49
+ id={NORDMAN_LOGIN_FIELDS.registerPassword}
50
+ name={NORDMAN_LOGIN_FIELDS.registerPassword}
51
+ label={nordmanLoginCopy.password}
52
+ type="password"
53
+ autoComplete="new-password"
54
+ minLength={props.passwordMin}
55
+ required
56
+ />
57
+ <div className="nm-login__submit">
58
+ <NmButton
59
+ label={props.pending ? nordmanLoginCopy.registerPending : nordmanLoginCopy.registerSubmit}
60
+ tone="filled"
61
+ size="large"
62
+ block
63
+ type="submit"
64
+ disabled={props.pending}
65
+ testId="cta-register"
66
+ />
67
+ </div>
68
+ </form>
69
+ );
70
+ }
@@ -0,0 +1,71 @@
1
+ import { useState, type FormEvent, type ReactNode } from 'react';
2
+ import { NORDMAN_LOGIN_FIELDS, NORDMAN_LOGIN_FORM_ID } from '../../config/nordman-login.ts';
3
+ import { NordmanLoginField } from '../nordman-login-field/nordman-login-field.tsx';
4
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
5
+ import { createLogger } from '../../kit-logger.ts';
6
+ import { NmButton } from '../nm-button/nm-button.tsx';
7
+
8
+ const logger = createLogger('interface-nordman-login-reset');
9
+
10
+ export type NordmanLoginResetProps = {
11
+ pending: boolean;
12
+ passwordMin: number;
13
+ onResetPassword: (input: { password: string }) => void;
14
+ };
15
+
16
+ export function NordmanLoginReset(props: NordmanLoginResetProps): ReactNode {
17
+ const [mismatch, setMismatch] = useState(false);
18
+
19
+ function onSubmit(event: FormEvent<HTMLFormElement>): void {
20
+ event.preventDefault();
21
+ const data = new FormData(event.currentTarget);
22
+ const password = String(data.get(NORDMAN_LOGIN_FIELDS.resetPassword) ?? '');
23
+ const confirm = String(data.get(NORDMAN_LOGIN_FIELDS.confirmPassword) ?? '');
24
+ if (password !== confirm) {
25
+ logger.warn('submit', 'mismatch');
26
+ setMismatch(true);
27
+ return;
28
+ }
29
+ setMismatch(false);
30
+ logger.debug('submit', 'start');
31
+ props.onResetPassword({ password });
32
+ }
33
+
34
+ return (
35
+ <form className="nm-login__form" id={NORDMAN_LOGIN_FORM_ID} onSubmit={onSubmit}>
36
+ {mismatch ? (
37
+ <p className="nm-login__error" role="alert">
38
+ {nordmanLoginCopy.mismatch}
39
+ </p>
40
+ ) : null}
41
+ <NordmanLoginField
42
+ id={NORDMAN_LOGIN_FIELDS.resetPassword}
43
+ name={NORDMAN_LOGIN_FIELDS.resetPassword}
44
+ label={nordmanLoginCopy.password}
45
+ type="password"
46
+ autoComplete="new-password"
47
+ placeholder={nordmanLoginCopy.passwordPlaceholder}
48
+ minLength={props.passwordMin}
49
+ />
50
+ <NordmanLoginField
51
+ id={NORDMAN_LOGIN_FIELDS.confirmPassword}
52
+ name={NORDMAN_LOGIN_FIELDS.confirmPassword}
53
+ label={nordmanLoginCopy.confirmPassword}
54
+ type="password"
55
+ autoComplete="new-password"
56
+ minLength={props.passwordMin}
57
+ />
58
+ <div className="nm-login__submit">
59
+ <NmButton
60
+ label={props.pending ? nordmanLoginCopy.resetPending : nordmanLoginCopy.resetSubmit}
61
+ tone="filled"
62
+ size="large"
63
+ block
64
+ type="submit"
65
+ disabled={props.pending}
66
+ testId="cta-reset-password"
67
+ />
68
+ </div>
69
+ </form>
70
+ );
71
+ }
@@ -0,0 +1,41 @@
1
+ import type { ReactNode } from 'react';
2
+ import { NORDMAN_LOGIN_REVEAL } from '../../config/nordman-login.ts';
3
+ import { nordmanLoginCopy } from '../../content/nordman-login.ts';
4
+ import { createLogger } from '../../kit-logger.ts';
5
+
6
+ const logger = createLogger('interface-nordman-login-reveal');
7
+
8
+ export type NordmanLoginRevealProps = {
9
+ revealed: boolean;
10
+ onToggle: () => void;
11
+ };
12
+
13
+ export function NordmanLoginReveal(props: NordmanLoginRevealProps): ReactNode {
14
+ const label = props.revealed ? nordmanLoginCopy.hidePassword : nordmanLoginCopy.showPassword;
15
+
16
+ return (
17
+ <button
18
+ className="nm-login__reveal"
19
+ type="button"
20
+ aria-label={label}
21
+ aria-pressed={props.revealed}
22
+ data-testid="cta-reveal-password"
23
+ onClick={() => {
24
+ logger.debug('toggle', props.revealed ? 'hide' : 'show');
25
+ props.onToggle();
26
+ }}
27
+ >
28
+ <svg
29
+ className="nm-login__reveal-icon"
30
+ viewBox={NORDMAN_LOGIN_REVEAL.viewBox}
31
+ aria-hidden="true"
32
+ focusable="false"
33
+ >
34
+ <path
35
+ d={props.revealed ? NORDMAN_LOGIN_REVEAL.hide : NORDMAN_LOGIN_REVEAL.show}
36
+ fill="currentColor"
37
+ />
38
+ </svg>
39
+ </button>
40
+ );
41
+ }