@adea-ai/ui 0.140.0 → 0.142.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/dist/components/composites/appearance-editor/appearance-editor.js +2 -2
- package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
- package/dist/components/composites/catalog-browser/catalog-browser-group.js +1 -1
- package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts +56 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.d.ts.map +1 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.js +117 -0
- package/dist/components/composites/chain-of-thought/chain-of-thought.js.map +1 -0
- package/dist/components/composites/chain-of-thought/index.d.ts +2 -0
- package/dist/components/composites/chain-of-thought/index.d.ts.map +1 -0
- package/dist/components/composites/chain-of-thought/index.js +2 -0
- package/dist/components/composites/chat/chat.d.ts +67 -0
- package/dist/components/composites/chat/chat.d.ts.map +1 -0
- package/dist/components/composites/chat/chat.js +179 -0
- package/dist/components/composites/chat/chat.js.map +1 -0
- package/dist/components/composites/chat/index.d.ts +2 -0
- package/dist/components/composites/chat/index.d.ts.map +1 -0
- package/dist/components/composites/chat/index.js +2 -0
- package/dist/components/composites/checkpoint/checkpoint-model.d.ts +34 -0
- package/dist/components/composites/checkpoint/checkpoint-model.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint-model.js +48 -0
- package/dist/components/composites/checkpoint/checkpoint-model.js.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint.d.ts +48 -0
- package/dist/components/composites/checkpoint/checkpoint.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/checkpoint.js +160 -0
- package/dist/components/composites/checkpoint/checkpoint.js.map +1 -0
- package/dist/components/composites/checkpoint/index.d.ts +3 -0
- package/dist/components/composites/checkpoint/index.d.ts.map +1 -0
- package/dist/components/composites/checkpoint/index.js +3 -0
- package/dist/components/composites/confirmation/confirmation-model.d.ts +45 -0
- package/dist/components/composites/confirmation/confirmation-model.d.ts.map +1 -0
- package/dist/components/composites/confirmation/confirmation-model.js +51 -0
- package/dist/components/composites/confirmation/confirmation-model.js.map +1 -0
- package/dist/components/composites/confirmation/confirmation.d.ts +72 -0
- package/dist/components/composites/confirmation/confirmation.d.ts.map +1 -0
- package/dist/components/composites/confirmation/confirmation.js +300 -0
- package/dist/components/composites/confirmation/confirmation.js.map +1 -0
- package/dist/components/composites/confirmation/index.d.ts +3 -0
- package/dist/components/composites/confirmation/index.d.ts.map +1 -0
- package/dist/components/composites/confirmation/index.js +3 -0
- package/dist/components/composites/context/context-model.d.ts +69 -0
- package/dist/components/composites/context/context-model.d.ts.map +1 -0
- package/dist/components/composites/context/context-model.js +122 -0
- package/dist/components/composites/context/context-model.js.map +1 -0
- package/dist/components/composites/context/context.d.ts +38 -0
- package/dist/components/composites/context/context.d.ts.map +1 -0
- package/dist/components/composites/context/context.js +234 -0
- package/dist/components/composites/context/context.js.map +1 -0
- package/dist/components/composites/context/index.d.ts +3 -0
- package/dist/components/composites/context/index.d.ts.map +1 -0
- package/dist/components/composites/context/index.js +3 -0
- package/dist/components/composites/file-tree/build-file-tree.d.ts +138 -0
- package/dist/components/composites/file-tree/build-file-tree.d.ts.map +1 -0
- package/dist/components/composites/file-tree/build-file-tree.js +325 -0
- package/dist/components/composites/file-tree/build-file-tree.js.map +1 -0
- package/dist/components/composites/file-tree/file-tree.d.ts +74 -0
- package/dist/components/composites/file-tree/file-tree.d.ts.map +1 -0
- package/dist/components/composites/file-tree/file-tree.js +389 -0
- package/dist/components/composites/file-tree/file-tree.js.map +1 -0
- package/dist/components/composites/file-tree/index.d.ts +3 -0
- package/dist/components/composites/file-tree/index.d.ts.map +1 -0
- package/dist/components/composites/file-tree/index.js +3 -0
- package/dist/components/composites/inline-citation/citation.d.ts +37 -0
- package/dist/components/composites/inline-citation/citation.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/citation.js +52 -0
- package/dist/components/composites/inline-citation/citation.js.map +1 -0
- package/dist/components/composites/inline-citation/index.d.ts +3 -0
- package/dist/components/composites/inline-citation/index.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/index.js +3 -0
- package/dist/components/composites/inline-citation/inline-citation.d.ts +64 -0
- package/dist/components/composites/inline-citation/inline-citation.d.ts.map +1 -0
- package/dist/components/composites/inline-citation/inline-citation.js +272 -0
- package/dist/components/composites/inline-citation/inline-citation.js.map +1 -0
- package/dist/components/composites/message-scroller/index.d.ts +3 -0
- package/dist/components/composites/message-scroller/index.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/index.js +3 -0
- package/dist/components/composites/message-scroller/message-scroller.d.ts +55 -0
- package/dist/components/composites/message-scroller/message-scroller.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/message-scroller.js +201 -0
- package/dist/components/composites/message-scroller/message-scroller.js.map +1 -0
- package/dist/components/composites/message-scroller/scroll-anchor.d.ts +66 -0
- package/dist/components/composites/message-scroller/scroll-anchor.d.ts.map +1 -0
- package/dist/components/composites/message-scroller/scroll-anchor.js +122 -0
- package/dist/components/composites/message-scroller/scroll-anchor.js.map +1 -0
- package/dist/components/composites/model-selector/index.d.ts +3 -0
- package/dist/components/composites/model-selector/index.d.ts.map +1 -0
- package/dist/components/composites/model-selector/index.js +3 -0
- package/dist/components/composites/model-selector/model-selector.d.ts +55 -0
- package/dist/components/composites/model-selector/model-selector.d.ts.map +1 -0
- package/dist/components/composites/model-selector/model-selector.js +490 -0
- package/dist/components/composites/model-selector/model-selector.js.map +1 -0
- package/dist/components/composites/model-selector/models.d.ts +51 -0
- package/dist/components/composites/model-selector/models.d.ts.map +1 -0
- package/dist/components/composites/model-selector/models.js +71 -0
- package/dist/components/composites/model-selector/models.js.map +1 -0
- package/dist/components/composites/plan/index.d.ts +2 -0
- package/dist/components/composites/plan/index.d.ts.map +1 -0
- package/dist/components/composites/plan/index.js +2 -0
- package/dist/components/composites/plan/plan.d.ts +61 -0
- package/dist/components/composites/plan/plan.d.ts.map +1 -0
- package/dist/components/composites/plan/plan.js +130 -0
- package/dist/components/composites/plan/plan.js.map +1 -0
- package/dist/components/composites/queue/index.d.ts +2 -0
- package/dist/components/composites/queue/index.d.ts.map +1 -0
- package/dist/components/composites/queue/index.js +2 -0
- package/dist/components/composites/queue/queue.d.ts +77 -0
- package/dist/components/composites/queue/queue.d.ts.map +1 -0
- package/dist/components/composites/queue/queue.js +271 -0
- package/dist/components/composites/queue/queue.js.map +1 -0
- package/dist/components/composites/reasoning/index.d.ts +2 -0
- package/dist/components/composites/reasoning/index.d.ts.map +1 -0
- package/dist/components/composites/reasoning/index.js +2 -0
- package/dist/components/composites/reasoning/reasoning.d.ts +62 -0
- package/dist/components/composites/reasoning/reasoning.d.ts.map +1 -0
- package/dist/components/composites/reasoning/reasoning.js +156 -0
- package/dist/components/composites/reasoning/reasoning.js.map +1 -0
- package/dist/components/composites/sources/index.d.ts +3 -0
- package/dist/components/composites/sources/index.d.ts.map +1 -0
- package/dist/components/composites/sources/index.js +3 -0
- package/dist/components/composites/sources/source.d.ts +46 -0
- package/dist/components/composites/sources/source.d.ts.map +1 -0
- package/dist/components/composites/sources/source.js +74 -0
- package/dist/components/composites/sources/source.js.map +1 -0
- package/dist/components/composites/sources/sources.d.ts +45 -0
- package/dist/components/composites/sources/sources.d.ts.map +1 -0
- package/dist/components/composites/sources/sources.js +175 -0
- package/dist/components/composites/sources/sources.js.map +1 -0
- package/dist/components/composites/stack-trace/index.d.ts +3 -0
- package/dist/components/composites/stack-trace/index.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/index.js +3 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.d.ts +118 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.js +376 -0
- package/dist/components/composites/stack-trace/parse-stack-trace.js.map +1 -0
- package/dist/components/composites/stack-trace/stack-trace.d.ts +63 -0
- package/dist/components/composites/stack-trace/stack-trace.d.ts.map +1 -0
- package/dist/components/composites/stack-trace/stack-trace.js +491 -0
- package/dist/components/composites/stack-trace/stack-trace.js.map +1 -0
- package/dist/components/composites/subagent/index.d.ts +2 -0
- package/dist/components/composites/subagent/index.d.ts.map +1 -0
- package/dist/components/composites/subagent/index.js +2 -0
- package/dist/components/composites/subagent/subagent.d.ts +55 -0
- package/dist/components/composites/subagent/subagent.d.ts.map +1 -0
- package/dist/components/composites/subagent/subagent.js +138 -0
- package/dist/components/composites/subagent/subagent.js.map +1 -0
- package/dist/components/composites/suggestion/index.d.ts +2 -0
- package/dist/components/composites/suggestion/index.d.ts.map +1 -0
- package/dist/components/composites/suggestion/index.js +2 -0
- package/dist/components/composites/suggestion/suggestion.d.ts +37 -0
- package/dist/components/composites/suggestion/suggestion.d.ts.map +1 -0
- package/dist/components/composites/suggestion/suggestion.js +100 -0
- package/dist/components/composites/suggestion/suggestion.js.map +1 -0
- package/dist/components/composites/task/index.d.ts +2 -0
- package/dist/components/composites/task/index.d.ts.map +1 -0
- package/dist/components/composites/task/index.js +2 -0
- package/dist/components/composites/task/task.d.ts +96 -0
- package/dist/components/composites/task/task.d.ts.map +1 -0
- package/dist/components/composites/task/task.js +311 -0
- package/dist/components/composites/task/task.js.map +1 -0
- package/dist/components/composites/terminal/ansi.d.ts +101 -0
- package/dist/components/composites/terminal/ansi.d.ts.map +1 -0
- package/dist/components/composites/terminal/ansi.js +544 -0
- package/dist/components/composites/terminal/ansi.js.map +1 -0
- package/dist/components/composites/terminal/index.d.ts +4 -0
- package/dist/components/composites/terminal/index.d.ts.map +1 -0
- package/dist/components/composites/terminal/index.js +4 -0
- package/dist/components/composites/terminal/terminal-model.d.ts +63 -0
- package/dist/components/composites/terminal/terminal-model.d.ts.map +1 -0
- package/dist/components/composites/terminal/terminal-model.js +69 -0
- package/dist/components/composites/terminal/terminal-model.js.map +1 -0
- package/dist/components/composites/terminal/terminal.d.ts +88 -0
- package/dist/components/composites/terminal/terminal.d.ts.map +1 -0
- package/dist/components/composites/terminal/terminal.js +500 -0
- package/dist/components/composites/terminal/terminal.js.map +1 -0
- package/dist/components/composites/test-results/index.d.ts +3 -0
- package/dist/components/composites/test-results/index.d.ts.map +1 -0
- package/dist/components/composites/test-results/index.js +3 -0
- package/dist/components/composites/test-results/test-results-model.d.ts +154 -0
- package/dist/components/composites/test-results/test-results-model.d.ts.map +1 -0
- package/dist/components/composites/test-results/test-results-model.js +252 -0
- package/dist/components/composites/test-results/test-results-model.js.map +1 -0
- package/dist/components/composites/test-results/test-results.d.ts +60 -0
- package/dist/components/composites/test-results/test-results.d.ts.map +1 -0
- package/dist/components/composites/test-results/test-results.js +631 -0
- package/dist/components/composites/test-results/test-results.js.map +1 -0
- package/dist/components/composites/tool/format-tool-value.d.ts +37 -0
- package/dist/components/composites/tool/format-tool-value.d.ts.map +1 -0
- package/dist/components/composites/tool/format-tool-value.js +135 -0
- package/dist/components/composites/tool/format-tool-value.js.map +1 -0
- package/dist/components/composites/tool/index.d.ts +3 -0
- package/dist/components/composites/tool/index.d.ts.map +1 -0
- package/dist/components/composites/tool/index.js +3 -0
- package/dist/components/composites/tool/tool.d.ts +69 -0
- package/dist/components/composites/tool/tool.d.ts.map +1 -0
- package/dist/components/composites/tool/tool.js +214 -0
- package/dist/components/composites/tool/tool.js.map +1 -0
- package/dist/components/composites/update-dialog/update-dialog.js +1 -1
- package/dist/components/conversation/conversation-surface.d.ts +7 -0
- package/dist/components/conversation/conversation-surface.d.ts.map +1 -1
- package/dist/components/conversation/conversation-surface.js +2 -0
- package/dist/components/conversation/conversation-surface.js.map +1 -1
- package/dist/components/conversation/scroll-follow-core.d.ts +24 -0
- package/dist/components/conversation/scroll-follow-core.d.ts.map +1 -1
- package/dist/components/conversation/scroll-follow-core.js +23 -1
- package/dist/components/conversation/scroll-follow-core.js.map +1 -1
- package/dist/components/conversation/scroll-follow.d.ts +3 -0
- package/dist/components/conversation/scroll-follow.d.ts.map +1 -1
- package/dist/components/conversation/scroll-follow.js +80 -1
- package/dist/components/conversation/scroll-follow.js.map +1 -1
- package/dist/components/ui/attachment/attachment.d.ts +58 -0
- package/dist/components/ui/attachment/attachment.d.ts.map +1 -0
- package/dist/components/ui/attachment/attachment.js +279 -0
- package/dist/components/ui/attachment/attachment.js.map +1 -0
- package/dist/components/ui/attachment/index.d.ts +2 -0
- package/dist/components/ui/attachment/index.d.ts.map +1 -0
- package/dist/components/ui/attachment/index.js +2 -0
- package/dist/components/ui/badge/badge.d.ts +1 -1
- package/dist/components/ui/bubble/bubble.d.ts +33 -0
- package/dist/components/ui/bubble/bubble.d.ts.map +1 -0
- package/dist/components/ui/bubble/bubble.js +95 -0
- package/dist/components/ui/bubble/bubble.js.map +1 -0
- package/dist/components/ui/bubble/index.d.ts +2 -0
- package/dist/components/ui/bubble/index.d.ts.map +1 -0
- package/dist/components/ui/bubble/index.js +2 -0
- package/dist/components/ui/button/button.d.ts +1 -1
- package/dist/components/ui/code-block/code-block.d.ts +56 -3
- package/dist/components/ui/code-block/code-block.d.ts.map +1 -1
- package/dist/components/ui/code-block/code-block.js +231 -50
- package/dist/components/ui/code-block/code-block.js.map +1 -1
- package/dist/components/ui/code-block/index.d.ts +1 -1
- package/dist/components/ui/code-block/index.d.ts.map +1 -1
- package/dist/components/ui/code-block/index.js +2 -2
- package/dist/components/ui/field/number-field.d.ts +21 -4
- package/dist/components/ui/field/number-field.d.ts.map +1 -1
- package/dist/components/ui/field/number-field.js +22 -11
- package/dist/components/ui/field/number-field.js.map +1 -1
- package/dist/components/ui/marker/index.d.ts +2 -0
- package/dist/components/ui/marker/index.d.ts.map +1 -0
- package/dist/components/ui/marker/index.js +2 -0
- package/dist/components/ui/marker/marker.d.ts +35 -0
- package/dist/components/ui/marker/marker.d.ts.map +1 -0
- package/dist/components/ui/marker/marker.js +123 -0
- package/dist/components/ui/marker/marker.js.map +1 -0
- package/dist/components/ui/message/cite-ranges.d.ts +42 -0
- package/dist/components/ui/message/cite-ranges.d.ts.map +1 -0
- package/dist/components/ui/message/cite-ranges.js +105 -0
- package/dist/components/ui/message/cite-ranges.js.map +1 -0
- package/dist/components/ui/message/index.d.ts +4 -0
- package/dist/components/ui/message/index.d.ts.map +1 -0
- package/dist/components/ui/message/index.js +4 -0
- package/dist/components/ui/message/message.d.ts +95 -0
- package/dist/components/ui/message/message.d.ts.map +1 -0
- package/dist/components/ui/message/message.js +443 -0
- package/dist/components/ui/message/message.js.map +1 -0
- package/dist/components/ui/message/parse-message-text.d.ts +93 -0
- package/dist/components/ui/message/parse-message-text.d.ts.map +1 -0
- package/dist/components/ui/message/parse-message-text.js +365 -0
- package/dist/components/ui/message/parse-message-text.js.map +1 -0
- package/dist/components/ui/questionnaire/index.d.ts +2 -0
- package/dist/components/ui/questionnaire/index.d.ts.map +1 -0
- package/dist/components/ui/questionnaire/index.js +2 -0
- package/dist/components/ui/questionnaire/questionnaire.d.ts +83 -0
- package/dist/components/ui/questionnaire/questionnaire.d.ts.map +1 -0
- package/dist/components/ui/questionnaire/questionnaire.js +470 -0
- package/dist/components/ui/questionnaire/questionnaire.js.map +1 -0
- package/dist/components/ui/status-chip/status-chip.d.ts +1 -1
- package/dist/components/ui/switch/switch.js +11 -11
- package/dist/components/ui/switch/switch.js.map +1 -1
- package/dist/components/ui/trace/index.d.ts +2 -0
- package/dist/components/ui/trace/index.d.ts.map +1 -0
- package/dist/components/ui/trace/index.js +2 -0
- package/dist/components/ui/trace/trace.d.ts +72 -0
- package/dist/components/ui/trace/trace.d.ts.map +1 -0
- package/dist/components/ui/trace/trace.js +340 -0
- package/dist/components/ui/trace/trace.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +46 -5
- package/dist/r/attachment.json +25 -0
- package/dist/r/bubble.json +22 -0
- package/dist/r/chain-of-thought.json +26 -0
- package/dist/r/chat.json +24 -0
- package/dist/r/checkpoint.json +35 -0
- package/dist/r/confirmation.json +34 -0
- package/dist/r/context.json +33 -0
- package/dist/r/file-tree.json +32 -0
- package/dist/r/inline-citation.json +35 -0
- package/dist/r/marker.json +22 -0
- package/dist/r/message-scroller.json +31 -0
- package/dist/r/message.json +33 -0
- package/dist/r/model-selector.json +34 -0
- package/dist/r/plan.json +26 -0
- package/dist/r/questionnaire.json +28 -0
- package/dist/r/queue.json +26 -0
- package/dist/r/reasoning.json +26 -0
- package/dist/r/registry.json +811 -52
- package/dist/r/sources.json +32 -0
- package/dist/r/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
- package/dist/r/src/components/composites/chain-of-thought/index.ts +11 -0
- package/dist/r/src/components/composites/chat/chat.tsx +190 -0
- package/dist/r/src/components/composites/chat/index.ts +11 -0
- package/dist/r/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
- package/dist/r/src/components/composites/checkpoint/checkpoint.tsx +214 -0
- package/dist/r/src/components/composites/checkpoint/index.ts +8 -0
- package/dist/r/src/components/composites/confirmation/confirmation-model.ts +83 -0
- package/dist/r/src/components/composites/confirmation/confirmation.tsx +311 -0
- package/dist/r/src/components/composites/confirmation/index.ts +9 -0
- package/dist/r/src/components/composites/context/context-model.ts +168 -0
- package/dist/r/src/components/composites/context/context.tsx +187 -0
- package/dist/r/src/components/composites/context/index.ts +18 -0
- package/dist/r/src/components/composites/file-tree/build-file-tree.ts +456 -0
- package/dist/r/src/components/composites/file-tree/file-tree.tsx +405 -0
- package/dist/r/src/components/composites/file-tree/index.ts +25 -0
- package/dist/r/src/components/composites/inline-citation/citation.ts +78 -0
- package/dist/r/src/components/composites/inline-citation/index.ts +9 -0
- package/dist/r/src/components/composites/inline-citation/inline-citation.tsx +285 -0
- package/dist/r/src/components/composites/message-scroller/index.ts +2 -0
- package/dist/r/src/components/composites/message-scroller/message-scroller.tsx +301 -0
- package/dist/r/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
- package/dist/r/src/components/composites/model-selector/index.ts +14 -0
- package/dist/r/src/components/composites/model-selector/model-selector.tsx +420 -0
- package/dist/r/src/components/composites/model-selector/models.ts +103 -0
- package/dist/r/src/components/composites/plan/index.ts +1 -0
- package/dist/r/src/components/composites/plan/plan.tsx +155 -0
- package/dist/r/src/components/composites/queue/index.ts +10 -0
- package/dist/r/src/components/composites/queue/queue.tsx +264 -0
- package/dist/r/src/components/composites/reasoning/index.ts +1 -0
- package/dist/r/src/components/composites/reasoning/reasoning.tsx +176 -0
- package/dist/r/src/components/composites/sources/index.ts +11 -0
- package/dist/r/src/components/composites/sources/source.ts +116 -0
- package/dist/r/src/components/composites/sources/sources.tsx +163 -0
- package/dist/r/src/components/composites/stack-trace/index.ts +19 -0
- package/dist/r/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
- package/dist/r/src/components/composites/stack-trace/stack-trace.tsx +395 -0
- package/dist/r/src/components/composites/subagent/index.ts +1 -0
- package/dist/r/src/components/composites/subagent/subagent.tsx +159 -0
- package/dist/r/src/components/composites/suggestion/index.ts +1 -0
- package/dist/r/src/components/composites/suggestion/suggestion.tsx +140 -0
- package/dist/r/src/components/composites/task/index.ts +14 -0
- package/dist/r/src/components/composites/task/task.tsx +317 -0
- package/dist/r/src/components/composites/terminal/ansi.ts +674 -0
- package/dist/r/src/components/composites/terminal/index.ts +20 -0
- package/dist/r/src/components/composites/terminal/terminal-model.ts +111 -0
- package/dist/r/src/components/composites/terminal/terminal.tsx +574 -0
- package/dist/r/src/components/composites/test-results/index.ts +20 -0
- package/dist/r/src/components/composites/test-results/test-results-model.ts +368 -0
- package/dist/r/src/components/composites/test-results/test-results.tsx +586 -0
- package/dist/r/src/components/composites/tool/format-tool-value.ts +221 -0
- package/dist/r/src/components/composites/tool/index.ts +2 -0
- package/dist/r/src/components/composites/tool/tool.tsx +228 -0
- package/dist/r/src/components/conversation/conversation-surface.tsx +9 -0
- package/dist/r/src/components/conversation/scroll-follow-core.ts +31 -0
- package/dist/r/src/components/conversation/scroll-follow.ts +92 -0
- package/dist/r/src/components/ui/attachment/attachment.tsx +282 -0
- package/dist/r/src/components/ui/attachment/index.ts +10 -0
- package/dist/r/src/components/ui/bubble/bubble.tsx +86 -0
- package/dist/r/src/components/ui/bubble/index.ts +1 -0
- package/dist/r/src/components/ui/code-block/code-block.tsx +256 -26
- package/dist/r/src/components/ui/code-block/index.ts +9 -1
- package/dist/r/src/components/ui/field/number-field.tsx +51 -14
- package/dist/r/src/components/ui/marker/index.ts +1 -0
- package/dist/r/src/components/ui/marker/marker.tsx +90 -0
- package/dist/r/src/components/ui/message/cite-ranges.ts +144 -0
- package/dist/r/src/components/ui/message/index.ts +23 -0
- package/dist/r/src/components/ui/message/message.tsx +434 -0
- package/dist/r/src/components/ui/message/parse-message-text.ts +450 -0
- package/dist/r/src/components/ui/questionnaire/index.ts +10 -0
- package/dist/r/src/components/ui/questionnaire/questionnaire.tsx +446 -0
- package/dist/r/src/components/ui/trace/index.ts +9 -0
- package/dist/r/src/components/ui/trace/trace.tsx +334 -0
- package/dist/r/src/styles/base.css +34 -0
- package/dist/r/stack-trace.json +32 -0
- package/dist/r/subagent.json +27 -0
- package/dist/r/suggestion.json +24 -0
- package/dist/r/task.json +28 -0
- package/dist/r/terminal.json +35 -0
- package/dist/r/test-results.json +33 -0
- package/dist/r/tool.json +31 -0
- package/dist/r/trace.json +25 -0
- package/package.json +6 -3
- package/registry.json +811 -52
- package/src/components/composites/chain-of-thought/chain-of-thought.tsx +141 -0
- package/src/components/composites/chain-of-thought/index.ts +11 -0
- package/src/components/composites/chat/chat.tsx +190 -0
- package/src/components/composites/chat/index.ts +11 -0
- package/src/components/composites/checkpoint/checkpoint-model.ts +71 -0
- package/src/components/composites/checkpoint/checkpoint.tsx +214 -0
- package/src/components/composites/checkpoint/index.ts +8 -0
- package/src/components/composites/confirmation/confirmation-model.ts +83 -0
- package/src/components/composites/confirmation/confirmation.tsx +311 -0
- package/src/components/composites/confirmation/index.ts +9 -0
- package/src/components/composites/context/context-model.ts +168 -0
- package/src/components/composites/context/context.tsx +187 -0
- package/src/components/composites/context/index.ts +18 -0
- package/src/components/composites/file-tree/build-file-tree.ts +456 -0
- package/src/components/composites/file-tree/file-tree.tsx +405 -0
- package/src/components/composites/file-tree/index.ts +25 -0
- package/src/components/composites/inline-citation/citation.ts +78 -0
- package/src/components/composites/inline-citation/index.ts +9 -0
- package/src/components/composites/inline-citation/inline-citation.tsx +285 -0
- package/src/components/composites/message-scroller/index.ts +2 -0
- package/src/components/composites/message-scroller/message-scroller.tsx +301 -0
- package/src/components/composites/message-scroller/scroll-anchor.ts +170 -0
- package/src/components/composites/model-selector/index.ts +14 -0
- package/src/components/composites/model-selector/model-selector.tsx +420 -0
- package/src/components/composites/model-selector/models.ts +103 -0
- package/src/components/composites/plan/index.ts +1 -0
- package/src/components/composites/plan/plan.tsx +155 -0
- package/src/components/composites/queue/index.ts +10 -0
- package/src/components/composites/queue/queue.tsx +264 -0
- package/src/components/composites/reasoning/index.ts +1 -0
- package/src/components/composites/reasoning/reasoning.tsx +176 -0
- package/src/components/composites/sources/index.ts +11 -0
- package/src/components/composites/sources/source.ts +116 -0
- package/src/components/composites/sources/sources.tsx +163 -0
- package/src/components/composites/stack-trace/index.ts +19 -0
- package/src/components/composites/stack-trace/parse-stack-trace.ts +507 -0
- package/src/components/composites/stack-trace/stack-trace.tsx +395 -0
- package/src/components/composites/subagent/index.ts +1 -0
- package/src/components/composites/subagent/subagent.tsx +159 -0
- package/src/components/composites/suggestion/index.ts +1 -0
- package/src/components/composites/suggestion/suggestion.tsx +140 -0
- package/src/components/composites/task/index.ts +14 -0
- package/src/components/composites/task/task.tsx +317 -0
- package/src/components/composites/terminal/ansi.ts +674 -0
- package/src/components/composites/terminal/index.ts +20 -0
- package/src/components/composites/terminal/terminal-model.ts +111 -0
- package/src/components/composites/terminal/terminal.tsx +574 -0
- package/src/components/composites/test-results/index.ts +20 -0
- package/src/components/composites/test-results/test-results-model.ts +368 -0
- package/src/components/composites/test-results/test-results.tsx +586 -0
- package/src/components/composites/tool/format-tool-value.ts +221 -0
- package/src/components/composites/tool/index.ts +2 -0
- package/src/components/composites/tool/tool.tsx +228 -0
- package/src/components/conversation/conversation-surface.tsx +9 -0
- package/src/components/conversation/scroll-follow-core.ts +31 -0
- package/src/components/conversation/scroll-follow.ts +92 -0
- package/src/components/ui/attachment/attachment.tsx +282 -0
- package/src/components/ui/attachment/index.ts +10 -0
- package/src/components/ui/bubble/bubble.tsx +86 -0
- package/src/components/ui/bubble/index.ts +1 -0
- package/src/components/ui/code-block/code-block.tsx +256 -26
- package/src/components/ui/code-block/index.ts +9 -1
- package/src/components/ui/field/number-field.tsx +51 -14
- package/src/components/ui/marker/index.ts +1 -0
- package/src/components/ui/marker/marker.tsx +90 -0
- package/src/components/ui/message/cite-ranges.ts +144 -0
- package/src/components/ui/message/index.ts +23 -0
- package/src/components/ui/message/message.tsx +434 -0
- package/src/components/ui/message/parse-message-text.ts +450 -0
- package/src/components/ui/questionnaire/index.ts +10 -0
- package/src/components/ui/questionnaire/questionnaire.tsx +446 -0
- package/src/components/ui/trace/index.ts +9 -0
- package/src/components/ui/trace/trace.tsx +334 -0
- package/src/index.ts +26 -0
- package/src/styles/base.css +34 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
createEffect,
|
|
2
3
|
createMemo,
|
|
3
4
|
createSignal,
|
|
4
5
|
For,
|
|
6
|
+
on,
|
|
7
|
+
onCleanup,
|
|
8
|
+
onMount,
|
|
5
9
|
Show,
|
|
6
10
|
splitProps,
|
|
7
11
|
type ComponentProps,
|
|
@@ -38,8 +42,9 @@ import { cn } from '#lib/utils'
|
|
|
38
42
|
* **The scroller is focusable and named.** A horizontally scrollable region has
|
|
39
43
|
* to be reachable by keyboard — this is axe's `scrollable-region-focusable`, and
|
|
40
44
|
* a region that scrolls but cannot be focused is a WCAG 2.1.1 failure. It is a
|
|
41
|
-
* `
|
|
42
|
-
*
|
|
45
|
+
* labelled `group` rather than a bare `tabindex`, so the tab stop announces what
|
|
46
|
+
* it is. It is deliberately not a `region` landmark: a transcript holds many
|
|
47
|
+
* blocks, often in one language, and repeated landmarks of one name are noise.
|
|
43
48
|
*
|
|
44
49
|
* **Resolving a streaming block must not move the reader.** When `complete` is
|
|
45
50
|
* false the block shows the code it has plus a generating indicator; the
|
|
@@ -47,8 +52,35 @@ import { cn } from '#lib/utils'
|
|
|
47
52
|
* block that grows the moment its content resolves shifts everything below it.
|
|
48
53
|
* If a caller's `highlight` changes the line box, that is the caller's height to
|
|
49
54
|
* hold — `lineHeight` is a prop for exactly that reason.
|
|
55
|
+
*
|
|
56
|
+
* ## Output, not only source
|
|
57
|
+
*
|
|
58
|
+
* The same surface carries terminal output, logs and diffs inside an agent's
|
|
59
|
+
* activity, so it also:
|
|
60
|
+
*
|
|
61
|
+
* - **loads its highlighter lazily** (`loadHighlight`). The grammar is fetched
|
|
62
|
+
* only for a block that is complete and has a language, the block renders plain
|
|
63
|
+
* until it arrives, and a loader that returns nothing — an unknown language, a
|
|
64
|
+
* failed fetch — leaves the plain text in place without an error. Highlighting
|
|
65
|
+
* a block on every streamed delta would re-tokenise the whole thing per token,
|
|
66
|
+
* so a streaming block stays plain until `complete`.
|
|
67
|
+
* - **marks lines** (`lineMarks`) as added, removed, highlighted or failed. A mark
|
|
68
|
+
* is carried by a gutter glyph and by `<ins>`/`<del>` for the two that change
|
|
69
|
+
* text, never by colour alone, and the glyph is not selectable so a copied
|
|
70
|
+
* selection stays the source.
|
|
71
|
+
* - **copies the source exactly.** The copy button writes `code` as given: no
|
|
72
|
+
* trailing-newline trimming, no line numbers, no gutter glyphs, and the whole
|
|
73
|
+
* block even when only part of it is rendered (`lineLimit`).
|
|
74
|
+
* - **bounds a large render.** Past `lineLimit` lines the per-line renderer and a
|
|
75
|
+
* highlighted render show the first lines and a control to show the rest,
|
|
76
|
+
* because tens of thousands of row elements, or a tokenizer run over all of
|
|
77
|
+
* them, are a freeze, not a transcript. Which renderer is in use is decided
|
|
78
|
+
* at the time, so a highlighter that loads late takes over the bound from the
|
|
79
|
+
* per-line rows and the note below the block always describes what is drawn.
|
|
80
|
+
* The plain renderer is a single text node and needs no limit.
|
|
81
|
+
* - **comes in a small size** (`size="sm"`) for tool output inside a Trace line.
|
|
50
82
|
*/
|
|
51
|
-
export type CodeBlockProps = Omit<ComponentProps<'div'>, 'children'> & {
|
|
83
|
+
export type CodeBlockProps = Omit<ComponentProps<'div'>, 'children' | 'onCopy'> & {
|
|
52
84
|
code: string
|
|
53
85
|
/** The language, shown in the header and used as the region's label. */
|
|
54
86
|
language?: string
|
|
@@ -82,8 +114,35 @@ export type CodeBlockProps = Omit<ComponentProps<'div'>, 'children'> & {
|
|
|
82
114
|
* any `pre` inside `highlight` output; line numbers stay on the first visual line.
|
|
83
115
|
*/
|
|
84
116
|
wrap?: boolean
|
|
117
|
+
/** `sm` is the compact chrome for output nested inside a Trace line. */
|
|
118
|
+
size?: 'default' | 'sm'
|
|
119
|
+
/**
|
|
120
|
+
* Marks on 1-based line numbers. Applies to the per-line renderer, which is
|
|
121
|
+
* used whenever marks or line numbers are present and no highlighter is in use,
|
|
122
|
+
* given as `highlight` or loaded by `loadHighlight`: a highlighter replaces the
|
|
123
|
+
* rows, so the marks and the gutter go with them.
|
|
124
|
+
*/
|
|
125
|
+
lineMarks?: Readonly<Record<number, CodeLineMark>>
|
|
126
|
+
/**
|
|
127
|
+
* Resolve a highlighter for the block's language. Called once the block is
|
|
128
|
+
* complete; resolving to `undefined` (or rejecting) keeps the plain rendering.
|
|
129
|
+
*/
|
|
130
|
+
loadHighlight?: (language: string | undefined) => Promise<CodeHighlighter | undefined>
|
|
131
|
+
/**
|
|
132
|
+
* Lines the per-line and the highlighted renderer show before offering the
|
|
133
|
+
* rest. Default 2000. The plain renderer is one text node and is not limited.
|
|
134
|
+
*/
|
|
135
|
+
lineLimit?: number
|
|
136
|
+
/** Called after each copy attempt with whether the clipboard accepted it. */
|
|
137
|
+
onCopy?: (ok: boolean) => void
|
|
85
138
|
}
|
|
86
139
|
|
|
140
|
+
export type CodeLineMark = 'add' | 'remove' | 'highlight' | 'error'
|
|
141
|
+
export type CodeHighlighter = (code: string) => JSX.Element
|
|
142
|
+
|
|
143
|
+
/** Lines the per-line renderer shows before it offers the rest. */
|
|
144
|
+
export const CODE_BLOCK_LINE_LIMIT = 2_000
|
|
145
|
+
|
|
87
146
|
/** The height a block must exceed before its actions are repeated. */
|
|
88
147
|
export const TALL_CODE_BLOCK_PX = 480
|
|
89
148
|
|
|
@@ -118,6 +177,11 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
118
177
|
'tallThreshold',
|
|
119
178
|
'maxHeight',
|
|
120
179
|
'wrap',
|
|
180
|
+
'size',
|
|
181
|
+
'lineMarks',
|
|
182
|
+
'loadHighlight',
|
|
183
|
+
'lineLimit',
|
|
184
|
+
'onCopy',
|
|
121
185
|
'class',
|
|
122
186
|
'ref',
|
|
123
187
|
])
|
|
@@ -126,9 +190,52 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
126
190
|
const [failed, setFailed] = createSignal(false)
|
|
127
191
|
const [tall, setTall] = createSignal(false)
|
|
128
192
|
|
|
129
|
-
const
|
|
130
|
-
const
|
|
193
|
+
const [loaded, setLoaded] = createSignal<CodeHighlighter>()
|
|
194
|
+
const [showAll, setShowAll] = createSignal(false)
|
|
195
|
+
let bodyElement: HTMLDivElement | undefined
|
|
196
|
+
|
|
197
|
+
// A language string can come from untrusted model output. It is rendered as
|
|
198
|
+
// text, so it cannot inject markup; the cap keeps a pathological one from
|
|
199
|
+
// swallowing the header.
|
|
200
|
+
const language = () => local.language?.trim().slice(0, 40) || undefined
|
|
201
|
+
const label = () => local.title ?? language() ?? 'code'
|
|
202
|
+
const groupLabel = () => (language() ? `${language()} code` : 'code')
|
|
203
|
+
const small = () => local.size === 'sm'
|
|
131
204
|
const lines = createMemo(() => local.code.replace(/\n$/, '').split('\n'))
|
|
205
|
+
const lineLimit = () => local.lineLimit ?? CODE_BLOCK_LINE_LIMIT
|
|
206
|
+
const visibleLines = createMemo(() => (showAll() ? lines() : lines().slice(0, lineLimit())))
|
|
207
|
+
const hiddenLines = () => lines().length - visibleLines().length
|
|
208
|
+
|
|
209
|
+
// Load once the block has stopped changing. `on` keys the effect to the
|
|
210
|
+
// language and completion, not to every streamed character, and a stale
|
|
211
|
+
// resolution (the language changed while the grammar was in flight) is dropped.
|
|
212
|
+
createEffect(
|
|
213
|
+
on(
|
|
214
|
+
() => [local.complete, language(), local.loadHighlight] as const,
|
|
215
|
+
([complete, lang, load]) => {
|
|
216
|
+
setLoaded(undefined)
|
|
217
|
+
if (!complete || !load || local.highlight) return
|
|
218
|
+
let current = true
|
|
219
|
+
onCleanup(() => (current = false))
|
|
220
|
+
// Wrapped, not called bare: a loader that throws before it returns a promise
|
|
221
|
+
// (a bad import path, a missing grammar table) must degrade to plain text
|
|
222
|
+
// like one that rejects, not tear down the tree from inside this effect.
|
|
223
|
+
new Promise<CodeHighlighter | undefined>((resolve) => resolve(load(lang))).then(
|
|
224
|
+
(highlighter) => {
|
|
225
|
+
if (current && highlighter) setLoaded(() => highlighter)
|
|
226
|
+
},
|
|
227
|
+
() => undefined
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
)
|
|
232
|
+
const highlighter = (): CodeHighlighter | undefined => local.highlight ?? loaded()
|
|
233
|
+
// The renderer in use decides everything about the limit, not the props alone:
|
|
234
|
+
// a highlighter that has loaded since the first render replaces the per-line
|
|
235
|
+
// rows, so what is drawn, and what the footer may say, follows `highlighter()`.
|
|
236
|
+
const perLine = () =>
|
|
237
|
+
highlighter() === undefined && (local.showLineNumbers === true || local.lineMarks !== undefined)
|
|
238
|
+
const truncated = () => hiddenLines() > 0 && (highlighter() !== undefined || perLine())
|
|
132
239
|
const maxHeight = () =>
|
|
133
240
|
typeof local.maxHeight === 'number' ? `${local.maxHeight}px` : local.maxHeight
|
|
134
241
|
|
|
@@ -136,15 +243,17 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
136
243
|
const ok = await copyText(local.code)
|
|
137
244
|
setCopied(ok)
|
|
138
245
|
setFailed(!ok)
|
|
246
|
+
local.onCopy?.(ok)
|
|
139
247
|
if (ok) setTimeout(() => setCopied(false), 1500)
|
|
140
248
|
}
|
|
141
249
|
|
|
142
250
|
const Actions = () => (
|
|
143
|
-
<div class="flex items-center gap-1 opacity-0 transition-opacity group-focus-within/code:opacity-100 group-hover/code:opacity-100">
|
|
251
|
+
<div class="flex items-center gap-1 opacity-0 transition-opacity group-focus-within/code:opacity-100 group-hover/code:opacity-100 [@media(hover:none)]:opacity-100">
|
|
144
252
|
{local.actions}
|
|
145
253
|
<Button
|
|
146
254
|
variant="ghost"
|
|
147
255
|
size="icon-2xs"
|
|
256
|
+
touchTarget="comfortable"
|
|
148
257
|
aria-label={copied() ? (local.copiedLabel ?? 'Copied') : (local.copyLabel ?? 'Copy code')}
|
|
149
258
|
title={failed() ? 'Copying is unavailable in this context' : undefined}
|
|
150
259
|
onClick={() => void copy()}
|
|
@@ -158,7 +267,13 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
158
267
|
|
|
159
268
|
return (
|
|
160
269
|
<div
|
|
161
|
-
|
|
270
|
+
data-slot="code-block"
|
|
271
|
+
data-size={local.size ?? 'default'}
|
|
272
|
+
class={cn(
|
|
273
|
+
'group/code overflow-hidden border border-border bg-card',
|
|
274
|
+
small() ? 'rounded-lg' : 'rounded-xl',
|
|
275
|
+
local.class
|
|
276
|
+
)}
|
|
162
277
|
{...rest}
|
|
163
278
|
ref={(element) => {
|
|
164
279
|
// Composed rather than replaced: a caller's ref must survive.
|
|
@@ -166,17 +281,33 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
166
281
|
else if (local.ref) local.ref = element
|
|
167
282
|
// Measured rather than assumed: the caller controls the content, so only
|
|
168
283
|
// the rendered box can say whether the action row has scrolled away.
|
|
284
|
+
// The body is what is watched, not the block: the repeated action row is
|
|
285
|
+
// added to the block, so watching the block made this callback resize the
|
|
286
|
+
// very element it observes, which is a ResizeObserver loop (WebKit reports
|
|
287
|
+
// it as an uncaught "loop completed with undelivered notifications" error).
|
|
288
|
+
// The footer's own height is left out of the measure for the same reason: a
|
|
289
|
+
// block is tall by its content, not by the row that tallness adds.
|
|
169
290
|
const observer = new ResizeObserver(() => {
|
|
170
|
-
|
|
291
|
+
const footer = element.querySelector<HTMLElement>('[data-code-block-footer]')
|
|
292
|
+
setTall(
|
|
293
|
+
element.offsetHeight - (footer?.offsetHeight ?? 0) >
|
|
294
|
+
(local.tallThreshold ?? TALL_CODE_BLOCK_PX)
|
|
295
|
+
)
|
|
296
|
+
})
|
|
297
|
+
onMount(() => {
|
|
298
|
+
if (bodyElement) observer.observe(bodyElement)
|
|
171
299
|
})
|
|
172
|
-
observer.
|
|
300
|
+
onCleanup(() => observer.disconnect())
|
|
173
301
|
}}
|
|
174
302
|
>
|
|
175
|
-
<div
|
|
303
|
+
<div
|
|
304
|
+
class={cn('flex items-center justify-between gap-2', small() ? 'px-2 py-0.5' : 'px-3 py-1')}
|
|
305
|
+
>
|
|
176
306
|
<span class="truncate font-code text-code text-muted-foreground">{label()}</span>
|
|
177
307
|
<Actions />
|
|
178
308
|
</div>
|
|
179
309
|
<div
|
|
310
|
+
ref={(element) => (bodyElement = element)}
|
|
180
311
|
data-slot="code-block-body"
|
|
181
312
|
data-wrap={local.wrap ? '' : undefined}
|
|
182
313
|
class={cn('scroll-fade overflow-x-auto', {
|
|
@@ -187,27 +318,31 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
187
318
|
})}
|
|
188
319
|
style={maxHeight() === undefined ? undefined : { 'max-height': maxHeight() }}
|
|
189
320
|
// A region that scrolls must be focusable, and a tab stop needs a name.
|
|
321
|
+
// A `group`, not a `region`: a landmark with the same role and name as the
|
|
322
|
+
// next block's ("ts code" twice) is a duplicate in the screen reader's
|
|
323
|
+
// landmark list, and a long answer would fill that list with code blocks.
|
|
190
324
|
tabindex="0"
|
|
191
|
-
role="
|
|
192
|
-
aria-label={
|
|
325
|
+
role="group"
|
|
326
|
+
aria-label={groupLabel()}
|
|
193
327
|
>
|
|
194
328
|
<Show
|
|
195
|
-
when={
|
|
329
|
+
when={highlighter()}
|
|
196
330
|
fallback={
|
|
197
|
-
<pre
|
|
331
|
+
<pre
|
|
332
|
+
class={cn('m-0', small() ? 'px-2 py-1.5' : 'px-3 py-2')}
|
|
333
|
+
style={{ 'line-height': local.lineHeight ?? '1.5' }}
|
|
334
|
+
>
|
|
198
335
|
<code class="font-code text-code">
|
|
199
|
-
<Show when={
|
|
200
|
-
<For each={
|
|
336
|
+
<Show when={perLine()} fallback={local.code.replace(/\n$/, '')}>
|
|
337
|
+
<For each={visibleLines()}>
|
|
201
338
|
{(line, index) => (
|
|
202
|
-
<
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<span class={cn({ 'min-w-0': local.wrap })}>{line || ' '}</span>
|
|
210
|
-
</span>
|
|
339
|
+
<CodeLine
|
|
340
|
+
line={line}
|
|
341
|
+
number={index() + 1}
|
|
342
|
+
numbered={local.showLineNumbers === true}
|
|
343
|
+
mark={local.lineMarks?.[index() + 1]}
|
|
344
|
+
wrap={local.wrap === true}
|
|
345
|
+
/>
|
|
211
346
|
)}
|
|
212
347
|
</For>
|
|
213
348
|
</Show>
|
|
@@ -215,7 +350,31 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
215
350
|
</pre>
|
|
216
351
|
}
|
|
217
352
|
>
|
|
218
|
-
{(highlight) =>
|
|
353
|
+
{(highlight) => (
|
|
354
|
+
<div class={small() ? 'px-2 py-1.5' : 'px-3 py-2'}>
|
|
355
|
+
{highlight()(hiddenLines() > 0 ? visibleLines().join('\n') : local.code)}
|
|
356
|
+
</div>
|
|
357
|
+
)}
|
|
358
|
+
</Show>
|
|
359
|
+
<Show when={truncated()}>
|
|
360
|
+
<div class="flex items-center gap-2 border-t border-border px-3 py-1 text-xs text-muted-foreground">
|
|
361
|
+
<span>
|
|
362
|
+
Showing the first {visibleLines().length.toLocaleString()} of{' '}
|
|
363
|
+
{lines().length.toLocaleString()} lines.
|
|
364
|
+
</span>
|
|
365
|
+
<Button
|
|
366
|
+
variant="ghost"
|
|
367
|
+
size="2xs"
|
|
368
|
+
onClick={() => {
|
|
369
|
+
setShowAll(true)
|
|
370
|
+
// This button leaves the document with the click; the scroller
|
|
371
|
+
// is the nearest place focus can stay, so a keyboard user keeps their place.
|
|
372
|
+
bodyElement?.focus({ preventScroll: true })
|
|
373
|
+
}}
|
|
374
|
+
>
|
|
375
|
+
Show all {lines().length.toLocaleString()} lines
|
|
376
|
+
</Button>
|
|
377
|
+
</div>
|
|
219
378
|
</Show>
|
|
220
379
|
{/*
|
|
221
380
|
In the scroller's box, and a single line: the indicator must not add
|
|
@@ -238,6 +397,77 @@ export function CodeBlock(props: CodeBlockProps) {
|
|
|
238
397
|
)
|
|
239
398
|
}
|
|
240
399
|
|
|
400
|
+
const MARK_GLYPH: Readonly<Record<CodeLineMark, string>> = {
|
|
401
|
+
add: '+',
|
|
402
|
+
remove: '−',
|
|
403
|
+
highlight: '',
|
|
404
|
+
error: '!',
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* One rendered line. The gutter glyph and the element (`ins`/`del`) carry what a
|
|
409
|
+
* mark means so it survives greyscale and a screen reader; both gutters are
|
|
410
|
+
* unselectable so dragging across the block and copying yields only source.
|
|
411
|
+
*/
|
|
412
|
+
function CodeLine(props: {
|
|
413
|
+
line: string
|
|
414
|
+
number: number
|
|
415
|
+
numbered: boolean
|
|
416
|
+
mark?: CodeLineMark
|
|
417
|
+
wrap: boolean
|
|
418
|
+
}) {
|
|
419
|
+
const content = () => (
|
|
420
|
+
<>
|
|
421
|
+
<Show when={props.numbered}>
|
|
422
|
+
<span class="text-right text-muted-foreground select-none" aria-hidden="true">
|
|
423
|
+
{props.number}
|
|
424
|
+
</span>
|
|
425
|
+
</Show>
|
|
426
|
+
<span
|
|
427
|
+
class="w-[1ch] text-center text-muted-foreground select-none"
|
|
428
|
+
aria-hidden="true"
|
|
429
|
+
data-slot="code-line-mark"
|
|
430
|
+
>
|
|
431
|
+
{props.mark ? MARK_GLYPH[props.mark] : ''}
|
|
432
|
+
</span>
|
|
433
|
+
<span class={cn({ 'min-w-0': props.wrap })}>{props.line || ' '}</span>
|
|
434
|
+
</>
|
|
435
|
+
)
|
|
436
|
+
const rowClass = () =>
|
|
437
|
+
cn(
|
|
438
|
+
'grid gap-3 no-underline',
|
|
439
|
+
props.numbered ? 'grid-cols-[3ch_1ch_1fr]' : 'grid-cols-[1ch_1fr]',
|
|
440
|
+
{
|
|
441
|
+
'bg-success-subtle': props.mark === 'add',
|
|
442
|
+
'bg-destructive-subtle': props.mark === 'remove' || props.mark === 'error',
|
|
443
|
+
'bg-primary-subtle': props.mark === 'highlight',
|
|
444
|
+
}
|
|
445
|
+
)
|
|
446
|
+
return (
|
|
447
|
+
<Show
|
|
448
|
+
when={props.mark === 'add' || props.mark === 'remove'}
|
|
449
|
+
fallback={
|
|
450
|
+
<span data-mark={props.mark} class={rowClass()}>
|
|
451
|
+
{content()}
|
|
452
|
+
</span>
|
|
453
|
+
}
|
|
454
|
+
>
|
|
455
|
+
<Show
|
|
456
|
+
when={props.mark === 'add'}
|
|
457
|
+
fallback={
|
|
458
|
+
<del data-mark="remove" class={rowClass()}>
|
|
459
|
+
{content()}
|
|
460
|
+
</del>
|
|
461
|
+
}
|
|
462
|
+
>
|
|
463
|
+
<ins data-mark="add" class={rowClass()}>
|
|
464
|
+
{content()}
|
|
465
|
+
</ins>
|
|
466
|
+
</Show>
|
|
467
|
+
</Show>
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
|
|
241
471
|
/**
|
|
242
472
|
* InlineCode.
|
|
243
473
|
*
|
|
@@ -1 +1,9 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
CODE_BLOCK_LINE_LIMIT,
|
|
3
|
+
CodeBlock,
|
|
4
|
+
InlineCode,
|
|
5
|
+
TALL_CODE_BLOCK_PX,
|
|
6
|
+
type CodeBlockProps,
|
|
7
|
+
type CodeHighlighter,
|
|
8
|
+
type CodeLineMark,
|
|
9
|
+
} from './code-block'
|
|
@@ -2,10 +2,9 @@ import { createEffect, createSignal, type JSX } from 'solid-js'
|
|
|
2
2
|
import { FormField } from './field'
|
|
3
3
|
import { Input } from '../input/input'
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type NumberFieldBaseProps = {
|
|
6
6
|
label: string
|
|
7
7
|
hint?: string
|
|
8
|
-
value: number
|
|
9
8
|
min: number
|
|
10
9
|
max: number
|
|
11
10
|
/**
|
|
@@ -23,20 +22,44 @@ export type NumberFieldProps = {
|
|
|
23
22
|
* `integer={false}`, and `min={0.5} step={1}` accepts 0.5, 1.5, 2.5.
|
|
24
23
|
*/
|
|
25
24
|
integer?: boolean
|
|
26
|
-
|
|
25
|
+
/** Locks the input; a locked field keeps its value and reports nothing. */
|
|
26
|
+
disabled?: boolean
|
|
27
27
|
class?: string
|
|
28
28
|
onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent>
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
export type NumberFieldProps = NumberFieldBaseProps &
|
|
32
|
+
(
|
|
33
|
+
| {
|
|
34
|
+
optional?: false
|
|
35
|
+
value: number
|
|
36
|
+
onChange: (value: number) => void
|
|
37
|
+
}
|
|
38
|
+
| {
|
|
39
|
+
/**
|
|
40
|
+
* Lets the field be left blank: a blank field is valid and reports `null`,
|
|
41
|
+
* and a `null` value shows a blank field. Use it for a limit that falls
|
|
42
|
+
* back to a default when unset, so a caller never maps `''` to
|
|
43
|
+
* `undefined` of its own.
|
|
44
|
+
*/
|
|
45
|
+
optional: true
|
|
46
|
+
value: number | null
|
|
47
|
+
onChange: (value: number | null) => void
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
const text = (value: number | null) => (value === null ? '' : String(value))
|
|
52
|
+
|
|
31
53
|
/**
|
|
32
54
|
* A controlled numeric field that keeps an editable draft while validating
|
|
33
55
|
* range, integer and step constraints. Invalid drafts are announced and restored
|
|
34
56
|
* to the latest controlled value when focus leaves the input, so `onChange`
|
|
35
57
|
* only ever receives a value the field accepts — a caller never needs a
|
|
36
|
-
* `Number(value) || fallback` of its own.
|
|
58
|
+
* `Number(value) || fallback` of its own. With `optional`, blank is accepted and
|
|
59
|
+
* reported as `null`.
|
|
37
60
|
*/
|
|
38
61
|
export function NumberField(props: NumberFieldProps) {
|
|
39
|
-
const [draft, setDraft] = createSignal(
|
|
62
|
+
const [draft, setDraft] = createSignal(text(props.value))
|
|
40
63
|
const [error, setError] = createSignal('')
|
|
41
64
|
// Whole numbers only when nothing on the grid is fractional: a whole step from
|
|
42
65
|
// a fractional `min` (0.5, 1.5, 2.5) puts the spinner's own values off the
|
|
@@ -46,11 +69,15 @@ export function NumberField(props: NumberFieldProps) {
|
|
|
46
69
|
(props.step === undefined || (Number.isInteger(props.step) && Number.isInteger(props.min)))
|
|
47
70
|
|
|
48
71
|
createEffect(() => {
|
|
49
|
-
setDraft(
|
|
72
|
+
setDraft(text(props.value))
|
|
50
73
|
})
|
|
51
74
|
|
|
52
|
-
|
|
53
|
-
|
|
75
|
+
// A number input reports '' both when it is empty and when it holds text it cannot parse
|
|
76
|
+
// ("abc", "-", "1e"); only `validity.badInput` tells them apart, and a bad draft must never
|
|
77
|
+
// count as blank (it would report `null` and clear the limit).
|
|
78
|
+
const validate = (raw: string, badInput: boolean) => {
|
|
79
|
+
if (badInput) return `${props.label} must be a valid number.`
|
|
80
|
+
if (!raw) return props.optional ? '' : `${props.label} is required.`
|
|
54
81
|
const next = Number(raw)
|
|
55
82
|
if (!Number.isFinite(next)) return `${props.label} must be a valid number.`
|
|
56
83
|
if (integer() && !Number.isInteger(next)) {
|
|
@@ -80,19 +107,29 @@ export function NumberField(props: NumberFieldProps) {
|
|
|
80
107
|
min={props.min}
|
|
81
108
|
max={props.max}
|
|
82
109
|
step={props.step ?? (integer() ? 1 : 'any')}
|
|
83
|
-
required
|
|
110
|
+
required={!props.optional}
|
|
111
|
+
disabled={props.disabled}
|
|
84
112
|
onInput={(event) => {
|
|
85
113
|
const raw = event.currentTarget.value
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
// Read before touching the draft: writing '' back to the input would clear the entry and
|
|
115
|
+
// with it `badInput`. An unparsable entry keeps the last draft and the text on screen, so
|
|
116
|
+
// the user can correct it; blur restores the last good value.
|
|
117
|
+
const badInput = event.currentTarget.validity.badInput
|
|
118
|
+
if (!badInput) setDraft(raw)
|
|
119
|
+
const nextError = validate(raw, badInput)
|
|
88
120
|
setError(nextError)
|
|
89
|
-
if (
|
|
121
|
+
if (nextError) return
|
|
122
|
+
// `optional` narrows the callback to `number | null`; a required field never sees `''`.
|
|
123
|
+
;(props.onChange as (value: number | null) => void)(raw ? Number(raw) : null)
|
|
90
124
|
}}
|
|
91
125
|
onBlur={(event) => {
|
|
92
|
-
const nextError = validate(draft())
|
|
126
|
+
const nextError = validate(draft(), event.currentTarget.validity.badInput)
|
|
93
127
|
if (nextError) {
|
|
94
|
-
setDraft(
|
|
128
|
+
setDraft(text(props.value))
|
|
95
129
|
setError('')
|
|
130
|
+
// The draft of an unparsable entry is '' and so is the restored blank value: the signal
|
|
131
|
+
// does not change, so the DOM has to be reset by hand to drop the leftover text.
|
|
132
|
+
event.currentTarget.value = text(props.value)
|
|
96
133
|
}
|
|
97
134
|
props.onBlur?.(event)
|
|
98
135
|
}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Marker, markerVariants, type MarkerProps } from './marker'
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Show, splitProps, type ComponentProps, type JSX } from 'solid-js'
|
|
2
|
+
import { cn } from '#lib/utils'
|
|
3
|
+
import { cva, type VariantProps } from '#lib/variants'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Marker.
|
|
7
|
+
*
|
|
8
|
+
* A note or divider *between* turns: a day change, a reconnect, a cancelled run,
|
|
9
|
+
* an event the transcript does not recognise. It is deliberately the quietest
|
|
10
|
+
* element in the column — a hairline with a label — because the transcript has
|
|
11
|
+
* dozens of these and any one that shouts teaches the reader to stop looking.
|
|
12
|
+
*
|
|
13
|
+
* `variant="rule"` draws the hairline either side (a boundary: "Today",
|
|
14
|
+
* "Reconnected"); `variant="note"` is a bare line of text with its mark (an
|
|
15
|
+
* observation that sits inside the flow). `tone` colours the mark and label and
|
|
16
|
+
* is never the only signal — the `label` always says it in words.
|
|
17
|
+
*
|
|
18
|
+
* A marker is static by default. Pass `live` for one that reports a change the
|
|
19
|
+
* reader must not miss (connection lost): it becomes a status region (`polite`)
|
|
20
|
+
* or an alert (`assertive`). A divider is not an ARIA separator, because
|
|
21
|
+
* `separator` is defined to carry no content.
|
|
22
|
+
*/
|
|
23
|
+
export const markerVariants = cva('flex min-w-0 items-center gap-3 text-xs', {
|
|
24
|
+
variants: {
|
|
25
|
+
tone: {
|
|
26
|
+
neutral: 'text-muted-foreground',
|
|
27
|
+
info: 'text-info',
|
|
28
|
+
success: 'text-success',
|
|
29
|
+
warning: 'text-warning',
|
|
30
|
+
danger: 'text-destructive',
|
|
31
|
+
},
|
|
32
|
+
variant: {
|
|
33
|
+
rule: 'w-full',
|
|
34
|
+
note: 'w-full justify-start',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: { tone: 'neutral', variant: 'rule' },
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
export type MarkerProps = Omit<ComponentProps<'div'>, 'children'> &
|
|
41
|
+
VariantProps<typeof markerVariants> & {
|
|
42
|
+
label: JSX.Element
|
|
43
|
+
icon?: JSX.Element
|
|
44
|
+
/** Secondary text after the label: a time, a count. */
|
|
45
|
+
description?: JSX.Element
|
|
46
|
+
/** A control that belongs to the note: Retry, Reconnect. */
|
|
47
|
+
action?: JSX.Element
|
|
48
|
+
live?: 'polite' | 'assertive'
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function Marker(props: MarkerProps) {
|
|
52
|
+
const [local, rest] = splitProps(props, [
|
|
53
|
+
'class',
|
|
54
|
+
'tone',
|
|
55
|
+
'variant',
|
|
56
|
+
'label',
|
|
57
|
+
'icon',
|
|
58
|
+
'description',
|
|
59
|
+
'action',
|
|
60
|
+
'live',
|
|
61
|
+
])
|
|
62
|
+
const rule = () => (local.variant ?? 'rule') === 'rule'
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
data-slot="marker"
|
|
66
|
+
role={local.live === 'assertive' ? 'alert' : local.live === 'polite' ? 'status' : undefined}
|
|
67
|
+
class={cn(markerVariants({ tone: local.tone, variant: local.variant }), local.class)}
|
|
68
|
+
{...rest}
|
|
69
|
+
>
|
|
70
|
+
<Show when={rule()}>
|
|
71
|
+
<span aria-hidden="true" class="h-px min-w-4 flex-1 bg-border" />
|
|
72
|
+
</Show>
|
|
73
|
+
<span class="flex min-w-0 items-center gap-1.5">
|
|
74
|
+
<Show when={local.icon}>
|
|
75
|
+
<span aria-hidden="true" class="grid shrink-0 place-items-center [&_svg]:size-3.5">
|
|
76
|
+
{local.icon}
|
|
77
|
+
</span>
|
|
78
|
+
</Show>
|
|
79
|
+
<span class="font-medium [overflow-wrap:anywhere]">{local.label}</span>
|
|
80
|
+
<Show when={local.description}>
|
|
81
|
+
<span class="text-muted-foreground [overflow-wrap:anywhere]">{local.description}</span>
|
|
82
|
+
</Show>
|
|
83
|
+
<Show when={local.action}>{local.action}</Show>
|
|
84
|
+
</span>
|
|
85
|
+
<Show when={rule()}>
|
|
86
|
+
<span aria-hidden="true" class="h-px min-w-4 flex-1 bg-border" />
|
|
87
|
+
</Show>
|
|
88
|
+
</div>
|
|
89
|
+
)
|
|
90
|
+
}
|