@runtypelabs/persona 1.40.0 → 1.41.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/README.md +151 -0
- package/dist/index.cjs +26 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +211 -3
- package/dist/index.d.ts +211 -3
- package/dist/index.global.js +51 -51
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +28 -28
- package/dist/index.js.map +1 -1
- package/dist/widget.css +7 -0
- package/package.json +1 -1
- package/src/components/composer-builder.ts +1 -1
- package/src/components/message-bubble.ts +63 -8
- package/src/index.ts +14 -3
- package/src/plugins/types.ts +38 -1
- package/src/styles/widget.css +7 -0
- package/src/types.ts +163 -0
- package/src/ui.ts +172 -44
- package/src/utils/morph.ts +3 -1
package/README.md
CHANGED
|
@@ -568,6 +568,157 @@ type AgentWidgetMessageActionsConfig = {
|
|
|
568
568
|
- **Copy button**: Shows a checkmark briefly after successful copy
|
|
569
569
|
- **Vote buttons**: Toggle active state and are mutually exclusive (upvoting clears downvote and vice versa)
|
|
570
570
|
|
|
571
|
+
### Loading & Idle Indicators
|
|
572
|
+
|
|
573
|
+
The widget displays visual indicators during different states of the conversation:
|
|
574
|
+
|
|
575
|
+
- **Loading indicator**: Shown while waiting for a response (standalone) or when an assistant message is streaming but has no content yet (inline)
|
|
576
|
+
- **Idle indicator**: Shown when the widget is idle (not streaming) and has at least one message - useful for showing the assistant is "waiting" for user input
|
|
577
|
+
|
|
578
|
+
#### Configuration
|
|
579
|
+
|
|
580
|
+
```ts
|
|
581
|
+
const controller = initAgentWidget({
|
|
582
|
+
target: '#app',
|
|
583
|
+
config: {
|
|
584
|
+
apiUrl: '/api/chat/dispatch',
|
|
585
|
+
|
|
586
|
+
loadingIndicator: {
|
|
587
|
+
// Show/hide bubble styling around standalone indicator (default: true)
|
|
588
|
+
showBubble: false,
|
|
589
|
+
|
|
590
|
+
// Custom loading indicator renderer
|
|
591
|
+
render: ({ location, config, defaultRenderer }) => {
|
|
592
|
+
// location: 'standalone' (separate bubble) or 'inline' (inside message)
|
|
593
|
+
if (location === 'standalone') {
|
|
594
|
+
const el = document.createElement('div');
|
|
595
|
+
el.innerHTML = '<svg class="spinner">...</svg>';
|
|
596
|
+
el.setAttribute('data-preserve-animation', 'true');
|
|
597
|
+
return el;
|
|
598
|
+
}
|
|
599
|
+
// Use default 3-dot bouncing indicator for inline
|
|
600
|
+
return defaultRenderer();
|
|
601
|
+
},
|
|
602
|
+
|
|
603
|
+
// Custom idle state indicator (shown after response completes)
|
|
604
|
+
renderIdle: ({ lastMessage, messageCount, config }) => {
|
|
605
|
+
// Only show after assistant messages
|
|
606
|
+
if (lastMessage?.role !== 'assistant') return null;
|
|
607
|
+
|
|
608
|
+
const el = document.createElement('div');
|
|
609
|
+
el.textContent = 'What would you like to do next?';
|
|
610
|
+
el.setAttribute('data-preserve-animation', 'true');
|
|
611
|
+
return el;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
});
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
#### Indicator Locations
|
|
619
|
+
|
|
620
|
+
| Location | When Shown | Description |
|
|
621
|
+
|----------|------------|-------------|
|
|
622
|
+
| `standalone` | Waiting for stream to start | Separate bubble shown after user sends a message |
|
|
623
|
+
| `inline` | Streaming with empty content | Inside the assistant message bubble |
|
|
624
|
+
| `idle` | Not streaming, has messages | After assistant finishes responding |
|
|
625
|
+
|
|
626
|
+
#### Animation Preservation
|
|
627
|
+
|
|
628
|
+
When using custom animated indicators, add the `data-preserve-animation="true"` attribute to prevent the DOM morpher from interrupting CSS animations during updates:
|
|
629
|
+
|
|
630
|
+
```ts
|
|
631
|
+
render: () => {
|
|
632
|
+
const el = document.createElement('div');
|
|
633
|
+
el.setAttribute('data-preserve-animation', 'true');
|
|
634
|
+
el.innerHTML = `
|
|
635
|
+
<style>
|
|
636
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
637
|
+
.spinner { animation: spin 1s linear infinite; }
|
|
638
|
+
</style>
|
|
639
|
+
<div class="spinner">⟳</div>
|
|
640
|
+
`;
|
|
641
|
+
return el;
|
|
642
|
+
}
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
#### Hiding Indicators
|
|
646
|
+
|
|
647
|
+
Return `null` from any render function to hide that indicator:
|
|
648
|
+
|
|
649
|
+
```ts
|
|
650
|
+
loadingIndicator: {
|
|
651
|
+
// Hide loading indicator entirely
|
|
652
|
+
render: () => null,
|
|
653
|
+
|
|
654
|
+
// Hide idle indicator (default behavior)
|
|
655
|
+
renderIdle: () => null
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
#### Using Plugins
|
|
660
|
+
|
|
661
|
+
You can also customize indicators via plugins, which take priority over config:
|
|
662
|
+
|
|
663
|
+
```ts
|
|
664
|
+
const customIndicatorPlugin = {
|
|
665
|
+
id: 'custom-indicators',
|
|
666
|
+
|
|
667
|
+
renderLoadingIndicator: ({ location, defaultRenderer }) => {
|
|
668
|
+
if (location === 'standalone') {
|
|
669
|
+
return createCustomSpinner();
|
|
670
|
+
}
|
|
671
|
+
return defaultRenderer();
|
|
672
|
+
},
|
|
673
|
+
|
|
674
|
+
renderIdleIndicator: ({ lastMessage, messageCount }) => {
|
|
675
|
+
if (messageCount === 0) return null;
|
|
676
|
+
if (lastMessage?.role !== 'assistant') return null;
|
|
677
|
+
return createIdleAnimation();
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
initAgentWidget({
|
|
682
|
+
target: '#app',
|
|
683
|
+
config: {
|
|
684
|
+
plugins: [customIndicatorPlugin]
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
#### Type Definitions
|
|
690
|
+
|
|
691
|
+
```typescript
|
|
692
|
+
// Loading indicator context
|
|
693
|
+
type LoadingIndicatorRenderContext = {
|
|
694
|
+
config: AgentWidgetConfig;
|
|
695
|
+
streaming: boolean;
|
|
696
|
+
location: 'inline' | 'standalone';
|
|
697
|
+
defaultRenderer: () => HTMLElement;
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
// Idle indicator context
|
|
701
|
+
type IdleIndicatorRenderContext = {
|
|
702
|
+
config: AgentWidgetConfig;
|
|
703
|
+
lastMessage: AgentWidgetMessage | undefined;
|
|
704
|
+
messageCount: number;
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
// Configuration
|
|
708
|
+
type AgentWidgetLoadingIndicatorConfig = {
|
|
709
|
+
showBubble?: boolean;
|
|
710
|
+
render?: (context: LoadingIndicatorRenderContext) => HTMLElement | null;
|
|
711
|
+
renderIdle?: (context: IdleIndicatorRenderContext) => HTMLElement | null;
|
|
712
|
+
};
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
#### Priority Chain
|
|
716
|
+
|
|
717
|
+
Indicators are resolved in this order:
|
|
718
|
+
1. **Plugin hook** (`renderLoadingIndicator` / `renderIdleIndicator`)
|
|
719
|
+
2. **Config function** (`loadingIndicator.render` / `loadingIndicator.renderIdle`)
|
|
720
|
+
3. **Default** (3-dot bouncing animation for loading, `null` for idle)
|
|
721
|
+
|
|
571
722
|
### Runtype adapter
|
|
572
723
|
|
|
573
724
|
This package ships with a Runtype adapter by default. The proxy handles all flow configuration, keeping the client lightweight and flexible.
|