@nordmanai/nif 0.2.2 → 0.2.3
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.
- package/README.md +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +31342 -11760
- package/dist/styles.css +1 -1
- package/dist/ui/components/nm-ai/nm-ai.d.ts +4 -0
- package/dist/ui/components/nm-alert/nm-alert.d.ts +13 -0
- package/dist/ui/components/nm-button/nm-button.d.ts +4 -2
- package/dist/ui/components/nm-checkbox/nm-checkbox.d.ts +1 -1
- package/dist/ui/components/nm-chip/nm-chip.d.ts +5 -2
- package/dist/ui/components/nm-collapsible/nm-collapsible.d.ts +6 -0
- package/dist/ui/components/nm-combobox/nm-combobox.d.ts +1 -1
- package/dist/ui/components/nm-command/nm-command.d.ts +8 -1
- package/dist/ui/components/nm-composer/nm-composer.d.ts +47 -4
- package/dist/ui/components/nm-context-menu/nm-context-menu.d.ts +1 -1
- package/dist/ui/components/nm-dialog/nm-dialog.d.ts +1 -1
- package/dist/ui/components/nm-dropdown/nm-dropdown.d.ts +1 -1
- package/dist/ui/components/nm-dropdown-menu/nm-dropdown-menu.d.ts +11 -2
- package/dist/ui/components/nm-hover-card/nm-hover-card.d.ts +1 -1
- package/dist/ui/components/nm-icon/animated/activity.d.ts +72 -0
- package/dist/ui/components/nm-icon/animated/archive.d.ts +31 -0
- package/dist/ui/components/nm-icon/animated/arrow-down.d.ts +128 -0
- package/dist/ui/components/nm-icon/animated/arrow-left.d.ts +128 -0
- package/dist/ui/components/nm-icon/animated/arrow-right.d.ts +128 -0
- package/dist/ui/components/nm-icon/animated/arrow-up-down.d.ts +119 -0
- package/dist/ui/components/nm-icon/animated/arrow-up.d.ts +128 -0
- package/dist/ui/components/nm-icon/animated/audio-lines.d.ts +99 -0
- package/dist/ui/components/nm-icon/animated/bookmark-plus.d.ts +35 -0
- package/dist/ui/components/nm-icon/animated/bookmark.d.ts +52 -0
- package/dist/ui/components/nm-icon/animated/bot.d.ts +90 -0
- package/dist/ui/components/nm-icon/animated/calendar-days.d.ts +87 -0
- package/dist/ui/components/nm-icon/animated/calendar.d.ts +36 -0
- package/dist/ui/components/nm-icon/animated/camera.d.ts +50 -0
- package/dist/ui/components/nm-icon/animated/chart-column-increasing.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/chart-column.d.ts +86 -0
- package/dist/ui/components/nm-icon/animated/chart-line.d.ts +51 -0
- package/dist/ui/components/nm-icon/animated/check-check.d.ts +50 -0
- package/dist/ui/components/nm-icon/animated/check.d.ts +25 -0
- package/dist/ui/components/nm-icon/animated/chevron-down.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/chevron-left.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/chevron-right.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/chevron-up.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/circle-alert.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/circle-check-big.d.ts +26 -0
- package/dist/ui/components/nm-icon/animated/circle-check.d.ts +26 -0
- package/dist/ui/components/nm-icon/animated/circle-plus.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/circle-question-mark.d.ts +22 -0
- package/dist/ui/components/nm-icon/animated/circle-x.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/clock-3.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/clock-4.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/clock.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/cloud-sun.d.ts +9 -0
- package/dist/ui/components/nm-icon/animated/cloud-upload.d.ts +45 -0
- package/dist/ui/components/nm-icon/animated/copy.d.ts +135 -0
- package/dist/ui/components/nm-icon/animated/download.d.ts +45 -0
- package/dist/ui/components/nm-icon/animated/ellipsis.d.ts +141 -0
- package/dist/ui/components/nm-icon/animated/external-link.d.ts +49 -0
- package/dist/ui/components/nm-icon/animated/eye-off.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/eye.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/fast-forward.d.ts +34 -0
- package/dist/ui/components/nm-icon/animated/file-clock.d.ts +48 -0
- package/dist/ui/components/nm-icon/animated/file-text.d.ts +56 -0
- package/dist/ui/components/nm-icon/animated/file.d.ts +67 -0
- package/dist/ui/components/nm-icon/animated/folder.d.ts +92 -0
- package/dist/ui/components/nm-icon/animated/gauge.d.ts +47 -0
- package/dist/ui/components/nm-icon/animated/globe.d.ts +21 -0
- package/dist/ui/components/nm-icon/animated/graduation-cap.d.ts +41 -0
- package/dist/ui/components/nm-icon/animated/headphones.d.ts +50 -0
- package/dist/ui/components/nm-icon/animated/image.d.ts +40 -0
- package/dist/ui/components/nm-icon/animated/index.d.ts +2 -0
- package/dist/ui/components/nm-icon/animated/info.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/key-round.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/layers.d.ts +61 -0
- package/dist/ui/components/nm-icon/animated/layout-dashboard.d.ts +131 -0
- package/dist/ui/components/nm-icon/animated/library-big.d.ts +29 -0
- package/dist/ui/components/nm-icon/animated/lightbulb.d.ts +51 -0
- package/dist/ui/components/nm-icon/animated/link.d.ts +193 -0
- package/dist/ui/components/nm-icon/animated/list-filter.d.ts +13 -0
- package/dist/ui/components/nm-icon/animated/list.d.ts +111 -0
- package/dist/ui/components/nm-icon/animated/loader-circle.d.ts +24 -0
- package/dist/ui/components/nm-icon/animated/lock.d.ts +94 -0
- package/dist/ui/components/nm-icon/animated/log-out.d.ts +45 -0
- package/dist/ui/components/nm-icon/animated/mail.d.ts +100 -0
- package/dist/ui/components/nm-icon/animated/map-pin.d.ts +67 -0
- package/dist/ui/components/nm-icon/animated/menu.d.ts +57 -0
- package/dist/ui/components/nm-icon/animated/message-circle-dashed.d.ts +34 -0
- package/dist/ui/components/nm-icon/animated/message-circle.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/message-square-plus.d.ts +49 -0
- package/dist/ui/components/nm-icon/animated/message-square-text.d.ts +104 -0
- package/dist/ui/components/nm-icon/animated/message-square.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/mic-off.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/mic.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/minimize.d.ts +139 -0
- package/dist/ui/components/nm-icon/animated/minus.d.ts +54 -0
- package/dist/ui/components/nm-icon/animated/moon.d.ts +62 -0
- package/dist/ui/components/nm-icon/animated/music.d.ts +22 -0
- package/dist/ui/components/nm-icon/animated/notebook-pen.d.ts +41 -0
- package/dist/ui/components/nm-icon/animated/panel-left.d.ts +29 -0
- package/dist/ui/components/nm-icon/animated/panel-right.d.ts +29 -0
- package/dist/ui/components/nm-icon/animated/paperclip.d.ts +49 -0
- package/dist/ui/components/nm-icon/animated/pause.d.ts +59 -0
- package/dist/ui/components/nm-icon/animated/pencil.d.ts +25 -0
- package/dist/ui/components/nm-icon/animated/pin-off.d.ts +44 -0
- package/dist/ui/components/nm-icon/animated/pin.d.ts +85 -0
- package/dist/ui/components/nm-icon/animated/plane-takeoff.d.ts +25 -0
- package/dist/ui/components/nm-icon/animated/play.d.ts +43 -0
- package/dist/ui/components/nm-icon/animated/plug-zap.d.ts +49 -0
- package/dist/ui/components/nm-icon/animated/plus.d.ts +95 -0
- package/dist/ui/components/nm-icon/animated/radio.d.ts +24 -0
- package/dist/ui/components/nm-icon/animated/refresh-cw.d.ts +55 -0
- package/dist/ui/components/nm-icon/animated/rocket.d.ts +48 -0
- package/dist/ui/components/nm-icon/animated/rotate-ccw.d.ts +51 -0
- package/dist/ui/components/nm-icon/animated/rotate-cw.d.ts +71 -0
- package/dist/ui/components/nm-icon/animated/save.d.ts +21 -0
- package/dist/ui/components/nm-icon/animated/search.d.ts +42 -0
- package/dist/ui/components/nm-icon/animated/send.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/settings.d.ts +39 -0
- package/dist/ui/components/nm-icon/animated/share-2.d.ts +122 -0
- package/dist/ui/components/nm-icon/animated/share.d.ts +40 -0
- package/dist/ui/components/nm-icon/animated/shield-check.d.ts +36 -0
- package/dist/ui/components/nm-icon/animated/shopping-bag.d.ts +35 -0
- package/dist/ui/components/nm-icon/animated/sliders-horizontal.d.ts +239 -0
- package/dist/ui/components/nm-icon/animated/sparkles.d.ts +205 -0
- package/dist/ui/components/nm-icon/animated/star.d.ts +48 -0
- package/dist/ui/components/nm-icon/animated/sun.d.ts +9 -0
- package/dist/ui/components/nm-icon/animated/terminal.d.ts +22 -0
- package/dist/ui/components/nm-icon/animated/trash-2.d.ts +61 -0
- package/dist/ui/components/nm-icon/animated/trash.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/trending-up.d.ts +40 -0
- package/dist/ui/components/nm-icon/animated/triangle-alert.d.ts +37 -0
- package/dist/ui/components/nm-icon/animated/trophy.d.ts +23 -0
- package/dist/ui/components/nm-icon/animated/type.d.ts +57 -0
- package/dist/ui/components/nm-icon/animated/upload.d.ts +49 -0
- package/dist/ui/components/nm-icon/animated/user-round.d.ts +33 -0
- package/dist/ui/components/nm-icon/animated/user.d.ts +33 -0
- package/dist/ui/components/nm-icon/animated/users-round.d.ts +93 -0
- package/dist/ui/components/nm-icon/animated/users.d.ts +93 -0
- package/dist/ui/components/nm-icon/animated/volume-2.d.ts +10 -0
- package/dist/ui/components/nm-icon/animated/wand-sparkles.d.ts +71 -0
- package/dist/ui/components/nm-icon/animated/x.d.ts +95 -0
- package/dist/ui/components/nm-icon/animated/zap.d.ts +65 -0
- package/dist/ui/components/nm-icon/animated/zoom-in.d.ts +35 -0
- package/dist/ui/components/nm-icon/animated/zoom-out.d.ts +53 -0
- package/dist/ui/components/nm-icon/nm-icon.d.ts +6 -3
- package/dist/ui/components/nm-icon/nm-lucide-extended.d.ts +3 -0
- package/dist/ui/components/nm-icon/nm-lucide.d.ts +7 -3
- package/dist/ui/components/nm-menubar/nm-menubar.d.ts +2 -2
- package/dist/ui/components/nm-panel/nm-panel.d.ts +5 -1
- package/dist/ui/components/nm-popover/nm-popover.d.ts +2 -2
- package/dist/ui/components/nm-progress/nm-progress.d.ts +1 -1
- package/dist/ui/components/nm-radio-group/nm-radio-group.d.ts +2 -2
- package/dist/ui/components/nm-select/nm-select.d.ts +1 -1
- package/dist/ui/components/nm-skeleton/nm-skeleton.d.ts +3 -0
- package/dist/ui/components/nm-slider/nm-slider.d.ts +1 -1
- package/dist/ui/components/nm-small-icon-button/nm-small-icon-button.d.ts +3 -3
- package/dist/ui/components/nm-spinner/nm-spinner.d.ts +3 -0
- package/dist/ui/components/nm-switch/nm-switch.d.ts +1 -1
- package/dist/ui/components/nm-tabs/nm-tabs.d.ts +6 -0
- package/dist/ui/components/nm-toggle/nm-toggle.d.ts +1 -1
- package/dist/ui/components/nm-tooltip/nm-tooltip.d.ts +1 -1
- package/dist/ui/components/nm-voice-orb/nm-voice-orb.d.ts +18 -0
- package/dist/ui/components/nm-voice-orb/use-nm-voice-orb-theme.d.ts +2 -0
- package/dist/ui/config/nm-app-panel.d.ts +2 -0
- package/dist/ui/config/nm-button.d.ts +6 -0
- package/dist/ui/config/nm-composer.d.ts +11 -0
- package/dist/ui/config/nm-icons-extended.d.ts +1 -0
- package/dist/ui/config/nm-icons.d.ts +4 -1
- package/dist/ui/config/nm-voice-orb.d.ts +22 -0
- package/dist/ui/lib/nm-motion.d.ts +29 -0
- package/package.json +12 -8
- package/registry/index.json +5099 -71
- package/registry/ui/components/nm-ai/nm-ai.tsx +7 -4
- package/registry/ui/components/nm-alert/nm-alert.css +85 -0
- package/registry/ui/components/nm-alert/nm-alert.tsx +35 -0
- package/registry/ui/components/nm-button/nm-button.css +24 -0
- package/registry/ui/components/nm-button/nm-button.tsx +25 -11
- package/registry/ui/components/nm-checkbox/nm-checkbox.tsx +1 -1
- package/registry/ui/components/nm-chip/nm-chip.css +25 -0
- package/registry/ui/components/nm-chip/nm-chip.tsx +9 -3
- package/registry/ui/components/nm-collapsible/nm-collapsible.css +3 -0
- package/registry/ui/components/nm-collapsible/nm-collapsible.tsx +16 -0
- package/registry/ui/components/nm-combobox/nm-combobox.tsx +1 -1
- package/registry/ui/components/nm-command/nm-command.css +48 -0
- package/registry/ui/components/nm-command/nm-command.tsx +19 -5
- package/registry/ui/components/nm-composer/nm-composer.css +87 -3
- package/registry/ui/components/nm-composer/nm-composer.tsx +321 -33
- package/registry/ui/components/nm-context-menu/nm-context-menu.tsx +1 -1
- package/registry/ui/components/nm-dialog/nm-dialog.css +5 -6
- package/registry/ui/components/nm-dialog/nm-dialog.tsx +1 -1
- package/registry/ui/components/nm-dropdown/nm-dropdown.css +5 -0
- package/registry/ui/components/nm-dropdown/nm-dropdown.tsx +28 -249
- package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.css +8 -0
- package/registry/ui/components/nm-dropdown-menu/nm-dropdown-menu.tsx +85 -6
- package/registry/ui/components/nm-hover-card/nm-hover-card.tsx +1 -1
- package/registry/ui/components/nm-icon/animated/activity.tsx +109 -0
- package/registry/ui/components/nm-icon/animated/archive.tsx +85 -0
- package/registry/ui/components/nm-icon/animated/arrow-down.tsx +149 -0
- package/registry/ui/components/nm-icon/animated/arrow-left.tsx +149 -0
- package/registry/ui/components/nm-icon/animated/arrow-right.tsx +149 -0
- package/registry/ui/components/nm-icon/animated/arrow-up-down.tsx +168 -0
- package/registry/ui/components/nm-icon/animated/arrow-up.tsx +149 -0
- package/registry/ui/components/nm-icon/animated/audio-lines.tsx +190 -0
- package/registry/ui/components/nm-icon/animated/bookmark-plus.tsx +65 -0
- package/registry/ui/components/nm-icon/animated/bookmark.tsx +77 -0
- package/registry/ui/components/nm-icon/animated/bot.tsx +167 -0
- package/registry/ui/components/nm-icon/animated/calendar-days.tsx +128 -0
- package/registry/ui/components/nm-icon/animated/calendar.tsx +83 -0
- package/registry/ui/components/nm-icon/animated/camera.tsx +85 -0
- package/registry/ui/components/nm-icon/animated/chart-column-increasing.tsx +150 -0
- package/registry/ui/components/nm-icon/animated/chart-column.tsx +179 -0
- package/registry/ui/components/nm-icon/animated/chart-line.tsx +88 -0
- package/registry/ui/components/nm-icon/animated/check-check.tsx +105 -0
- package/registry/ui/components/nm-icon/animated/check.tsx +70 -0
- package/registry/ui/components/nm-icon/animated/chevron-down.tsx +73 -0
- package/registry/ui/components/nm-icon/animated/chevron-left.tsx +73 -0
- package/registry/ui/components/nm-icon/animated/chevron-right.tsx +73 -0
- package/registry/ui/components/nm-icon/animated/chevron-up.tsx +73 -0
- package/registry/ui/components/nm-icon/animated/circle-alert.tsx +84 -0
- package/registry/ui/components/nm-icon/animated/circle-check-big.tsx +75 -0
- package/registry/ui/components/nm-icon/animated/circle-check.tsx +77 -0
- package/registry/ui/components/nm-icon/animated/circle-plus.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/circle-question-mark.tsx +62 -0
- package/registry/ui/components/nm-icon/animated/circle-x.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/clock-3.tsx +95 -0
- package/registry/ui/components/nm-icon/animated/clock-4.tsx +95 -0
- package/registry/ui/components/nm-icon/animated/clock.tsx +95 -0
- package/registry/ui/components/nm-icon/animated/cloud-sun.tsx +130 -0
- package/registry/ui/components/nm-icon/animated/cloud-upload.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/copy.tsx +153 -0
- package/registry/ui/components/nm-icon/animated/download.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/ellipsis.tsx +189 -0
- package/registry/ui/components/nm-icon/animated/external-link.tsx +97 -0
- package/registry/ui/components/nm-icon/animated/eye-off.tsx +63 -0
- package/registry/ui/components/nm-icon/animated/eye.tsx +82 -0
- package/registry/ui/components/nm-icon/animated/fast-forward.tsx +72 -0
- package/registry/ui/components/nm-icon/animated/file-clock.tsx +105 -0
- package/registry/ui/components/nm-icon/animated/file-text.tsx +102 -0
- package/registry/ui/components/nm-icon/animated/file.tsx +124 -0
- package/registry/ui/components/nm-icon/animated/folder.tsx +132 -0
- package/registry/ui/components/nm-icon/animated/gauge.tsx +84 -0
- package/registry/ui/components/nm-icon/animated/globe.tsx +61 -0
- package/registry/ui/components/nm-icon/animated/graduation-cap.tsx +92 -0
- package/registry/ui/components/nm-icon/animated/headphones.tsx +85 -0
- package/registry/ui/components/nm-icon/animated/image.tsx +88 -0
- package/registry/ui/components/nm-icon/animated/index.ts +251 -0
- package/registry/ui/components/nm-icon/animated/info.tsx +75 -0
- package/registry/ui/components/nm-icon/animated/key-round.tsx +67 -0
- package/registry/ui/components/nm-icon/animated/layers.tsx +116 -0
- package/registry/ui/components/nm-icon/animated/layout-dashboard.tsx +176 -0
- package/registry/ui/components/nm-icon/animated/library-big.tsx +89 -0
- package/registry/ui/components/nm-icon/animated/lightbulb.tsx +106 -0
- package/registry/ui/components/nm-icon/animated/link.tsx +210 -0
- package/registry/ui/components/nm-icon/animated/list-filter.tsx +78 -0
- package/registry/ui/components/nm-icon/animated/list.tsx +184 -0
- package/registry/ui/components/nm-icon/animated/loader-circle.tsx +68 -0
- package/registry/ui/components/nm-icon/animated/lock.tsx +152 -0
- package/registry/ui/components/nm-icon/animated/log-out.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/mail.tsx +131 -0
- package/registry/ui/components/nm-icon/animated/map-pin.tsx +111 -0
- package/registry/ui/components/nm-icon/animated/menu.tsx +121 -0
- package/registry/ui/components/nm-icon/animated/message-circle-dashed.tsx +140 -0
- package/registry/ui/components/nm-icon/animated/message-circle.tsx +66 -0
- package/registry/ui/components/nm-icon/animated/message-square-plus.tsx +106 -0
- package/registry/ui/components/nm-icon/animated/message-square-text.tsx +153 -0
- package/registry/ui/components/nm-icon/animated/message-square.tsx +66 -0
- package/registry/ui/components/nm-icon/animated/mic-off.tsx +65 -0
- package/registry/ui/components/nm-icon/animated/mic.tsx +77 -0
- package/registry/ui/components/nm-icon/animated/minimize.tsx +164 -0
- package/registry/ui/components/nm-icon/animated/minus.tsx +84 -0
- package/registry/ui/components/nm-icon/animated/moon.tsx +98 -0
- package/registry/ui/components/nm-icon/animated/music.tsx +62 -0
- package/registry/ui/components/nm-icon/animated/notebook-pen.tsx +114 -0
- package/registry/ui/components/nm-icon/animated/panel-left.tsx +77 -0
- package/registry/ui/components/nm-icon/animated/panel-right.tsx +77 -0
- package/registry/ui/components/nm-icon/animated/paperclip.tsx +83 -0
- package/registry/ui/components/nm-icon/animated/pause.tsx +116 -0
- package/registry/ui/components/nm-icon/animated/pencil.tsx +70 -0
- package/registry/ui/components/nm-icon/animated/pin-off.tsx +102 -0
- package/registry/ui/components/nm-icon/animated/pin.tsx +124 -0
- package/registry/ui/components/nm-icon/animated/plane-takeoff.tsx +62 -0
- package/registry/ui/components/nm-icon/animated/play.tsx +74 -0
- package/registry/ui/components/nm-icon/animated/plug-zap.tsx +117 -0
- package/registry/ui/components/nm-icon/animated/plus.tsx +122 -0
- package/registry/ui/components/nm-icon/animated/radio.tsx +137 -0
- package/registry/ui/components/nm-icon/animated/refresh-cw.tsx +103 -0
- package/registry/ui/components/nm-icon/animated/rocket.tsx +93 -0
- package/registry/ui/components/nm-icon/animated/rotate-ccw.tsx +87 -0
- package/registry/ui/components/nm-icon/animated/rotate-cw.tsx +98 -0
- package/registry/ui/components/nm-icon/animated/save.tsx +58 -0
- package/registry/ui/components/nm-icon/animated/search.tsx +90 -0
- package/registry/ui/components/nm-icon/animated/send.tsx +87 -0
- package/registry/ui/components/nm-icon/animated/settings.tsx +92 -0
- package/registry/ui/components/nm-icon/animated/share-2.tsx +148 -0
- package/registry/ui/components/nm-icon/animated/share.tsx +76 -0
- package/registry/ui/components/nm-icon/animated/shield-check.tsx +70 -0
- package/registry/ui/components/nm-icon/animated/shopping-bag.tsx +71 -0
- package/registry/ui/components/nm-icon/animated/sliders-horizontal.tsx +243 -0
- package/registry/ui/components/nm-icon/animated/sparkles.tsx +227 -0
- package/registry/ui/components/nm-icon/animated/star.tsx +86 -0
- package/registry/ui/components/nm-icon/animated/sun.tsx +148 -0
- package/registry/ui/components/nm-icon/animated/terminal.tsx +71 -0
- package/registry/ui/components/nm-icon/animated/trash-2.tsx +136 -0
- package/registry/ui/components/nm-icon/animated/trash.tsx +94 -0
- package/registry/ui/components/nm-icon/animated/trending-up.tsx +75 -0
- package/registry/ui/components/nm-icon/animated/triangle-alert.tsx +75 -0
- package/registry/ui/components/nm-icon/animated/trophy.tsx +62 -0
- package/registry/ui/components/nm-icon/animated/type.tsx +106 -0
- package/registry/ui/components/nm-icon/animated/upload.tsx +94 -0
- package/registry/ui/components/nm-icon/animated/user-round.tsx +84 -0
- package/registry/ui/components/nm-icon/animated/user.tsx +84 -0
- package/registry/ui/components/nm-icon/animated/users-round.tsx +156 -0
- package/registry/ui/components/nm-icon/animated/users.tsx +156 -0
- package/registry/ui/components/nm-icon/animated/volume-2.tsx +119 -0
- package/registry/ui/components/nm-icon/animated/wand-sparkles.tsx +111 -0
- package/registry/ui/components/nm-icon/animated/x.tsx +122 -0
- package/registry/ui/components/nm-icon/animated/zap.tsx +86 -0
- package/registry/ui/components/nm-icon/animated/zoom-in.tsx +66 -0
- package/registry/ui/components/nm-icon/animated/zoom-out.tsx +85 -0
- package/registry/ui/components/nm-icon/nm-icon.css +0 -1
- package/registry/ui/components/nm-icon/nm-icon.tsx +20 -5
- package/registry/ui/components/nm-icon/nm-lucide-extended.tsx +284 -0
- package/registry/ui/components/nm-icon/nm-lucide.tsx +55 -5
- package/registry/ui/components/nm-input/nm-input.css +1 -0
- package/registry/ui/components/nm-menubar/nm-menubar.tsx +2 -2
- package/registry/ui/components/nm-panel/nm-panel.css +7 -0
- package/registry/ui/components/nm-panel/nm-panel.tsx +19 -2
- package/registry/ui/components/nm-popover/nm-popover.tsx +4 -3
- package/registry/ui/components/nm-progress/nm-progress.tsx +1 -1
- package/registry/ui/components/nm-radio-group/nm-radio-group.tsx +2 -2
- package/registry/ui/components/nm-select/nm-select.tsx +1 -1
- package/registry/ui/components/nm-skeleton/nm-skeleton.css +17 -0
- package/registry/ui/components/nm-skeleton/nm-skeleton.tsx +7 -0
- package/registry/ui/components/nm-slider/nm-slider.tsx +1 -1
- package/registry/ui/components/nm-small-icon-button/nm-small-icon-button.tsx +3 -3
- package/registry/ui/components/nm-spinner/nm-spinner.css +22 -0
- package/registry/ui/components/nm-spinner/nm-spinner.tsx +7 -0
- package/registry/ui/components/nm-switch/nm-switch.css +20 -3
- package/registry/ui/components/nm-switch/nm-switch.tsx +1 -1
- package/registry/ui/components/nm-tabs/nm-tabs.css +4 -0
- package/registry/ui/components/nm-tabs/nm-tabs.tsx +19 -0
- package/registry/ui/components/nm-textarea/nm-textarea.css +1 -0
- package/registry/ui/components/nm-toggle/nm-toggle.tsx +1 -1
- package/registry/ui/components/nm-toolbar/nm-toolbar.tsx +4 -1
- package/registry/ui/components/nm-tooltip/nm-tooltip.tsx +1 -1
- package/registry/ui/components/nm-voice-orb/nm-voice-orb.css +17 -0
- package/registry/ui/components/nm-voice-orb/nm-voice-orb.tsx +112 -0
- package/registry/ui/components/nm-voice-orb/use-nm-voice-orb-theme.ts +34 -0
- package/registry/ui/components/nordman-icon-button/nordman-icon-button.tsx +7 -3
- package/registry/ui/config/nm-button.ts +6 -0
- package/registry/ui/config/nm-composer.ts +12 -0
- package/registry/ui/config/nm-icons-extended.ts +141 -0
- package/registry/ui/config/nm-icons.ts +6 -2
- package/registry/ui/config/nm-voice-orb.ts +50 -0
- package/registry/ui/lib/nm-motion.ts +30 -0
- package/registry/ui/styles/tokens.css +7 -0
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Archive,
|
|
3
|
+
Camera,
|
|
4
|
+
CloudUpload,
|
|
5
|
+
Download,
|
|
6
|
+
Lock,
|
|
7
|
+
LogOut,
|
|
8
|
+
Minimize,
|
|
9
|
+
Pencil,
|
|
10
|
+
Pin,
|
|
11
|
+
Share,
|
|
12
|
+
Trash2,
|
|
13
|
+
Volume2,
|
|
2
14
|
AppWindowMac,
|
|
3
15
|
ArrowLeft,
|
|
4
16
|
ArrowRight,
|
|
@@ -72,15 +84,29 @@ import {
|
|
|
72
84
|
X,
|
|
73
85
|
type LucideIcon,
|
|
74
86
|
} from 'lucide-react';
|
|
75
|
-
import type { ReactNode } from 'react';
|
|
87
|
+
import type { CSSProperties, ReactNode, SVGAttributes } from 'react';
|
|
88
|
+
import { NM_ANIMATED_ICONS } from './animated/index.ts';
|
|
89
|
+
import { NM_LUCIDE_EXTENDED } from './nm-lucide-extended.tsx';
|
|
76
90
|
import type { NmIconId } from '../../config/nm-icons.ts';
|
|
77
91
|
|
|
78
92
|
export const NM_LUCIDE_FILLED_IDS = new Set<string>(['stop']);
|
|
79
93
|
|
|
80
|
-
const
|
|
94
|
+
const LUCIDE_CORE: Partial<
|
|
81
95
|
Record<NmIconId | 'square-dashed-bottom-code' | 'layout-grid' | 'stop' | 'scan' | 'pause', LucideIcon>
|
|
82
96
|
> = {
|
|
83
97
|
plus: Plus,
|
|
98
|
+
volume: Volume2,
|
|
99
|
+
camera: Camera,
|
|
100
|
+
minimize: Minimize,
|
|
101
|
+
download: Download,
|
|
102
|
+
publish: CloudUpload,
|
|
103
|
+
share: Share,
|
|
104
|
+
pen: Pencil,
|
|
105
|
+
pin: Pin,
|
|
106
|
+
archive: Archive,
|
|
107
|
+
trash: Trash2,
|
|
108
|
+
logout: LogOut,
|
|
109
|
+
lock: Lock,
|
|
84
110
|
expand: Maximize2,
|
|
85
111
|
scan: Scan,
|
|
86
112
|
reload: RotateCcw,
|
|
@@ -156,25 +182,49 @@ const LUCIDE: Partial<
|
|
|
156
182
|
rows: Rows2,
|
|
157
183
|
};
|
|
158
184
|
|
|
185
|
+
const LUCIDE: Partial<Record<string, LucideIcon>> = { ...NM_LUCIDE_EXTENDED, ...LUCIDE_CORE };
|
|
186
|
+
|
|
187
|
+
/** True when the icon plays an animation on hover: a lucide icon Animate UI has an animation for. */
|
|
188
|
+
export function isNmIconAnimated(id: string): boolean {
|
|
189
|
+
const Icon = LUCIDE[id];
|
|
190
|
+
return Icon != null && !NM_LUCIDE_FILLED_IDS.has(id) && (Icon as { displayName?: string }).displayName! in NM_ANIMATED_ICONS;
|
|
191
|
+
}
|
|
192
|
+
|
|
159
193
|
export function hasNmLucide(id: string): boolean {
|
|
160
194
|
return id in LUCIDE;
|
|
161
195
|
}
|
|
162
196
|
|
|
163
|
-
|
|
164
|
-
|
|
197
|
+
function sized(size: number | string | undefined, style: CSSProperties | undefined): CSSProperties | undefined {
|
|
198
|
+
if (size == null) {
|
|
199
|
+
return style;
|
|
200
|
+
}
|
|
201
|
+
const length = typeof size === 'number' ? `${size}px` : size;
|
|
202
|
+
return { width: length, height: length, ...style };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function NmLucide({ id, className, size, style, ...rest }: { id: string; className?: string; size?: number | string; style?: CSSProperties } & Omit<SVGAttributes<SVGElement>, 'id' | 'className' | 'style'>): ReactNode {
|
|
206
|
+
const Icon = LUCIDE[id];
|
|
165
207
|
if (Icon == null) {
|
|
166
208
|
return null;
|
|
167
209
|
}
|
|
168
210
|
const filled = NM_LUCIDE_FILLED_IDS.has(id);
|
|
169
211
|
const baseClass = filled ? 'nm-icon nm-icon--filled' : 'nm-icon';
|
|
170
212
|
const iconClass = className == null ? baseClass : `${baseClass} ${className}`;
|
|
213
|
+
// An icon Animate UI has an animation for plays it when the control around it is hovered. The rest stay lucide.
|
|
214
|
+
const Animated = filled ? undefined : NM_ANIMATED_ICONS[(Icon as { displayName?: string }).displayName ?? ''];
|
|
215
|
+
if (Animated) {
|
|
216
|
+
return <Animated className={iconClass} data-icon={id} aria-hidden={rest['aria-label'] == null} focusable="false" size={typeof size === 'number' ? size : undefined} {...rest} style={sized(size, style)} />;
|
|
217
|
+
}
|
|
171
218
|
return (
|
|
172
219
|
<Icon
|
|
173
220
|
className={iconClass}
|
|
174
221
|
data-icon={id}
|
|
175
222
|
strokeWidth={filled ? undefined : 2}
|
|
176
|
-
aria-hidden
|
|
223
|
+
aria-hidden={rest['aria-label'] == null}
|
|
177
224
|
focusable="false"
|
|
225
|
+
size={typeof size === 'number' ? size : undefined}
|
|
226
|
+
{...(rest as object)}
|
|
227
|
+
style={sized(size, style)}
|
|
178
228
|
/>
|
|
179
229
|
);
|
|
180
230
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Menubar as MenubarPrimitive } from '
|
|
2
|
-
import { Menu as MenuPrimitive } from '
|
|
1
|
+
import { Menubar as MenubarPrimitive } from '../../lib/nm-motion.ts';
|
|
2
|
+
import { Menu as MenuPrimitive } from '../../lib/nm-motion.ts';
|
|
3
3
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -21,6 +21,13 @@
|
|
|
21
21
|
background: var(--nm-canvas);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
.nm-panel-region[data-measure='column'] {
|
|
25
|
+
width: var(--nm-width-column);
|
|
26
|
+
min-width: min(100%, var(--nm-width-column-min));
|
|
27
|
+
max-width: var(--nm-width-column-max);
|
|
28
|
+
margin-inline: auto;
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
.nm-panel-region__header {
|
|
25
32
|
display: flex;
|
|
26
33
|
flex-shrink: 0;
|
|
@@ -4,9 +4,26 @@ import { nmClass } from '../../lib/nm-class.ts';
|
|
|
4
4
|
export const NM_PANEL_VARIANTS = ['default', 'inset', 'plain'] as const;
|
|
5
5
|
export type NmPanelVariant = (typeof NM_PANEL_VARIANTS)[number];
|
|
6
6
|
|
|
7
|
+
/** `full` fills the room it is given. `column` is a centred share of it, held between a minimum and a maximum width. */
|
|
8
|
+
export const NM_PANEL_MEASURES = ['full', 'column'] as const;
|
|
9
|
+
export type NmPanelMeasure = (typeof NM_PANEL_MEASURES)[number];
|
|
10
|
+
|
|
7
11
|
/** A region of the app, such as an inspector or a side panel: a header, content that scrolls, and a footer. */
|
|
8
|
-
export function NmPanel({
|
|
9
|
-
|
|
12
|
+
export function NmPanel({
|
|
13
|
+
className,
|
|
14
|
+
variant = 'default',
|
|
15
|
+
measure = 'full',
|
|
16
|
+
...props
|
|
17
|
+
}: ComponentProps<'section'> & { variant?: NmPanelVariant; measure?: NmPanelMeasure }) {
|
|
18
|
+
return (
|
|
19
|
+
<section
|
|
20
|
+
data-slot="panel"
|
|
21
|
+
data-variant={variant}
|
|
22
|
+
data-measure={measure}
|
|
23
|
+
className={nmClass('nm-panel-region', className)}
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
10
27
|
}
|
|
11
28
|
|
|
12
29
|
export function NmPanelHeader({ className, ...props }: ComponentProps<'header'>) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentProps } from 'react';
|
|
2
|
-
import { Popover as PopoverPrimitive } from '
|
|
2
|
+
import { Popover as PopoverPrimitive } from '../../lib/nm-motion.ts';
|
|
3
3
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
4
4
|
|
|
5
5
|
export function NmPopover(props: PopoverPrimitive.Root.Props) {
|
|
@@ -16,11 +16,12 @@ export function NmPopoverContent({
|
|
|
16
16
|
alignOffset = 0,
|
|
17
17
|
side = 'bottom',
|
|
18
18
|
sideOffset = 8,
|
|
19
|
+
anchor,
|
|
19
20
|
...props
|
|
20
|
-
}: PopoverPrimitive.Popup.Props & Pick<PopoverPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
|
|
21
|
+
}: PopoverPrimitive.Popup.Props & Pick<PopoverPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset' | 'anchor'>) {
|
|
21
22
|
return (
|
|
22
23
|
<PopoverPrimitive.Portal>
|
|
23
|
-
<PopoverPrimitive.Positioner align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset} className="nm-popover__positioner">
|
|
24
|
+
<PopoverPrimitive.Positioner anchor={anchor} align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset} className="nm-popover__positioner">
|
|
24
25
|
<PopoverPrimitive.Popup data-slot="popover-content" className={nmClass('nm-popover', className as string)} {...props} />
|
|
25
26
|
</PopoverPrimitive.Positioner>
|
|
26
27
|
</PopoverPrimitive.Portal>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Progress as ProgressPrimitive } from '
|
|
1
|
+
import { Progress as ProgressPrimitive } from '../../lib/nm-motion.ts';
|
|
2
2
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
3
3
|
|
|
4
4
|
/** Base UI Progress, in the shadcn composition, styled by NIF tokens. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Radio as RadioPrimitive } from '
|
|
2
|
-
import { RadioGroup as RadioGroupPrimitive } from '
|
|
1
|
+
import { Radio as RadioPrimitive } from '../../lib/nm-motion.ts';
|
|
2
|
+
import { RadioGroup as RadioGroupPrimitive } from '../../lib/nm-motion.ts';
|
|
3
3
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
4
4
|
|
|
5
5
|
export function NmRadioGroup({ className, ...props }: RadioGroupPrimitive.Props) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { Select as SelectPrimitive } from '
|
|
2
|
+
import { Select as SelectPrimitive } 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
5
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.nm-skeleton {
|
|
2
|
+
border-radius: var(--nm-radius-md);
|
|
3
|
+
background: var(--nm-panel);
|
|
4
|
+
animation: nm-skeleton-pulse 1.6s ease-in-out infinite;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
@keyframes nm-skeleton-pulse {
|
|
8
|
+
50% {
|
|
9
|
+
opacity: 0.5;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@media (prefers-reduced-motion: reduce) {
|
|
14
|
+
.nm-skeleton {
|
|
15
|
+
animation: none;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
import { nmClass } from '../../lib/nm-class.ts';
|
|
3
|
+
|
|
4
|
+
/** A pulsing placeholder in the shape of the content that is loading. Size it with a class. */
|
|
5
|
+
export function NmSkeleton({ className, ...props }: ComponentProps<'div'>): ReactNode {
|
|
6
|
+
return <div data-slot="skeleton" className={nmClass('nm-skeleton', className)} {...props} />;
|
|
7
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Slider as SliderPrimitive } from '
|
|
1
|
+
import { Slider as SliderPrimitive } from '../../lib/nm-motion.ts';
|
|
2
2
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
3
3
|
|
|
4
4
|
/** `label` and `output` add a caption above the track, set like the caption of a Field. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
1
|
+
import { forwardRef, type ButtonHTMLAttributes, type MouseEvent, type ReactNode } from 'react';
|
|
2
2
|
import type { NmIconId } from '../../config/nm-icons.ts';
|
|
3
3
|
import {
|
|
4
4
|
NM_SMALL_ICON_BUTTON_TONES,
|
|
@@ -22,7 +22,7 @@ export type NmSmallIconButtonProps = {
|
|
|
22
22
|
active?: boolean;
|
|
23
23
|
iconContent?: ReactNode;
|
|
24
24
|
testId?: string;
|
|
25
|
-
onClick?: () => void;
|
|
25
|
+
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
26
26
|
} & Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onClick' | 'aria-label' | 'children'>;
|
|
27
27
|
|
|
28
28
|
export const NmSmallIconButton = forwardRef<HTMLButtonElement, NmSmallIconButtonProps>(
|
|
@@ -56,7 +56,7 @@ export const NmSmallIconButton = forwardRef<HTMLButtonElement, NmSmallIconButton
|
|
|
56
56
|
if (disabled === true) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
|
-
onClick?.();
|
|
59
|
+
onClick?.(event);
|
|
60
60
|
}}
|
|
61
61
|
>
|
|
62
62
|
{iconContent}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.nm-spinner {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
width: var(--nm-icon);
|
|
5
|
+
height: var(--nm-icon);
|
|
6
|
+
border: 2px solid var(--nm-line-strong);
|
|
7
|
+
border-top-color: var(--nm-fg);
|
|
8
|
+
border-radius: 50%;
|
|
9
|
+
animation: nm-spinner-turn 0.8s linear infinite;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@keyframes nm-spinner-turn {
|
|
13
|
+
to {
|
|
14
|
+
transform: rotate(360deg);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@media (prefers-reduced-motion: reduce) {
|
|
19
|
+
.nm-spinner {
|
|
20
|
+
animation-duration: 2.4s;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
import { nmClass } from '../../lib/nm-class.ts';
|
|
3
|
+
|
|
4
|
+
/** A ring that turns while something loads. It is the themed icon size; a class or style sets another. */
|
|
5
|
+
export function NmSpinner({ className, ...props }: ComponentProps<'span'>): ReactNode {
|
|
6
|
+
return <span role="status" aria-live="polite" data-slot="spinner" className={nmClass('nm-spinner', className)} {...props} />;
|
|
7
|
+
}
|
|
@@ -7,11 +7,16 @@
|
|
|
7
7
|
width: calc(var(--nm-switch-thumb) * 2);
|
|
8
8
|
height: var(--nm-switch-thumb);
|
|
9
9
|
padding: var(--nm-space-2);
|
|
10
|
-
border:
|
|
10
|
+
border: var(--nm-rule) solid var(--nm-line-strong);
|
|
11
11
|
border-radius: var(--toggle-r);
|
|
12
12
|
background: var(--nm-panel);
|
|
13
13
|
cursor: pointer;
|
|
14
|
-
|
|
14
|
+
user-select: none;
|
|
15
|
+
-webkit-user-select: none;
|
|
16
|
+
touch-action: none;
|
|
17
|
+
transition:
|
|
18
|
+
background 0.15s,
|
|
19
|
+
border-color 0.15s;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
.nm-switch:focus-visible {
|
|
@@ -20,6 +25,7 @@
|
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
.nm-switch[data-checked] {
|
|
28
|
+
border-color: var(--nm-fg);
|
|
23
29
|
background: var(--nm-fg);
|
|
24
30
|
}
|
|
25
31
|
|
|
@@ -30,12 +36,16 @@
|
|
|
30
36
|
|
|
31
37
|
.nm-switch__thumb {
|
|
32
38
|
display: block;
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
pointer-events: none;
|
|
33
41
|
width: var(--nm-switch-thumb);
|
|
34
42
|
height: var(--nm-switch-thumb);
|
|
35
43
|
border-radius: 50%;
|
|
36
44
|
background: var(--nm-fg);
|
|
45
|
+
transform: translateX(0);
|
|
46
|
+
will-change: transform;
|
|
37
47
|
transition:
|
|
38
|
-
transform 0.15s,
|
|
48
|
+
transform 0.15s var(--ease, ease),
|
|
39
49
|
background 0.15s;
|
|
40
50
|
}
|
|
41
51
|
|
|
@@ -43,3 +53,10 @@
|
|
|
43
53
|
transform: translateX(var(--nm-switch-thumb));
|
|
44
54
|
background: var(--nm-canvas);
|
|
45
55
|
}
|
|
56
|
+
|
|
57
|
+
@media (prefers-reduced-motion: reduce) {
|
|
58
|
+
.nm-switch,
|
|
59
|
+
.nm-switch__thumb {
|
|
60
|
+
transition: none;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import { Tabs as TabsPrimitive } from '../../lib/nm-motion.ts';
|
|
3
|
+
import { nmClass } from '../../lib/nm-class.ts';
|
|
2
4
|
import { NM_TABS_CLASSES, type NmTabItem } from '../../config/nm-tabs.ts';
|
|
3
5
|
import { createLogger } from '../../kit-logger.ts';
|
|
4
6
|
|
|
@@ -30,3 +32,20 @@ export function NmTabs(props: NmTabsProps): ReactNode {
|
|
|
30
32
|
</div>
|
|
31
33
|
);
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
/** The parts of a tab set, for a view that lays out its own list and panels. */
|
|
37
|
+
export function NmTabsRoot(props: TabsPrimitive.Root.Props): ReactNode {
|
|
38
|
+
return <TabsPrimitive.Root data-slot="tabs" {...props} />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function NmTabsList({ className, ...props }: TabsPrimitive.List.Props): ReactNode {
|
|
42
|
+
return <TabsPrimitive.List data-slot="tabs-list" className={nmClass(NM_TABS_CLASSES.root, className as string)} {...props} />;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function NmTabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props): ReactNode {
|
|
46
|
+
return <TabsPrimitive.Tab data-slot="tabs-trigger" className={nmClass(NM_TABS_CLASSES.item, className as string)} {...props} />;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function NmTabsContent({ className, ...props }: TabsPrimitive.Panel.Props): ReactNode {
|
|
50
|
+
return <TabsPrimitive.Panel data-slot="tabs-content" className={nmClass('nm-tabs__panel', className as string)} {...props} />;
|
|
51
|
+
}
|
|
@@ -4,6 +4,7 @@ import { nmClass } from '../../lib/nm-class.ts';
|
|
|
4
4
|
import type { NmIconId } from '../../config/nm-icons.ts';
|
|
5
5
|
import { NM_BUTTON_TONES, nmButtonClassName, type NmButtonTone } from '../../config/nm-button.ts';
|
|
6
6
|
import { nmIconButtonClassName, type NmIconButtonTone } from '../../config/nm-icon-button.ts';
|
|
7
|
+
import { AnimateIcon } from '../../lib/nm-motion.ts';
|
|
7
8
|
import { NmIcon } from '../nm-icon/nm-icon.tsx';
|
|
8
9
|
|
|
9
10
|
/** Base UI Toolbar, in the shadcn composition, styled by NIF tokens. One tab stop, arrow keys move between controls. */
|
|
@@ -40,7 +41,7 @@ export function NmToolbarButton({
|
|
|
40
41
|
}: Omit<ToolbarPrimitive.Button.Props, 'children'> & { icon?: NmIconId; label: string; tone?: NmIconButtonTone | NmButtonTone; pressed?: boolean; children?: ReactNode }) {
|
|
41
42
|
const withText = children != null;
|
|
42
43
|
const buttonTone = (Object.values(NM_BUTTON_TONES) as string[]).includes(tone ?? '') ? (tone as NmButtonTone) : 'muted';
|
|
43
|
-
|
|
44
|
+
const button = (
|
|
44
45
|
<ToolbarPrimitive.Button
|
|
45
46
|
data-slot="toolbar-button"
|
|
46
47
|
aria-label={label}
|
|
@@ -52,6 +53,8 @@ export function NmToolbarButton({
|
|
|
52
53
|
{withText ? <span className="nm-button__label">{children}</span> : null}
|
|
53
54
|
</ToolbarPrimitive.Button>
|
|
54
55
|
);
|
|
56
|
+
// Always wrapped, so the control keeps its place in the tree when its icon is added or removed.
|
|
57
|
+
return <AnimateIcon animateOnHover={Boolean(icon)} asChild>{button}</AnimateIcon>;
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/** A field in the bar that takes the free width, such as an address. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Tooltip as TooltipPrimitive } from '
|
|
1
|
+
import { Tooltip as TooltipPrimitive } from '../../lib/nm-motion.ts';
|
|
2
2
|
import { nmClass } from '../../lib/nm-class.ts';
|
|
3
3
|
|
|
4
4
|
export function NmTooltipProvider({ delay = 0, ...props }: TooltipPrimitive.Provider.Props) {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
.nm-voice-orb {
|
|
2
|
+
--orb-ui-size: var(--nm-icon-control);
|
|
3
|
+
flex-shrink: 0;
|
|
4
|
+
border-radius: var(--nm-control-radius);
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.nm-voice-orb .orb-ui__content {
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
border-radius: inherit;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.nm-voice-orb:focus-visible {
|
|
14
|
+
outline: var(--nm-rule) solid var(--nm-fg);
|
|
15
|
+
outline-offset: var(--nm-space-2);
|
|
16
|
+
}
|
|
17
|
+
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { useMemo, type ReactNode } from 'react';
|
|
2
|
+
import { Orb, type OrbAdapter, type OrbSignal, type OrbTheme } from 'orb-ui';
|
|
3
|
+
import {
|
|
4
|
+
NM_VOICE_ORB_CLASSES,
|
|
5
|
+
NM_VOICE_ORB_SIZE,
|
|
6
|
+
toOrbUiState,
|
|
7
|
+
type NmVoiceOrbAgentState,
|
|
8
|
+
} from '../../config/nm-voice-orb.ts';
|
|
9
|
+
import { useNmVoiceOrbTheme } from './use-nm-voice-orb-theme.ts';
|
|
10
|
+
import { createLogger } from '../../kit-logger.ts';
|
|
11
|
+
|
|
12
|
+
const logger = createLogger('interface-nm-voice-orb');
|
|
13
|
+
|
|
14
|
+
export type NmVoiceOrbProps = {
|
|
15
|
+
adapter?: OrbAdapter;
|
|
16
|
+
signal?: OrbSignal;
|
|
17
|
+
agentState?: NmVoiceOrbAgentState;
|
|
18
|
+
theme?: OrbTheme;
|
|
19
|
+
size?: number;
|
|
20
|
+
inputVolume?: number;
|
|
21
|
+
outputVolume?: number;
|
|
22
|
+
getInputVolume?: () => number;
|
|
23
|
+
getOutputVolume?: () => number;
|
|
24
|
+
label?: string;
|
|
25
|
+
testId?: string;
|
|
26
|
+
onClick?: () => void;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function clamp01(value: number | undefined): number {
|
|
30
|
+
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
return Math.min(1, Math.max(0, value));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function ensureMatchMedia(): void {
|
|
37
|
+
if (typeof window === 'undefined' || typeof window.matchMedia === 'function') {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
41
|
+
writable: true,
|
|
42
|
+
configurable: true,
|
|
43
|
+
value: (query: string) => ({
|
|
44
|
+
matches: false,
|
|
45
|
+
media: query,
|
|
46
|
+
onchange: null,
|
|
47
|
+
addListener: () => {},
|
|
48
|
+
removeListener: () => {},
|
|
49
|
+
addEventListener: () => {},
|
|
50
|
+
removeEventListener: () => {},
|
|
51
|
+
dispatchEvent: () => false,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function NmVoiceOrb(props: NmVoiceOrbProps): ReactNode {
|
|
57
|
+
ensureMatchMedia();
|
|
58
|
+
const appearanceTheme = useNmVoiceOrbTheme();
|
|
59
|
+
|
|
60
|
+
const {
|
|
61
|
+
signal,
|
|
62
|
+
adapter,
|
|
63
|
+
inputVolume: propInputVolume,
|
|
64
|
+
outputVolume: propOutputVolume,
|
|
65
|
+
getInputVolume,
|
|
66
|
+
getOutputVolume,
|
|
67
|
+
} = props;
|
|
68
|
+
const mappedState = toOrbUiState(props.agentState);
|
|
69
|
+
const fallbackSignal = useMemo<OrbSignal | undefined>(() => {
|
|
70
|
+
if (signal) {
|
|
71
|
+
return signal;
|
|
72
|
+
}
|
|
73
|
+
if (adapter) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
const inputVolume = clamp01(propInputVolume ?? getInputVolume?.() ?? 0);
|
|
77
|
+
const outputVolume = clamp01(
|
|
78
|
+
propOutputVolume ?? getOutputVolume?.() ?? (mappedState === 'speaking' ? 0.72 : 0),
|
|
79
|
+
);
|
|
80
|
+
return {
|
|
81
|
+
state: mappedState,
|
|
82
|
+
inputVolume,
|
|
83
|
+
outputVolume,
|
|
84
|
+
};
|
|
85
|
+
}, [
|
|
86
|
+
mappedState,
|
|
87
|
+
adapter,
|
|
88
|
+
getInputVolume,
|
|
89
|
+
getOutputVolume,
|
|
90
|
+
propInputVolume,
|
|
91
|
+
propOutputVolume,
|
|
92
|
+
signal,
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
logger.debug('render', 'orb-ui', { state: mappedState });
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Orb
|
|
99
|
+
adapter={props.adapter}
|
|
100
|
+
signal={fallbackSignal}
|
|
101
|
+
state={props.agentState != null ? mappedState : undefined}
|
|
102
|
+
theme={props.theme ?? appearanceTheme}
|
|
103
|
+
size={props.size ?? NM_VOICE_ORB_SIZE}
|
|
104
|
+
className={NM_VOICE_ORB_CLASSES.root}
|
|
105
|
+
aria-label={props.label ?? 'Avsluta röstläge'}
|
|
106
|
+
onStart={props.onClick}
|
|
107
|
+
onStop={props.onClick}
|
|
108
|
+
data-testid={props.testId ?? 'voice-orb'}
|
|
109
|
+
data-agent-state={props.agentState ?? mappedState}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { defineOrbTheme, type OrbTheme } from 'orb-ui';
|
|
3
|
+
import { deriveCloudOrbAppearance } from '../../lib/appearance/cloudOrbAppearance.ts';
|
|
4
|
+
import { NM_APPEARANCE_APPLIED_EVENT } from '../../config/nm-appearance.ts';
|
|
5
|
+
import { NM_ORB_UI_THEME } from '../../config/nm-voice-orb.ts';
|
|
6
|
+
|
|
7
|
+
function readAppearanceChannel(name: string, fallback: string): string {
|
|
8
|
+
if (typeof document === 'undefined') {
|
|
9
|
+
return fallback;
|
|
10
|
+
}
|
|
11
|
+
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
|
12
|
+
return value.length > 0 ? value : fallback;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useNmVoiceOrbTheme(): OrbTheme {
|
|
16
|
+
const [revision, setRevision] = useState(0);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const sync = () => setRevision((value) => value + 1);
|
|
20
|
+
window.addEventListener(NM_APPEARANCE_APPLIED_EVENT, sync);
|
|
21
|
+
return () => window.removeEventListener(NM_APPEARANCE_APPLIED_EVENT, sync);
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return useMemo(() => {
|
|
25
|
+
void revision;
|
|
26
|
+
const accent = readAppearanceChannel('--nm-accent', '#D2BB9C');
|
|
27
|
+
const canvas = readAppearanceChannel('--nm-canvas', '#000000');
|
|
28
|
+
const fg = readAppearanceChannel('--nm-fg', '#FFFFFF');
|
|
29
|
+
return defineOrbTheme({
|
|
30
|
+
...NM_ORB_UI_THEME,
|
|
31
|
+
appearance: deriveCloudOrbAppearance(accent, canvas, fg),
|
|
32
|
+
});
|
|
33
|
+
}, [revision]);
|
|
34
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from '../../config/nm-icon-button.ts';
|
|
8
8
|
import { NORDMAN_CHROME_ICONS, type NordmanChromeIconId } from '../../config/nordman-chrome.ts';
|
|
9
9
|
import { createLogger } from '../../kit-logger.ts';
|
|
10
|
+
import { AnimateIcon, Button as MotionButton } from '../../lib/nm-motion.ts';
|
|
10
11
|
import { NmIcon } from '../nm-icon/nm-icon.tsx';
|
|
11
12
|
|
|
12
13
|
const logger = createLogger('interface-nordman-icon-button');
|
|
@@ -174,11 +175,14 @@ export const NordmanIconButton = forwardRef<HTMLButtonElement, NordmanIconButton
|
|
|
174
175
|
</a>
|
|
175
176
|
);
|
|
176
177
|
}
|
|
177
|
-
|
|
178
|
-
<
|
|
178
|
+
const button = (
|
|
179
|
+
<MotionButton {...(rest as object)} {...shared} ref={ref} type={type ?? 'button'} hoverScale={rest.disabled ? 1 : 1.08} tapScale={rest.disabled ? 1 : 0.92}>
|
|
179
180
|
{face}
|
|
180
|
-
</
|
|
181
|
+
</MotionButton>
|
|
181
182
|
);
|
|
183
|
+
// The icon plays its animation when the button is hovered.
|
|
184
|
+
// Always wrapped: a control that swaps its glyph for an image must stay the same element.
|
|
185
|
+
return <AnimateIcon animateOnHover={glyph != null} asChild>{button}</AnimateIcon>;
|
|
182
186
|
},
|
|
183
187
|
);
|
|
184
188
|
|
|
@@ -4,6 +4,10 @@ export const NM_BUTTON_TONES = {
|
|
|
4
4
|
muted: 'muted',
|
|
5
5
|
panel: 'panel',
|
|
6
6
|
danger: 'danger',
|
|
7
|
+
/** No fill until hovered. For actions that sit inside other content. */
|
|
8
|
+
ghost: 'ghost',
|
|
9
|
+
/** Text with an underline on hover. */
|
|
10
|
+
link: 'link',
|
|
7
11
|
} as const;
|
|
8
12
|
|
|
9
13
|
export type NmButtonTone = (typeof NM_BUTTON_TONES)[keyof typeof NM_BUTTON_TONES];
|
|
@@ -24,6 +28,8 @@ export const NM_BUTTON_CLASSES = {
|
|
|
24
28
|
muted: 'nm-button--muted',
|
|
25
29
|
panel: 'nm-button--panel',
|
|
26
30
|
danger: 'nm-button--danger',
|
|
31
|
+
ghost: 'nm-button--ghost',
|
|
32
|
+
link: 'nm-button--link',
|
|
27
33
|
default: 'nm-button--default',
|
|
28
34
|
compact: 'nm-button--compact',
|
|
29
35
|
chip: 'nm-button--chip',
|