@dowel-ui/react 0.1.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.
- package/LICENSE +21 -0
- package/dist/blocks/admin-users/meta.js +27 -0
- package/dist/blocks/admin-users/meta.js.map +1 -0
- package/dist/blocks/ai-chat/meta.js +30 -0
- package/dist/blocks/ai-chat/meta.js.map +1 -0
- package/dist/blocks/dashboard/meta.js +23 -0
- package/dist/blocks/dashboard/meta.js.map +1 -0
- package/dist/blocks/forgot-password/meta.js +24 -0
- package/dist/blocks/forgot-password/meta.js.map +1 -0
- package/dist/blocks/login/meta.js +26 -0
- package/dist/blocks/login/meta.js.map +1 -0
- package/dist/blocks/pricing/meta.js +24 -0
- package/dist/blocks/pricing/meta.js.map +1 -0
- package/dist/blocks/settings/meta.js +29 -0
- package/dist/blocks/settings/meta.js.map +1 -0
- package/dist/blocks/signup/meta.js +25 -0
- package/dist/blocks/signup/meta.js.map +1 -0
- package/dist/components/accordion/accordion.d.ts +19 -0
- package/dist/components/accordion/accordion.d.ts.map +1 -0
- package/dist/components/accordion/accordion.js +58 -0
- package/dist/components/accordion/accordion.js.map +1 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +2 -0
- package/dist/components/accordion/meta.js +17 -0
- package/dist/components/accordion/meta.js.map +1 -0
- package/dist/components/activity-feed/activity-feed.d.ts +39 -0
- package/dist/components/activity-feed/activity-feed.d.ts.map +1 -0
- package/dist/components/activity-feed/activity-feed.js +77 -0
- package/dist/components/activity-feed/activity-feed.js.map +1 -0
- package/dist/components/activity-feed/index.d.ts +2 -0
- package/dist/components/activity-feed/index.js +2 -0
- package/dist/components/activity-feed/meta.js +17 -0
- package/dist/components/activity-feed/meta.js.map +1 -0
- package/dist/components/ai-agent-status/ai-agent-status.d.ts +30 -0
- package/dist/components/ai-agent-status/ai-agent-status.d.ts.map +1 -0
- package/dist/components/ai-agent-status/ai-agent-status.js +43 -0
- package/dist/components/ai-agent-status/ai-agent-status.js.map +1 -0
- package/dist/components/ai-agent-status/index.d.ts +2 -0
- package/dist/components/ai-agent-status/index.js +2 -0
- package/dist/components/ai-agent-status/meta.js +17 -0
- package/dist/components/ai-agent-status/meta.js.map +1 -0
- package/dist/components/ai-conversation/ai-conversation.d.ts +45 -0
- package/dist/components/ai-conversation/ai-conversation.d.ts.map +1 -0
- package/dist/components/ai-conversation/ai-conversation.js +138 -0
- package/dist/components/ai-conversation/ai-conversation.js.map +1 -0
- package/dist/components/ai-conversation/index.d.ts +2 -0
- package/dist/components/ai-conversation/index.js +2 -0
- package/dist/components/ai-conversation/meta.js +17 -0
- package/dist/components/ai-conversation/meta.js.map +1 -0
- package/dist/components/ai-message/ai-message.d.ts +56 -0
- package/dist/components/ai-message/ai-message.d.ts.map +1 -0
- package/dist/components/ai-message/ai-message.js +90 -0
- package/dist/components/ai-message/ai-message.js.map +1 -0
- package/dist/components/ai-message/index.d.ts +2 -0
- package/dist/components/ai-message/index.js +2 -0
- package/dist/components/ai-message/meta.js +17 -0
- package/dist/components/ai-message/meta.js.map +1 -0
- package/dist/components/ai-model-selector/ai-model-selector.d.ts +42 -0
- package/dist/components/ai-model-selector/ai-model-selector.d.ts.map +1 -0
- package/dist/components/ai-model-selector/ai-model-selector.js +48 -0
- package/dist/components/ai-model-selector/ai-model-selector.js.map +1 -0
- package/dist/components/ai-model-selector/index.d.ts +2 -0
- package/dist/components/ai-model-selector/index.js +2 -0
- package/dist/components/ai-model-selector/meta.js +17 -0
- package/dist/components/ai-model-selector/meta.js.map +1 -0
- package/dist/components/ai-prompt-input/ai-prompt-input.d.ts +61 -0
- package/dist/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -0
- package/dist/components/ai-prompt-input/ai-prompt-input.js +170 -0
- package/dist/components/ai-prompt-input/ai-prompt-input.js.map +1 -0
- package/dist/components/ai-prompt-input/index.d.ts +2 -0
- package/dist/components/ai-prompt-input/index.js +2 -0
- package/dist/components/ai-prompt-input/meta.js +17 -0
- package/dist/components/ai-prompt-input/meta.js.map +1 -0
- package/dist/components/ai-reasoning/ai-reasoning.d.ts +24 -0
- package/dist/components/ai-reasoning/ai-reasoning.d.ts.map +1 -0
- package/dist/components/ai-reasoning/ai-reasoning.js +64 -0
- package/dist/components/ai-reasoning/ai-reasoning.js.map +1 -0
- package/dist/components/ai-reasoning/index.d.ts +2 -0
- package/dist/components/ai-reasoning/index.js +2 -0
- package/dist/components/ai-reasoning/meta.js +17 -0
- package/dist/components/ai-reasoning/meta.js.map +1 -0
- package/dist/components/ai-response/ai-response.d.ts +36 -0
- package/dist/components/ai-response/ai-response.d.ts.map +1 -0
- package/dist/components/ai-response/ai-response.js +46 -0
- package/dist/components/ai-response/ai-response.js.map +1 -0
- package/dist/components/ai-response/index.d.ts +2 -0
- package/dist/components/ai-response/index.js +2 -0
- package/dist/components/ai-response/meta.js +17 -0
- package/dist/components/ai-response/meta.js.map +1 -0
- package/dist/components/ai-sources/ai-sources.d.ts +44 -0
- package/dist/components/ai-sources/ai-sources.d.ts.map +1 -0
- package/dist/components/ai-sources/ai-sources.js +112 -0
- package/dist/components/ai-sources/ai-sources.js.map +1 -0
- package/dist/components/ai-sources/index.d.ts +2 -0
- package/dist/components/ai-sources/index.js +2 -0
- package/dist/components/ai-sources/meta.js +17 -0
- package/dist/components/ai-sources/meta.js.map +1 -0
- package/dist/components/ai-token-usage/ai-token-usage.d.ts +34 -0
- package/dist/components/ai-token-usage/ai-token-usage.d.ts.map +1 -0
- package/dist/components/ai-token-usage/ai-token-usage.js +58 -0
- package/dist/components/ai-token-usage/ai-token-usage.js.map +1 -0
- package/dist/components/ai-token-usage/index.d.ts +2 -0
- package/dist/components/ai-token-usage/index.js +2 -0
- package/dist/components/ai-token-usage/meta.js +17 -0
- package/dist/components/ai-token-usage/meta.js.map +1 -0
- package/dist/components/ai-tool/ai-tool.d.ts +50 -0
- package/dist/components/ai-tool/ai-tool.d.ts.map +1 -0
- package/dist/components/ai-tool/ai-tool.js +129 -0
- package/dist/components/ai-tool/ai-tool.js.map +1 -0
- package/dist/components/ai-tool/index.d.ts +2 -0
- package/dist/components/ai-tool/index.js +2 -0
- package/dist/components/ai-tool/meta.js +17 -0
- package/dist/components/ai-tool/meta.js.map +1 -0
- package/dist/components/alert/alert.d.ts +32 -0
- package/dist/components/alert/alert.d.ts.map +1 -0
- package/dist/components/alert/alert.js +49 -0
- package/dist/components/alert/alert.js.map +1 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +2 -0
- package/dist/components/alert/meta.js +17 -0
- package/dist/components/alert/meta.js.map +1 -0
- package/dist/components/avatar/avatar.d.ts +23 -0
- package/dist/components/avatar/avatar.d.ts.map +1 -0
- package/dist/components/avatar/avatar.js +44 -0
- package/dist/components/avatar/avatar.js.map +1 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +2 -0
- package/dist/components/avatar/meta.js +17 -0
- package/dist/components/avatar/meta.js.map +1 -0
- package/dist/components/badge/badge.d.ts +20 -0
- package/dist/components/badge/badge.d.ts.map +1 -0
- package/dist/components/badge/badge.js +47 -0
- package/dist/components/badge/badge.js.map +1 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +2 -0
- package/dist/components/badge/meta.js +17 -0
- package/dist/components/badge/meta.js.map +1 -0
- package/dist/components/button/button.d.ts +28 -0
- package/dist/components/button/button.d.ts.map +1 -0
- package/dist/components/button/button.js +77 -0
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +2 -0
- package/dist/components/button/meta.js +17 -0
- package/dist/components/button/meta.js.map +1 -0
- package/dist/components/calendar/calendar.d.ts +16 -0
- package/dist/components/calendar/calendar.d.ts.map +1 -0
- package/dist/components/calendar/calendar.js +70 -0
- package/dist/components/calendar/calendar.js.map +1 -0
- package/dist/components/calendar/index.d.ts +2 -0
- package/dist/components/calendar/index.js +2 -0
- package/dist/components/calendar/meta.js +17 -0
- package/dist/components/calendar/meta.js.map +1 -0
- package/dist/components/card/card.d.ts +23 -0
- package/dist/components/card/card.d.ts.map +1 -0
- package/dist/components/card/card.js +53 -0
- package/dist/components/card/card.js.map +1 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +2 -0
- package/dist/components/card/meta.js +17 -0
- package/dist/components/card/meta.js.map +1 -0
- package/dist/components/checkbox/checkbox.d.ts +15 -0
- package/dist/components/checkbox/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox/checkbox.js +45 -0
- package/dist/components/checkbox/checkbox.js.map +1 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +2 -0
- package/dist/components/checkbox/meta.js +17 -0
- package/dist/components/checkbox/meta.js.map +1 -0
- package/dist/components/code-block/code-block.d.ts +46 -0
- package/dist/components/code-block/code-block.d.ts.map +1 -0
- package/dist/components/code-block/code-block.js +110 -0
- package/dist/components/code-block/code-block.js.map +1 -0
- package/dist/components/code-block/index.d.ts +2 -0
- package/dist/components/code-block/index.js +2 -0
- package/dist/components/code-block/meta.js +17 -0
- package/dist/components/code-block/meta.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +59 -0
- package/dist/components/combobox/combobox.d.ts.map +1 -0
- package/dist/components/combobox/combobox.js +346 -0
- package/dist/components/combobox/combobox.js.map +1 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +2 -0
- package/dist/components/combobox/meta.js +17 -0
- package/dist/components/combobox/meta.js.map +1 -0
- package/dist/components/command/command.d.ts +65 -0
- package/dist/components/command/command.d.ts.map +1 -0
- package/dist/components/command/command.js +330 -0
- package/dist/components/command/command.js.map +1 -0
- package/dist/components/command/index.d.ts +2 -0
- package/dist/components/command/index.js +2 -0
- package/dist/components/command/meta.js +17 -0
- package/dist/components/command/meta.js.map +1 -0
- package/dist/components/data-table/data-table.d.ts +91 -0
- package/dist/components/data-table/data-table.d.ts.map +1 -0
- package/dist/components/data-table/data-table.js +263 -0
- package/dist/components/data-table/data-table.js.map +1 -0
- package/dist/components/data-table/index.d.ts +2 -0
- package/dist/components/data-table/index.js +2 -0
- package/dist/components/data-table/meta.js +22 -0
- package/dist/components/data-table/meta.js.map +1 -0
- package/dist/components/date-picker/date-picker.d.ts +31 -0
- package/dist/components/date-picker/date-picker.d.ts.map +1 -0
- package/dist/components/date-picker/date-picker.js +123 -0
- package/dist/components/date-picker/date-picker.js.map +1 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +2 -0
- package/dist/components/date-picker/meta.js +21 -0
- package/dist/components/date-picker/meta.js.map +1 -0
- package/dist/components/dialog/dialog.d.ts +30 -0
- package/dist/components/dialog/dialog.d.ts.map +1 -0
- package/dist/components/dialog/dialog.js +79 -0
- package/dist/components/dialog/dialog.js.map +1 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +2 -0
- package/dist/components/dialog/meta.js +17 -0
- package/dist/components/dialog/meta.js.map +1 -0
- package/dist/components/drawer/drawer.d.ts +32 -0
- package/dist/components/drawer/drawer.d.ts.map +1 -0
- package/dist/components/drawer/drawer.js +153 -0
- package/dist/components/drawer/drawer.js.map +1 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +2 -0
- package/dist/components/drawer/meta.js +17 -0
- package/dist/components/drawer/meta.js.map +1 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +43 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +1 -0
- package/dist/components/dropdown-menu/dropdown-menu.js +130 -0
- package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -0
- package/dist/components/dropdown-menu/index.d.ts +2 -0
- package/dist/components/dropdown-menu/index.js +2 -0
- package/dist/components/dropdown-menu/meta.js +17 -0
- package/dist/components/dropdown-menu/meta.js.map +1 -0
- package/dist/components/empty-state/empty-state.d.ts +24 -0
- package/dist/components/empty-state/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state/empty-state.js +73 -0
- package/dist/components/empty-state/empty-state.js.map +1 -0
- package/dist/components/empty-state/index.d.ts +2 -0
- package/dist/components/empty-state/index.js +2 -0
- package/dist/components/empty-state/meta.js +17 -0
- package/dist/components/empty-state/meta.js.map +1 -0
- package/dist/components/form/form.d.ts +43 -0
- package/dist/components/form/form.d.ts.map +1 -0
- package/dist/components/form/form.js +127 -0
- package/dist/components/form/form.js.map +1 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.js +2 -0
- package/dist/components/form/meta.js +17 -0
- package/dist/components/form/meta.js.map +1 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +2 -0
- package/dist/components/input/input.d.ts +21 -0
- package/dist/components/input/input.d.ts.map +1 -0
- package/dist/components/input/input.js +34 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/input/meta.js +17 -0
- package/dist/components/input/meta.js.map +1 -0
- package/dist/components/label/index.d.ts +2 -0
- package/dist/components/label/index.js +2 -0
- package/dist/components/label/label.d.ts +14 -0
- package/dist/components/label/label.d.ts.map +1 -0
- package/dist/components/label/label.js +20 -0
- package/dist/components/label/label.js.map +1 -0
- package/dist/components/label/meta.js +17 -0
- package/dist/components/label/meta.js.map +1 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +2 -0
- package/dist/components/pagination/meta.js +17 -0
- package/dist/components/pagination/meta.js.map +1 -0
- package/dist/components/pagination/pagination.d.ts +33 -0
- package/dist/components/pagination/pagination.d.ts.map +1 -0
- package/dist/components/pagination/pagination.js +143 -0
- package/dist/components/pagination/pagination.js.map +1 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +2 -0
- package/dist/components/popover/meta.js +17 -0
- package/dist/components/popover/meta.js.map +1 -0
- package/dist/components/popover/popover.d.ts +24 -0
- package/dist/components/popover/popover.d.ts.map +1 -0
- package/dist/components/popover/popover.js +60 -0
- package/dist/components/popover/popover.js.map +1 -0
- package/dist/components/progress/index.d.ts +2 -0
- package/dist/components/progress/index.js +2 -0
- package/dist/components/progress/meta.js +17 -0
- package/dist/components/progress/meta.js.map +1 -0
- package/dist/components/progress/progress.d.ts +21 -0
- package/dist/components/progress/progress.d.ts.map +1 -0
- package/dist/components/progress/progress.js +55 -0
- package/dist/components/progress/progress.js.map +1 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +2 -0
- package/dist/components/radio-group/meta.js +17 -0
- package/dist/components/radio-group/meta.js.map +1 -0
- package/dist/components/radio-group/radio-group.d.ts +17 -0
- package/dist/components/radio-group/radio-group.d.ts.map +1 -0
- package/dist/components/radio-group/radio-group.js +29 -0
- package/dist/components/radio-group/radio-group.js.map +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +2 -0
- package/dist/components/select/meta.js +17 -0
- package/dist/components/select/meta.js.map +1 -0
- package/dist/components/select/select.d.ts +37 -0
- package/dist/components/select/select.d.ts.map +1 -0
- package/dist/components/select/select.js +128 -0
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/separator/index.d.ts +2 -0
- package/dist/components/separator/index.js +2 -0
- package/dist/components/separator/meta.js +17 -0
- package/dist/components/separator/meta.js.map +1 -0
- package/dist/components/separator/separator.d.ts +15 -0
- package/dist/components/separator/separator.d.ts.map +1 -0
- package/dist/components/separator/separator.js +23 -0
- package/dist/components/separator/separator.js.map +1 -0
- package/dist/components/sheet/index.d.ts +2 -0
- package/dist/components/sheet/index.js +2 -0
- package/dist/components/sheet/meta.js +17 -0
- package/dist/components/sheet/meta.js.map +1 -0
- package/dist/components/sheet/sheet.d.ts +31 -0
- package/dist/components/sheet/sheet.d.ts.map +1 -0
- package/dist/components/sheet/sheet.js +90 -0
- package/dist/components/sheet/sheet.js.map +1 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +2 -0
- package/dist/components/skeleton/meta.js +17 -0
- package/dist/components/skeleton/meta.js.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +20 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.js +29 -0
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +2 -0
- package/dist/components/slider/meta.js +17 -0
- package/dist/components/slider/meta.js.map +1 -0
- package/dist/components/slider/slider.d.ts +29 -0
- package/dist/components/slider/slider.d.ts.map +1 -0
- package/dist/components/slider/slider.js +61 -0
- package/dist/components/slider/slider.js.map +1 -0
- package/dist/components/spinner/index.d.ts +2 -0
- package/dist/components/spinner/index.js +2 -0
- package/dist/components/spinner/meta.js +17 -0
- package/dist/components/spinner/meta.js.map +1 -0
- package/dist/components/spinner/spinner.d.ts +21 -0
- package/dist/components/spinner/spinner.d.ts.map +1 -0
- package/dist/components/spinner/spinner.js +45 -0
- package/dist/components/spinner/spinner.js.map +1 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +2 -0
- package/dist/components/switch/meta.js +17 -0
- package/dist/components/switch/meta.js.map +1 -0
- package/dist/components/switch/switch.d.ts +15 -0
- package/dist/components/switch/switch.d.ts.map +1 -0
- package/dist/components/switch/switch.js +21 -0
- package/dist/components/switch/switch.js.map +1 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +2 -0
- package/dist/components/table/meta.js +17 -0
- package/dist/components/table/meta.js.map +1 -0
- package/dist/components/table/table.d.ts +41 -0
- package/dist/components/table/table.d.ts.map +1 -0
- package/dist/components/table/table.js +78 -0
- package/dist/components/table/table.js.map +1 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +2 -0
- package/dist/components/tabs/meta.js +17 -0
- package/dist/components/tabs/meta.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +28 -0
- package/dist/components/tabs/tabs.d.ts.map +1 -0
- package/dist/components/tabs/tabs.js +58 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/toast/index.d.ts +3 -0
- package/dist/components/toast/index.js +3 -0
- package/dist/components/toast/meta.js +17 -0
- package/dist/components/toast/meta.js.map +1 -0
- package/dist/components/toast/toast-store.d.ts +84 -0
- package/dist/components/toast/toast-store.d.ts.map +1 -0
- package/dist/components/toast/toast-store.js +115 -0
- package/dist/components/toast/toast-store.js.map +1 -0
- package/dist/components/toast/toast.d.ts +39 -0
- package/dist/components/toast/toast.d.ts.map +1 -0
- package/dist/components/toast/toast.js +140 -0
- package/dist/components/toast/toast.js.map +1 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +2 -0
- package/dist/components/tooltip/meta.js +17 -0
- package/dist/components/tooltip/meta.js.map +1 -0
- package/dist/components/tooltip/tooltip.d.ts +24 -0
- package/dist/components/tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip/tooltip.js +38 -0
- package/dist/components/tooltip/tooltip.js.map +1 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.js +51 -0
- package/dist/lib/styles.d.ts +21 -0
- package/dist/lib/styles.d.ts.map +1 -0
- package/dist/lib/styles.js +22 -0
- package/dist/lib/styles.js.map +1 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +21 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/registry/blocks.d.ts +15 -0
- package/dist/registry/blocks.d.ts.map +1 -0
- package/dist/registry/blocks.js +32 -0
- package/dist/registry/blocks.js.map +1 -0
- package/dist/registry/components.d.ts +18 -0
- package/dist/registry/components.d.ts.map +1 -0
- package/dist/registry/components.js +112 -0
- package/dist/registry/components.js.map +1 -0
- package/dist/registry/schema.d.ts +44 -0
- package/dist/registry/schema.d.ts.map +1 -0
- package/dist/registry/schema.js +33 -0
- package/dist/registry/schema.js.map +1 -0
- package/package.json +74 -0
- package/src/blocks/admin-users/admin-users.stories.tsx +83 -0
- package/src/blocks/admin-users/admin-users.test.tsx +159 -0
- package/src/blocks/admin-users/admin-users.tsx +251 -0
- package/src/blocks/admin-users/index.ts +1 -0
- package/src/blocks/admin-users/meta.ts +27 -0
- package/src/blocks/ai-chat/ai-chat.stories.tsx +149 -0
- package/src/blocks/ai-chat/ai-chat.test.tsx +166 -0
- package/src/blocks/ai-chat/ai-chat.tsx +280 -0
- package/src/blocks/ai-chat/index.ts +7 -0
- package/src/blocks/ai-chat/meta.ts +32 -0
- package/src/blocks/dashboard/dashboard.stories.tsx +106 -0
- package/src/blocks/dashboard/dashboard.test.tsx +94 -0
- package/src/blocks/dashboard/dashboard.tsx +192 -0
- package/src/blocks/dashboard/index.ts +6 -0
- package/src/blocks/dashboard/meta.ts +18 -0
- package/src/blocks/forgot-password/forgot-password.stories.tsx +41 -0
- package/src/blocks/forgot-password/forgot-password.test.tsx +62 -0
- package/src/blocks/forgot-password/forgot-password.tsx +158 -0
- package/src/blocks/forgot-password/index.ts +1 -0
- package/src/blocks/forgot-password/meta.ts +18 -0
- package/src/blocks/login/index.ts +1 -0
- package/src/blocks/login/login.stories.tsx +46 -0
- package/src/blocks/login/login.test.tsx +100 -0
- package/src/blocks/login/login.tsx +178 -0
- package/src/blocks/login/meta.ts +18 -0
- package/src/blocks/pricing/index.ts +1 -0
- package/src/blocks/pricing/meta.ts +18 -0
- package/src/blocks/pricing/pricing.stories.tsx +62 -0
- package/src/blocks/pricing/pricing.test.tsx +101 -0
- package/src/blocks/pricing/pricing.tsx +176 -0
- package/src/blocks/settings/index.ts +6 -0
- package/src/blocks/settings/meta.ts +29 -0
- package/src/blocks/settings/settings.stories.tsx +94 -0
- package/src/blocks/settings/settings.test.tsx +167 -0
- package/src/blocks/settings/settings.tsx +317 -0
- package/src/blocks/signup/index.ts +1 -0
- package/src/blocks/signup/meta.ts +18 -0
- package/src/blocks/signup/signup.stories.tsx +27 -0
- package/src/blocks/signup/signup.test.tsx +97 -0
- package/src/blocks/signup/signup.tsx +240 -0
- package/src/components/accordion/accordion.stories.tsx +90 -0
- package/src/components/accordion/accordion.test.tsx +156 -0
- package/src/components/accordion/accordion.tsx +88 -0
- package/src/components/accordion/index.ts +9 -0
- package/src/components/accordion/meta.ts +16 -0
- package/src/components/activity-feed/activity-feed.stories.tsx +163 -0
- package/src/components/activity-feed/activity-feed.test.tsx +125 -0
- package/src/components/activity-feed/activity-feed.tsx +115 -0
- package/src/components/activity-feed/index.ts +12 -0
- package/src/components/activity-feed/meta.ts +17 -0
- package/src/components/ai-agent-status/ai-agent-status.stories.tsx +86 -0
- package/src/components/ai-agent-status/ai-agent-status.test.tsx +66 -0
- package/src/components/ai-agent-status/ai-agent-status.tsx +88 -0
- package/src/components/ai-agent-status/index.ts +6 -0
- package/src/components/ai-agent-status/meta.ts +17 -0
- package/src/components/ai-conversation/ai-conversation.stories.tsx +126 -0
- package/src/components/ai-conversation/ai-conversation.test.tsx +144 -0
- package/src/components/ai-conversation/ai-conversation.tsx +229 -0
- package/src/components/ai-conversation/index.ts +9 -0
- package/src/components/ai-conversation/meta.ts +20 -0
- package/src/components/ai-message/ai-message.stories.tsx +106 -0
- package/src/components/ai-message/ai-message.test.tsx +160 -0
- package/src/components/ai-message/ai-message.tsx +162 -0
- package/src/components/ai-message/index.ts +13 -0
- package/src/components/ai-message/meta.ts +17 -0
- package/src/components/ai-model-selector/ai-model-selector.stories.tsx +66 -0
- package/src/components/ai-model-selector/ai-model-selector.test.tsx +120 -0
- package/src/components/ai-model-selector/ai-model-selector.tsx +112 -0
- package/src/components/ai-model-selector/index.ts +1 -0
- package/src/components/ai-model-selector/meta.ts +17 -0
- package/src/components/ai-prompt-input/ai-prompt-input.stories.tsx +145 -0
- package/src/components/ai-prompt-input/ai-prompt-input.test.tsx +273 -0
- package/src/components/ai-prompt-input/ai-prompt-input.tsx +306 -0
- package/src/components/ai-prompt-input/index.ts +11 -0
- package/src/components/ai-prompt-input/meta.ts +18 -0
- package/src/components/ai-reasoning/ai-reasoning.stories.tsx +60 -0
- package/src/components/ai-reasoning/ai-reasoning.test.tsx +95 -0
- package/src/components/ai-reasoning/ai-reasoning.tsx +106 -0
- package/src/components/ai-reasoning/index.ts +7 -0
- package/src/components/ai-reasoning/meta.ts +17 -0
- package/src/components/ai-response/ai-response.stories.tsx +75 -0
- package/src/components/ai-response/ai-response.test.tsx +96 -0
- package/src/components/ai-response/ai-response.tsx +95 -0
- package/src/components/ai-response/index.ts +7 -0
- package/src/components/ai-response/meta.ts +17 -0
- package/src/components/ai-sources/ai-sources.stories.tsx +93 -0
- package/src/components/ai-sources/ai-sources.test.tsx +102 -0
- package/src/components/ai-sources/ai-sources.tsx +186 -0
- package/src/components/ai-sources/index.ts +11 -0
- package/src/components/ai-sources/meta.ts +17 -0
- package/src/components/ai-token-usage/ai-token-usage.stories.tsx +59 -0
- package/src/components/ai-token-usage/ai-token-usage.test.tsx +83 -0
- package/src/components/ai-token-usage/ai-token-usage.tsx +105 -0
- package/src/components/ai-token-usage/index.ts +6 -0
- package/src/components/ai-token-usage/meta.ts +16 -0
- package/src/components/ai-tool/ai-tool.stories.tsx +96 -0
- package/src/components/ai-tool/ai-tool.test.tsx +137 -0
- package/src/components/ai-tool/ai-tool.tsx +235 -0
- package/src/components/ai-tool/index.ts +13 -0
- package/src/components/ai-tool/meta.ts +17 -0
- package/src/components/alert/alert.stories.tsx +101 -0
- package/src/components/alert/alert.test.tsx +94 -0
- package/src/components/alert/alert.tsx +89 -0
- package/src/components/alert/index.ts +8 -0
- package/src/components/alert/meta.ts +16 -0
- package/src/components/avatar/avatar.stories.tsx +58 -0
- package/src/components/avatar/avatar.test.tsx +64 -0
- package/src/components/avatar/avatar.tsx +68 -0
- package/src/components/avatar/index.ts +9 -0
- package/src/components/avatar/meta.ts +15 -0
- package/src/components/badge/badge.stories.tsx +68 -0
- package/src/components/badge/badge.test.tsx +61 -0
- package/src/components/badge/badge.tsx +54 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/badge/meta.ts +15 -0
- package/src/components/button/button.stories.tsx +128 -0
- package/src/components/button/button.test.tsx +224 -0
- package/src/components/button/button.tsx +114 -0
- package/src/components/button/index.ts +1 -0
- package/src/components/button/meta.ts +16 -0
- package/src/components/calendar/calendar.stories.tsx +105 -0
- package/src/components/calendar/calendar.test.tsx +255 -0
- package/src/components/calendar/calendar.tsx +115 -0
- package/src/components/calendar/index.ts +1 -0
- package/src/components/calendar/meta.ts +17 -0
- package/src/components/card/card.stories.tsx +61 -0
- package/src/components/card/card.test.tsx +66 -0
- package/src/components/card/card.tsx +81 -0
- package/src/components/card/index.ts +9 -0
- package/src/components/card/meta.ts +16 -0
- package/src/components/checkbox/checkbox.stories.tsx +124 -0
- package/src/components/checkbox/checkbox.test.tsx +121 -0
- package/src/components/checkbox/checkbox.tsx +66 -0
- package/src/components/checkbox/index.ts +1 -0
- package/src/components/checkbox/meta.ts +16 -0
- package/src/components/code-block/code-block.stories.tsx +62 -0
- package/src/components/code-block/code-block.test.tsx +139 -0
- package/src/components/code-block/code-block.tsx +188 -0
- package/src/components/code-block/index.ts +1 -0
- package/src/components/code-block/meta.ts +17 -0
- package/src/components/combobox/combobox.stories.tsx +171 -0
- package/src/components/combobox/combobox.test.tsx +429 -0
- package/src/components/combobox/combobox.tsx +544 -0
- package/src/components/combobox/index.ts +15 -0
- package/src/components/combobox/meta.ts +17 -0
- package/src/components/command/command.stories.tsx +152 -0
- package/src/components/command/command.test.tsx +380 -0
- package/src/components/command/command.tsx +482 -0
- package/src/components/command/index.ts +17 -0
- package/src/components/command/meta.ts +18 -0
- package/src/components/data-table/data-table.stories.tsx +151 -0
- package/src/components/data-table/data-table.test.tsx +288 -0
- package/src/components/data-table/data-table.tsx +485 -0
- package/src/components/data-table/index.ts +13 -0
- package/src/components/data-table/meta.ts +19 -0
- package/src/components/date-picker/date-picker.stories.tsx +103 -0
- package/src/components/date-picker/date-picker.test.tsx +205 -0
- package/src/components/date-picker/date-picker.tsx +198 -0
- package/src/components/date-picker/index.ts +6 -0
- package/src/components/date-picker/meta.ts +18 -0
- package/src/components/dialog/dialog.stories.tsx +140 -0
- package/src/components/dialog/dialog.test.tsx +186 -0
- package/src/components/dialog/dialog.tsx +132 -0
- package/src/components/dialog/index.ts +16 -0
- package/src/components/dialog/meta.ts +16 -0
- package/src/components/drawer/drawer.stories.tsx +111 -0
- package/src/components/drawer/drawer.test.tsx +187 -0
- package/src/components/drawer/drawer.tsx +293 -0
- package/src/components/drawer/index.ts +16 -0
- package/src/components/drawer/meta.ts +16 -0
- package/src/components/dropdown-menu/dropdown-menu.stories.tsx +128 -0
- package/src/components/dropdown-menu/dropdown-menu.test.tsx +321 -0
- package/src/components/dropdown-menu/dropdown-menu.tsx +242 -0
- package/src/components/dropdown-menu/index.ts +21 -0
- package/src/components/dropdown-menu/meta.ts +17 -0
- package/src/components/empty-state/empty-state.stories.tsx +70 -0
- package/src/components/empty-state/empty-state.test.tsx +97 -0
- package/src/components/empty-state/empty-state.tsx +92 -0
- package/src/components/empty-state/index.ts +9 -0
- package/src/components/empty-state/meta.ts +16 -0
- package/src/components/form/form.stories.tsx +144 -0
- package/src/components/form/form.test.tsx +203 -0
- package/src/components/form/form.tsx +221 -0
- package/src/components/form/index.ts +13 -0
- package/src/components/form/meta.ts +17 -0
- package/src/components/input/index.ts +1 -0
- package/src/components/input/input.stories.tsx +84 -0
- package/src/components/input/input.test.tsx +108 -0
- package/src/components/input/input.tsx +51 -0
- package/src/components/input/meta.ts +15 -0
- package/src/components/label/index.ts +1 -0
- package/src/components/label/label.stories.tsx +51 -0
- package/src/components/label/label.test.tsx +55 -0
- package/src/components/label/label.tsx +26 -0
- package/src/components/label/meta.ts +15 -0
- package/src/components/pagination/index.ts +10 -0
- package/src/components/pagination/meta.ts +17 -0
- package/src/components/pagination/pagination.stories.tsx +129 -0
- package/src/components/pagination/pagination.test.tsx +119 -0
- package/src/components/pagination/pagination.tsx +142 -0
- package/src/components/popover/index.ts +9 -0
- package/src/components/popover/meta.ts +18 -0
- package/src/components/popover/popover.stories.tsx +84 -0
- package/src/components/popover/popover.test.tsx +163 -0
- package/src/components/popover/popover.tsx +89 -0
- package/src/components/progress/index.ts +1 -0
- package/src/components/progress/meta.ts +17 -0
- package/src/components/progress/progress.stories.tsx +90 -0
- package/src/components/progress/progress.test.tsx +78 -0
- package/src/components/progress/progress.tsx +70 -0
- package/src/components/radio-group/index.ts +6 -0
- package/src/components/radio-group/meta.ts +16 -0
- package/src/components/radio-group/radio-group.stories.tsx +102 -0
- package/src/components/radio-group/radio-group.test.tsx +152 -0
- package/src/components/radio-group/radio-group.tsx +53 -0
- package/src/components/select/index.ts +14 -0
- package/src/components/select/meta.ts +16 -0
- package/src/components/select/select.stories.tsx +137 -0
- package/src/components/select/select.test.tsx +209 -0
- package/src/components/select/select.tsx +222 -0
- package/src/components/separator/index.ts +1 -0
- package/src/components/separator/meta.ts +15 -0
- package/src/components/separator/separator.stories.tsx +42 -0
- package/src/components/separator/separator.test.tsx +46 -0
- package/src/components/separator/separator.tsx +33 -0
- package/src/components/sheet/index.ts +14 -0
- package/src/components/sheet/meta.ts +16 -0
- package/src/components/sheet/sheet.stories.tsx +107 -0
- package/src/components/sheet/sheet.test.tsx +152 -0
- package/src/components/sheet/sheet.tsx +160 -0
- package/src/components/skeleton/index.ts +1 -0
- package/src/components/skeleton/meta.ts +15 -0
- package/src/components/skeleton/skeleton.stories.tsx +46 -0
- package/src/components/skeleton/skeleton.test.tsx +57 -0
- package/src/components/skeleton/skeleton.tsx +28 -0
- package/src/components/slider/index.ts +1 -0
- package/src/components/slider/meta.ts +19 -0
- package/src/components/slider/slider.stories.tsx +87 -0
- package/src/components/slider/slider.test.tsx +148 -0
- package/src/components/slider/slider.tsx +135 -0
- package/src/components/spinner/index.ts +1 -0
- package/src/components/spinner/meta.ts +15 -0
- package/src/components/spinner/spinner.stories.tsx +47 -0
- package/src/components/spinner/spinner.test.tsx +41 -0
- package/src/components/spinner/spinner.tsx +68 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/switch/meta.ts +15 -0
- package/src/components/switch/switch.stories.tsx +70 -0
- package/src/components/switch/switch.test.tsx +101 -0
- package/src/components/switch/switch.tsx +42 -0
- package/src/components/table/index.ts +11 -0
- package/src/components/table/meta.ts +17 -0
- package/src/components/table/table.stories.tsx +131 -0
- package/src/components/table/table.test.tsx +153 -0
- package/src/components/table/table.tsx +138 -0
- package/src/components/tabs/index.ts +11 -0
- package/src/components/tabs/meta.ts +17 -0
- package/src/components/tabs/tabs.stories.tsx +139 -0
- package/src/components/tabs/tabs.test.tsx +148 -0
- package/src/components/tabs/tabs.tsx +106 -0
- package/src/components/toast/index.ts +24 -0
- package/src/components/toast/meta.ts +18 -0
- package/src/components/toast/toast-store.ts +181 -0
- package/src/components/toast/toast.stories.tsx +167 -0
- package/src/components/toast/toast.test.tsx +306 -0
- package/src/components/toast/toast.tsx +241 -0
- package/src/components/tooltip/index.ts +8 -0
- package/src/components/tooltip/meta.ts +17 -0
- package/src/components/tooltip/tooltip.stories.tsx +89 -0
- package/src/components/tooltip/tooltip.test.tsx +120 -0
- package/src/components/tooltip/tooltip.tsx +58 -0
- package/src/index.ts +50 -0
- package/src/lib/styles.ts +26 -0
- package/src/lib/utils.test.ts +32 -0
- package/src/lib/utils.ts +24 -0
- package/src/registry/blocks.ts +30 -0
- package/src/registry/components.ts +114 -0
- package/src/registry/meta.test.ts +234 -0
- package/src/registry/schema.ts +58 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
useId,
|
|
7
|
+
useLayoutEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useRef,
|
|
10
|
+
type ComponentPropsWithRef,
|
|
11
|
+
type FormEvent,
|
|
12
|
+
type KeyboardEvent as ReactKeyboardEvent,
|
|
13
|
+
} from "react";
|
|
14
|
+
|
|
15
|
+
import { focusRing, focusRingInset } from "@/lib/styles";
|
|
16
|
+
import { cn } from "@/lib/utils";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The composer.
|
|
20
|
+
*
|
|
21
|
+
* Handles the parts of a chat input that are easy to get subtly wrong:
|
|
22
|
+
* auto-growing to fit the text up to a ceiling, sending on Enter without
|
|
23
|
+
* breaking multi-line input, and — the one almost everybody misses —
|
|
24
|
+
* not sending mid-composition when someone is typing with an IME.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
interface PromptInputContextValue {
|
|
28
|
+
textareaId: string;
|
|
29
|
+
submit: () => void;
|
|
30
|
+
disabled: boolean;
|
|
31
|
+
busy: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const PromptInputContext = createContext<PromptInputContextValue | null>(null);
|
|
35
|
+
|
|
36
|
+
function usePromptInput(component: string): PromptInputContextValue {
|
|
37
|
+
const context = useContext(PromptInputContext);
|
|
38
|
+
if (!context) {
|
|
39
|
+
throw new Error(`${component} must be rendered inside <PromptInput>.`);
|
|
40
|
+
}
|
|
41
|
+
return context;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface PromptInputProps extends Omit<ComponentPropsWithRef<"form">, "onSubmit"> {
|
|
45
|
+
onSubmit?: (event: FormEvent<HTMLFormElement>) => void;
|
|
46
|
+
/** Blocks submission and dims the composer. */
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
/** A response is in flight: submission is blocked and Stop is shown instead. */
|
|
49
|
+
busy?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function PromptInput({
|
|
53
|
+
className,
|
|
54
|
+
onSubmit,
|
|
55
|
+
disabled = false,
|
|
56
|
+
busy = false,
|
|
57
|
+
children,
|
|
58
|
+
...props
|
|
59
|
+
}: PromptInputProps) {
|
|
60
|
+
const uid = useId();
|
|
61
|
+
const formRef = useRef<HTMLFormElement | null>(null);
|
|
62
|
+
|
|
63
|
+
const context = useMemo<PromptInputContextValue>(
|
|
64
|
+
() => ({
|
|
65
|
+
textareaId: `${uid}-textarea`,
|
|
66
|
+
disabled,
|
|
67
|
+
busy,
|
|
68
|
+
submit: () => {
|
|
69
|
+
formRef.current?.requestSubmit();
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
[uid, disabled, busy],
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<PromptInputContext.Provider value={context}>
|
|
77
|
+
<form
|
|
78
|
+
ref={formRef}
|
|
79
|
+
data-slot="prompt-input"
|
|
80
|
+
data-busy={busy || undefined}
|
|
81
|
+
onSubmit={(event) => {
|
|
82
|
+
if (disabled || busy) {
|
|
83
|
+
event.preventDefault();
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
onSubmit?.(event);
|
|
87
|
+
}}
|
|
88
|
+
className={cn(
|
|
89
|
+
"rounded-xl border border-input bg-background shadow-xs",
|
|
90
|
+
"transition-[border-color,box-shadow] duration-[var(--duration-fast)]",
|
|
91
|
+
"focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/55",
|
|
92
|
+
disabled && "opacity-60",
|
|
93
|
+
className,
|
|
94
|
+
)}
|
|
95
|
+
{...props}
|
|
96
|
+
>
|
|
97
|
+
{children}
|
|
98
|
+
</form>
|
|
99
|
+
</PromptInputContext.Provider>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Rows the textarea will grow to before it starts scrolling. */
|
|
104
|
+
const DEFAULT_MAX_ROWS = 8;
|
|
105
|
+
|
|
106
|
+
export interface PromptInputTextareaProps extends Omit<
|
|
107
|
+
ComponentPropsWithRef<"textarea">,
|
|
108
|
+
"rows"
|
|
109
|
+
> {
|
|
110
|
+
maxRows?: number;
|
|
111
|
+
/**
|
|
112
|
+
* Send on Enter, newline on Shift+Enter.
|
|
113
|
+
*
|
|
114
|
+
* Turn it off for a composer where Enter should always insert a newline and
|
|
115
|
+
* sending is only ever an explicit button press.
|
|
116
|
+
*/
|
|
117
|
+
submitOnEnter?: boolean;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function PromptInputTextarea({
|
|
121
|
+
className,
|
|
122
|
+
maxRows = DEFAULT_MAX_ROWS,
|
|
123
|
+
submitOnEnter = true,
|
|
124
|
+
onKeyDown,
|
|
125
|
+
onChange,
|
|
126
|
+
...props
|
|
127
|
+
}: PromptInputTextareaProps) {
|
|
128
|
+
const { textareaId, submit, disabled, busy } = usePromptInput("PromptInputTextarea");
|
|
129
|
+
const ref = useRef<HTMLTextAreaElement | null>(null);
|
|
130
|
+
|
|
131
|
+
// Grows with the content up to maxRows, then scrolls. Measured after layout
|
|
132
|
+
// so the height is right on the first paint rather than one frame late.
|
|
133
|
+
useLayoutEffect(() => {
|
|
134
|
+
const textarea = ref.current;
|
|
135
|
+
if (!textarea) return;
|
|
136
|
+
|
|
137
|
+
textarea.style.height = "auto";
|
|
138
|
+
const lineHeight = Number.parseFloat(getComputedStyle(textarea).lineHeight) || 20;
|
|
139
|
+
const maxHeight = lineHeight * maxRows;
|
|
140
|
+
textarea.style.height = `${String(Math.min(textarea.scrollHeight, maxHeight))}px`;
|
|
141
|
+
textarea.style.overflowY = textarea.scrollHeight > maxHeight ? "auto" : "hidden";
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function handleKeyDown(event: ReactKeyboardEvent<HTMLTextAreaElement>) {
|
|
145
|
+
onKeyDown?.(event);
|
|
146
|
+
if (event.defaultPrevented || !submitOnEnter) return;
|
|
147
|
+
if (event.key !== "Enter" || event.shiftKey) return;
|
|
148
|
+
|
|
149
|
+
// Mid-composition Enter confirms the candidate an IME is offering — for
|
|
150
|
+
// Japanese, Chinese, Korean and others it is part of typing a word, not a
|
|
151
|
+
// request to send. Sending here truncates the sentence and is the single
|
|
152
|
+
// most common way a chat composer breaks for those users.
|
|
153
|
+
if (event.nativeEvent.isComposing) return;
|
|
154
|
+
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
submit();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<textarea
|
|
161
|
+
ref={ref}
|
|
162
|
+
id={textareaId}
|
|
163
|
+
data-slot="prompt-input-textarea"
|
|
164
|
+
rows={1}
|
|
165
|
+
disabled={disabled}
|
|
166
|
+
aria-disabled={busy || undefined}
|
|
167
|
+
onKeyDown={handleKeyDown}
|
|
168
|
+
onChange={onChange}
|
|
169
|
+
className={cn(
|
|
170
|
+
"block w-full resize-none bg-transparent px-4 py-3 text-sm outline-none",
|
|
171
|
+
"placeholder:text-muted-foreground disabled:cursor-not-allowed",
|
|
172
|
+
focusRingInset,
|
|
173
|
+
"focus-visible:ring-0",
|
|
174
|
+
className,
|
|
175
|
+
)}
|
|
176
|
+
{...props}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** The row beneath the textarea: attachments, model picker, send. */
|
|
182
|
+
export function PromptInputToolbar({ className, ...props }: ComponentPropsWithRef<"div">) {
|
|
183
|
+
return (
|
|
184
|
+
<div
|
|
185
|
+
data-slot="prompt-input-toolbar"
|
|
186
|
+
className={cn("flex items-center gap-2 px-2 pb-2", className)}
|
|
187
|
+
{...props}
|
|
188
|
+
/>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface PromptInputSubmitProps extends ComponentPropsWithRef<"button"> {
|
|
193
|
+
/** Label while idle. */
|
|
194
|
+
label?: string;
|
|
195
|
+
/** Label while a response is streaming. */
|
|
196
|
+
stopLabel?: string;
|
|
197
|
+
/** Called instead of submitting when busy. */
|
|
198
|
+
onStop?: () => void;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Send, or stop.
|
|
203
|
+
*
|
|
204
|
+
* One control with two jobs, because that is what the space affords and what
|
|
205
|
+
* people expect. The accessible name changes with the state, so it is never
|
|
206
|
+
* "Send" while it actually stops.
|
|
207
|
+
*/
|
|
208
|
+
export function PromptInputSubmit({
|
|
209
|
+
className,
|
|
210
|
+
label = "Send message",
|
|
211
|
+
stopLabel = "Stop generating",
|
|
212
|
+
onStop,
|
|
213
|
+
...props
|
|
214
|
+
}: PromptInputSubmitProps) {
|
|
215
|
+
const { busy, disabled } = usePromptInput("PromptInputSubmit");
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<button
|
|
219
|
+
type={busy ? "button" : "submit"}
|
|
220
|
+
data-slot="prompt-input-submit"
|
|
221
|
+
aria-label={busy ? stopLabel : label}
|
|
222
|
+
disabled={disabled}
|
|
223
|
+
onClick={busy ? onStop : undefined}
|
|
224
|
+
className={cn(
|
|
225
|
+
"ml-auto grid size-8 shrink-0 place-items-center rounded-lg",
|
|
226
|
+
"bg-primary text-primary-foreground transition-colors duration-[var(--duration-fast)]",
|
|
227
|
+
"hover:bg-primary-hover disabled:pointer-events-none disabled:opacity-55",
|
|
228
|
+
focusRing,
|
|
229
|
+
className,
|
|
230
|
+
)}
|
|
231
|
+
{...props}
|
|
232
|
+
>
|
|
233
|
+
{busy ? (
|
|
234
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className="size-3.5">
|
|
235
|
+
<rect x="6" y="6" width="12" height="12" rx="2" fill="currentColor" />
|
|
236
|
+
</svg>
|
|
237
|
+
) : (
|
|
238
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className="size-4">
|
|
239
|
+
<path
|
|
240
|
+
d="M12 19V5m0 0-6 6m6-6 6 6"
|
|
241
|
+
stroke="currentColor"
|
|
242
|
+
strokeWidth="2"
|
|
243
|
+
strokeLinecap="round"
|
|
244
|
+
strokeLinejoin="round"
|
|
245
|
+
/>
|
|
246
|
+
</svg>
|
|
247
|
+
)}
|
|
248
|
+
</button>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface PromptInputCounterProps extends ComponentPropsWithRef<"div"> {
|
|
253
|
+
value: number;
|
|
254
|
+
max: number;
|
|
255
|
+
/** Fraction of the limit past which the counter starts warning. */
|
|
256
|
+
warnAt?: number;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Characters used against a limit.
|
|
261
|
+
*
|
|
262
|
+
* The visible count updates on every keystroke; the live region does not.
|
|
263
|
+
*
|
|
264
|
+
* The naive version toggles `aria-live` on once the count matters, but a region
|
|
265
|
+
* only announces changes that happen *while* it is live — switching it on at
|
|
266
|
+
* the same moment the content changes means the one update worth hearing is the
|
|
267
|
+
* one that is missed. So the region is live from the start and simply has
|
|
268
|
+
* nothing in it until the limit is close, which is also what keeps ordinary
|
|
269
|
+
* typing silent.
|
|
270
|
+
*/
|
|
271
|
+
export function PromptInputCounter({
|
|
272
|
+
className,
|
|
273
|
+
value,
|
|
274
|
+
max,
|
|
275
|
+
warnAt = 0.9,
|
|
276
|
+
...props
|
|
277
|
+
}: PromptInputCounterProps) {
|
|
278
|
+
const warning = value >= max * warnAt;
|
|
279
|
+
const over = value > max;
|
|
280
|
+
const remaining = max - value;
|
|
281
|
+
|
|
282
|
+
return (
|
|
283
|
+
<div
|
|
284
|
+
data-slot="prompt-input-counter"
|
|
285
|
+
data-warning={warning || undefined}
|
|
286
|
+
data-over={over || undefined}
|
|
287
|
+
className={cn(
|
|
288
|
+
"text-xs tabular-nums",
|
|
289
|
+
over ? "text-destructive" : warning ? "text-warning" : "text-muted-foreground",
|
|
290
|
+
className,
|
|
291
|
+
)}
|
|
292
|
+
{...props}
|
|
293
|
+
>
|
|
294
|
+
<span aria-hidden="true">
|
|
295
|
+
{warning ? `${String(value)} / ${String(max)}` : String(value)}
|
|
296
|
+
</span>
|
|
297
|
+
<span role="status" aria-live="polite" className="sr-only">
|
|
298
|
+
{over
|
|
299
|
+
? `Over the limit by ${String(-remaining)} characters`
|
|
300
|
+
: warning
|
|
301
|
+
? `${String(remaining)} characters remaining`
|
|
302
|
+
: ""}
|
|
303
|
+
</span>
|
|
304
|
+
</div>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export {
|
|
2
|
+
PromptInput,
|
|
3
|
+
PromptInputCounter,
|
|
4
|
+
PromptInputSubmit,
|
|
5
|
+
PromptInputTextarea,
|
|
6
|
+
PromptInputToolbar,
|
|
7
|
+
type PromptInputCounterProps,
|
|
8
|
+
type PromptInputProps,
|
|
9
|
+
type PromptInputSubmitProps,
|
|
10
|
+
type PromptInputTextareaProps,
|
|
11
|
+
} from "./ai-prompt-input";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "ai-prompt-input",
|
|
5
|
+
title: "AI Prompt Input",
|
|
6
|
+
description: "The composer: auto-growing textarea, send-on-Enter, and a send/stop control.",
|
|
7
|
+
category: "ai",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: [],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["ai-prompt-input.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
"Enter sends and Shift+Enter inserts a newline, but never while an IME composition is active " +
|
|
14
|
+
"— for Japanese, Chinese and Korean input Enter confirms a candidate, and sending there " +
|
|
15
|
+
'truncates the sentence mid-word. The submit control renames itself to "Stop generating" ' +
|
|
16
|
+
"while busy, so its accessible name always matches what it does. The character counter stays " +
|
|
17
|
+
"silent until it nears the limit; announcing every keystroke would be unusable.",
|
|
18
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { Decorator, Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
|
|
3
|
+
import { Response } from "@/components/ai-response";
|
|
4
|
+
|
|
5
|
+
import { Reasoning, ReasoningContent, ReasoningTrigger } from "./ai-reasoning";
|
|
6
|
+
|
|
7
|
+
/** Named so its type is nameable in declaration output (TS2883). */
|
|
8
|
+
const withFixedWidth: Decorator = (Story) => (
|
|
9
|
+
<div className="w-[32rem]">
|
|
10
|
+
<Story />
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: "AI/Reasoning",
|
|
16
|
+
component: Reasoning,
|
|
17
|
+
parameters: { controls: { disable: true } },
|
|
18
|
+
decorators: [withFixedWidth],
|
|
19
|
+
} satisfies Meta<typeof Reasoning>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
type Story = StoryObj<typeof meta>;
|
|
23
|
+
|
|
24
|
+
const WORKING =
|
|
25
|
+
'The question is about keyboard access to overflowing tables.\n\nA scroll container is not focusable by default, so its content past the edge cannot be reached without a pointer. Adding tabindex="0" makes it a focus stop, and a role plus a name stops it being an unlabelled one.';
|
|
26
|
+
|
|
27
|
+
/** Collapsed by default: reasoning is supporting material, not the answer. */
|
|
28
|
+
export const Default: Story = {
|
|
29
|
+
render: () => (
|
|
30
|
+
<div className="grid gap-2">
|
|
31
|
+
<Reasoning>
|
|
32
|
+
<ReasoningTrigger />
|
|
33
|
+
<ReasoningContent>{WORKING}</ReasoningContent>
|
|
34
|
+
</Reasoning>
|
|
35
|
+
<Response>
|
|
36
|
+
Give the scrolling wrapper `tabindex="0"`, a role and an accessible name.
|
|
37
|
+
</Response>
|
|
38
|
+
</div>
|
|
39
|
+
),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Streaming: Story = {
|
|
43
|
+
render: () => (
|
|
44
|
+
<Reasoning defaultOpen>
|
|
45
|
+
<ReasoningTrigger streaming />
|
|
46
|
+
<ReasoningContent>
|
|
47
|
+
The question is about keyboard access to overflowing tables. A scroll container
|
|
48
|
+
</ReasoningContent>
|
|
49
|
+
</Reasoning>
|
|
50
|
+
),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const Expanded: Story = {
|
|
54
|
+
render: () => (
|
|
55
|
+
<Reasoning defaultOpen>
|
|
56
|
+
<ReasoningTrigger />
|
|
57
|
+
<ReasoningContent>{WORKING}</ReasoningContent>
|
|
58
|
+
</Reasoning>
|
|
59
|
+
),
|
|
60
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { render, screen, waitFor } from "@testing-library/react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
|
|
5
|
+
import { expectNoA11yViolations } from "../../../test/a11y";
|
|
6
|
+
import { Reasoning, ReasoningContent, ReasoningTrigger } from "./ai-reasoning";
|
|
7
|
+
|
|
8
|
+
describe("Reasoning", () => {
|
|
9
|
+
it("is collapsed by default, so the answer is not buried", () => {
|
|
10
|
+
render(
|
|
11
|
+
<Reasoning>
|
|
12
|
+
<ReasoningTrigger />
|
|
13
|
+
<ReasoningContent>Step one, then step two.</ReasoningContent>
|
|
14
|
+
</Reasoning>,
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
expect(screen.getByRole("button", { name: "Reasoning" })).toHaveAttribute(
|
|
18
|
+
"aria-expanded",
|
|
19
|
+
"false",
|
|
20
|
+
);
|
|
21
|
+
expect(screen.queryByText("Step one, then step two.")).not.toBeInTheDocument();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("opens on click", async () => {
|
|
25
|
+
const user = userEvent.setup();
|
|
26
|
+
render(
|
|
27
|
+
<Reasoning>
|
|
28
|
+
<ReasoningTrigger />
|
|
29
|
+
<ReasoningContent>Step one, then step two.</ReasoningContent>
|
|
30
|
+
</Reasoning>,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
await user.click(screen.getByRole("button", { name: "Reasoning" }));
|
|
34
|
+
expect(await screen.findByText("Step one, then step two.")).toBeInTheDocument();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("says it is thinking while reasoning streams", () => {
|
|
38
|
+
render(
|
|
39
|
+
<Reasoning>
|
|
40
|
+
<ReasoningTrigger streaming />
|
|
41
|
+
<ReasoningContent>Partial…</ReasoningContent>
|
|
42
|
+
</Reasoning>,
|
|
43
|
+
);
|
|
44
|
+
expect(screen.getByRole("button", { name: "Thinking…" })).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("accepts custom labels", () => {
|
|
48
|
+
render(
|
|
49
|
+
<Reasoning>
|
|
50
|
+
<ReasoningTrigger label="Show working" />
|
|
51
|
+
<ReasoningContent>Work</ReasoningContent>
|
|
52
|
+
</Reasoning>,
|
|
53
|
+
);
|
|
54
|
+
expect(screen.getByRole("button", { name: "Show working" })).toBeInTheDocument();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("can be opened by default", () => {
|
|
58
|
+
render(
|
|
59
|
+
<Reasoning defaultOpen>
|
|
60
|
+
<ReasoningTrigger />
|
|
61
|
+
<ReasoningContent>Visible</ReasoningContent>
|
|
62
|
+
</Reasoning>,
|
|
63
|
+
);
|
|
64
|
+
expect(screen.getByText("Visible")).toBeInTheDocument();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("toggles from the keyboard", async () => {
|
|
68
|
+
const user = userEvent.setup();
|
|
69
|
+
render(
|
|
70
|
+
<Reasoning>
|
|
71
|
+
<ReasoningTrigger />
|
|
72
|
+
<ReasoningContent>Work</ReasoningContent>
|
|
73
|
+
</Reasoning>,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
await user.tab();
|
|
77
|
+
await user.keyboard("{Enter}");
|
|
78
|
+
await waitFor(() => {
|
|
79
|
+
expect(screen.getByRole("button", { name: "Reasoning" })).toHaveAttribute(
|
|
80
|
+
"aria-expanded",
|
|
81
|
+
"true",
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("has no accessibility violations", async () => {
|
|
87
|
+
const { container } = render(
|
|
88
|
+
<Reasoning defaultOpen>
|
|
89
|
+
<ReasoningTrigger />
|
|
90
|
+
<ReasoningContent>Step one, then step two.</ReasoningContent>
|
|
91
|
+
</Reasoning>,
|
|
92
|
+
);
|
|
93
|
+
await expectNoA11yViolations(container);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
|
|
4
|
+
import type { ComponentPropsWithRef } from "react";
|
|
5
|
+
|
|
6
|
+
import { focusRing } from "@/lib/styles";
|
|
7
|
+
import { cn } from "@/lib/utils";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The model's reasoning, tucked away.
|
|
11
|
+
*
|
|
12
|
+
* Collapsed by default and deliberately understated. Reasoning is supporting
|
|
13
|
+
* material — surfacing it at the same weight as the answer buries the answer,
|
|
14
|
+
* and most readers never want it. It stays one keystroke away for the people
|
|
15
|
+
* who do.
|
|
16
|
+
*/
|
|
17
|
+
export type ReasoningProps = ComponentPropsWithRef<typeof CollapsiblePrimitive.Root>;
|
|
18
|
+
|
|
19
|
+
export function Reasoning({ className, ...props }: ReasoningProps) {
|
|
20
|
+
return (
|
|
21
|
+
<CollapsiblePrimitive.Root
|
|
22
|
+
data-slot="reasoning"
|
|
23
|
+
className={cn("text-sm", className)}
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface ReasoningTriggerProps extends ComponentPropsWithRef<
|
|
30
|
+
typeof CollapsiblePrimitive.Trigger
|
|
31
|
+
> {
|
|
32
|
+
/** Shown while reasoning is still arriving. */
|
|
33
|
+
streaming?: boolean;
|
|
34
|
+
label?: string;
|
|
35
|
+
streamingLabel?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function ReasoningTrigger({
|
|
39
|
+
className,
|
|
40
|
+
streaming,
|
|
41
|
+
label = "Reasoning",
|
|
42
|
+
streamingLabel = "Thinking…",
|
|
43
|
+
children,
|
|
44
|
+
...props
|
|
45
|
+
}: ReasoningTriggerProps) {
|
|
46
|
+
return (
|
|
47
|
+
<CollapsiblePrimitive.Trigger
|
|
48
|
+
data-slot="reasoning-trigger"
|
|
49
|
+
className={cn(
|
|
50
|
+
"flex items-center gap-1.5 rounded-md text-xs text-muted-foreground",
|
|
51
|
+
"transition-colors duration-[var(--duration-fast)] hover:text-foreground",
|
|
52
|
+
"[&[data-state=open]>svg:last-child]:rotate-180",
|
|
53
|
+
focusRing,
|
|
54
|
+
className,
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className="size-3.5 shrink-0">
|
|
59
|
+
<path
|
|
60
|
+
d="M9.5 21h5M12 3a6 6 0 0 1 3.6 10.8c-.6.5-.9 1.1-1 1.7l-.1.5h-5l-.1-.5c-.1-.6-.4-1.2-1-1.7A6 6 0 0 1 12 3Z"
|
|
61
|
+
stroke="currentColor"
|
|
62
|
+
strokeWidth="1.75"
|
|
63
|
+
strokeLinecap="round"
|
|
64
|
+
strokeLinejoin="round"
|
|
65
|
+
/>
|
|
66
|
+
</svg>
|
|
67
|
+
{children ?? (streaming ? streamingLabel : label)}
|
|
68
|
+
<svg
|
|
69
|
+
viewBox="0 0 24 24"
|
|
70
|
+
fill="none"
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
className="size-3.5 shrink-0 transition-transform duration-[var(--duration-normal)]"
|
|
73
|
+
>
|
|
74
|
+
<path
|
|
75
|
+
d="m6 9 6 6 6-6"
|
|
76
|
+
stroke="currentColor"
|
|
77
|
+
strokeWidth="2"
|
|
78
|
+
strokeLinecap="round"
|
|
79
|
+
strokeLinejoin="round"
|
|
80
|
+
/>
|
|
81
|
+
</svg>
|
|
82
|
+
</CollapsiblePrimitive.Trigger>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function ReasoningContent({
|
|
87
|
+
className,
|
|
88
|
+
children,
|
|
89
|
+
...props
|
|
90
|
+
}: ComponentPropsWithRef<typeof CollapsiblePrimitive.Content>) {
|
|
91
|
+
return (
|
|
92
|
+
<CollapsiblePrimitive.Content
|
|
93
|
+
data-slot="reasoning-content"
|
|
94
|
+
className={cn(
|
|
95
|
+
"overflow-hidden",
|
|
96
|
+
"data-[state=closed]:animate-accordion-close data-[state=open]:animate-accordion-open",
|
|
97
|
+
className,
|
|
98
|
+
)}
|
|
99
|
+
{...props}
|
|
100
|
+
>
|
|
101
|
+
<div className="mt-2 border-l-2 border-border pl-3 text-sm whitespace-pre-wrap text-muted-foreground">
|
|
102
|
+
{children}
|
|
103
|
+
</div>
|
|
104
|
+
</CollapsiblePrimitive.Content>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "ai-reasoning",
|
|
5
|
+
title: "AI Reasoning",
|
|
6
|
+
description: "A collapsible disclosure for the model's reasoning.",
|
|
7
|
+
category: "ai",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: ["radix-ui"],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["ai-reasoning.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
"A standard disclosure with aria-expanded on the trigger. Collapsed by default because " +
|
|
14
|
+
"reasoning is supporting material — giving it the same weight as the answer buries the " +
|
|
15
|
+
"answer. The trigger's label changes while reasoning streams, so its accessible name matches " +
|
|
16
|
+
"what is happening.",
|
|
17
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Decorator, Meta, StoryObj } from "@storybook/react-vite";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
|
|
4
|
+
import { Response, ThinkingIndicator } from "./ai-response";
|
|
5
|
+
|
|
6
|
+
const FULL =
|
|
7
|
+
"Streaming works one token at a time. The caret marks where the text stops, and nothing is announced as it arrives — a live region firing on every token is unusable with a screen reader.";
|
|
8
|
+
|
|
9
|
+
/** Named so its type is nameable in declaration output (TS2883). */
|
|
10
|
+
const withFixedWidth: Decorator = (Story) => (
|
|
11
|
+
<div className="w-[32rem]">
|
|
12
|
+
<Story />
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: "AI/Response",
|
|
18
|
+
component: Response,
|
|
19
|
+
args: { streaming: false, children: FULL },
|
|
20
|
+
argTypes: { streaming: { control: "boolean" } },
|
|
21
|
+
decorators: [withFixedWidth],
|
|
22
|
+
} satisfies Meta<typeof Response>;
|
|
23
|
+
|
|
24
|
+
export default meta;
|
|
25
|
+
type Story = StoryObj<typeof meta>;
|
|
26
|
+
|
|
27
|
+
export const Default: Story = {};
|
|
28
|
+
|
|
29
|
+
export const Streaming: Story = {
|
|
30
|
+
args: { streaming: true, children: "Streaming works one token at a time. The caret" },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** The real thing: text arriving, then settling. */
|
|
34
|
+
export const Live: Story = {
|
|
35
|
+
parameters: { controls: { disable: true } },
|
|
36
|
+
render: function Live() {
|
|
37
|
+
const [length, setLength] = useState(0);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const timer = setInterval(() => {
|
|
41
|
+
setLength((current) => (current >= FULL.length ? 0 : current + 2));
|
|
42
|
+
}, 40);
|
|
43
|
+
return () => {
|
|
44
|
+
clearInterval(timer);
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const done = length >= FULL.length;
|
|
49
|
+
return <Response streaming={!done}>{FULL.slice(0, length)}</Response>;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Before the first token there is nothing to put a caret after. */
|
|
54
|
+
export const Thinking: Story = {
|
|
55
|
+
parameters: { controls: { disable: true } },
|
|
56
|
+
render: () => <ThinkingIndicator />,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const WithRenderedMarkdown: Story = {
|
|
60
|
+
parameters: { controls: { disable: true } },
|
|
61
|
+
render: () => (
|
|
62
|
+
<Response>
|
|
63
|
+
<p>Three things matter here:</p>
|
|
64
|
+
<ul>
|
|
65
|
+
<li>
|
|
66
|
+
The transcript is a <code>list</code>, not a live region.
|
|
67
|
+
</li>
|
|
68
|
+
<li>State is announced; content is not.</li>
|
|
69
|
+
<li>
|
|
70
|
+
See <a href="#a11y">the accessibility notes</a>.
|
|
71
|
+
</li>
|
|
72
|
+
</ul>
|
|
73
|
+
</Response>
|
|
74
|
+
),
|
|
75
|
+
};
|